Using nft to manually control nftables in OpenWRT 22.03

Hi everyone,
I have a project in mind, involving an OpenWRT router, an Ubuntu server, and a IPTV decoder.
In this point of the development of the project, I'm having issues with nftables.

I installed nftables in my Comtrend AR-5387un router, with OpenWRT 22.03.
I configured table + chain + rule, in order to drop a stream of packets, all of them having the following unique characteristics (corresponding to an IPTV channel):
destination IP address (multicast): 239.0.0.81
destination UDP port: 8208

The nft commands I did:

nft add table bridge kodi
nft add chain bridge kodi channeldrop { type filter hook forward priority filter \; }
nft add rule bridge kodi channeldrop ether type ip ip daddr 239.0.0.81 ip protocol udp udp dport 8208 drop

and the output of the command nft list ruleset :

table inet fw4 {
	chain input {
		type filter hook input priority filter; policy accept;
		iifname "lo" accept comment "!fw4: Accept traffic from loopback"
		ct state established,related accept comment "!fw4: Allow inbound established and related flows"
		tcp flags syn / fin,syn,rst,ack jump syn_flood comment "!fw4: Rate limit TCP syn packets"
		iifname "br-lan" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
		iifname "br-lan" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
		jump handle_reject
	}

	chain output {
		type filter hook output priority filter; policy accept;
		oifname "lo" accept comment "!fw4: Accept traffic towards loopback"
		ct state established,related accept comment "!fw4: Allow outbound established and related flows"
		oifname "br-lan" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic"
	}

	chain prerouting {
		type filter hook prerouting priority filter; policy accept;
		iifname "br-lan" jump helper_lan comment "!fw4: Handle lan IPv4/IPv6 helper assignment"
	}

	chain handle_reject {
		meta l4proto tcp reject with tcp reset comment "!fw4: Reject TCP traffic"
		reject comment "!fw4: Reject any other traffic"
	}

	chain syn_flood {
		limit rate 25/second burst 50 packets return comment "!fw4: Accept SYN packets below rate-limit"
		drop comment "!fw4: Drop excess packets"
	}

	chain input_lan {
		jump accept_from_lan
	}

	chain output_lan {
		jump accept_to_lan
	}

	chain forward_lan {
		jump accept_to_wan comment "!fw4: Accept lan to wan forwarding"
		jump accept_to_lan
	}

	chain helper_lan {
	}

	chain accept_from_lan {
		iifname "br-lan" counter packets 124 bytes 8655 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
	}

	chain accept_to_lan {
		oifname "br-lan" counter packets 73 bytes 7528 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
	}

	chain input_wan {
		meta nfproto ipv4 udp dport 68 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCP-Renew"
		icmp type echo-request counter packets 0 bytes 0 accept comment "!fw4: Allow-Ping"
		meta nfproto ipv4 meta l4proto igmp counter packets 0 bytes 0 accept comment "!fw4: Allow-IGMP"
		meta nfproto ipv6 udp dport 546 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCPv6"
		ip6 saddr fe80::/10 icmpv6 type . icmpv6 code { mld-listener-query . no-route, mld-listener-report . no-route, mld-listener-done . no-route, mld2-listener-report . no-route } counter packets 0 bytes 0 accept comment "!fw4: Allow-MLD"
		icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply, nd-router-solicit, nd-router-advert } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
		icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, parameter-problem . admin-prohibited, nd-neighbor-solicit . no-route, nd-neighbor-advert . no-route } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
		jump reject_from_wan
	}

	chain output_wan {
		jump accept_to_wan
	}

	chain forward_wan {
		icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
		icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
		meta l4proto esp counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-IPSec-ESP"
		udp dport 500 counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-ISAKMP"
		jump reject_to_wan
	}

	chain accept_to_wan {
	}

	chain reject_from_wan {
	}

	chain reject_to_wan {
	}

	chain dstnat {
		type nat hook prerouting priority dstnat; policy accept;
	}

	chain srcnat {
		type nat hook postrouting priority srcnat; policy accept;
	}

	chain srcnat_wan {
		meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 wan traffic"
	}

	chain raw_prerouting {
		type filter hook prerouting priority raw; policy accept;
	}

	chain raw_output {
		type filter hook output priority raw; policy accept;
	}

	chain mangle_prerouting {
		type filter hook prerouting priority mangle; policy accept;
	}

	chain mangle_postrouting {
		type filter hook postrouting priority mangle; policy accept;
	}

	chain mangle_input {
		type filter hook input priority mangle; policy accept;
	}

	chain mangle_output {
		type route hook output priority mangle; policy accept;
	}

	chain mangle_forward {
		type filter hook forward priority mangle; policy accept;
	}
}
table bridge kodi {
	chain channeldrop {
		type filter hook forward priority filter; policy accept;
		ip daddr 239.0.0.81 ip protocol udp udp dport 8208 drop
	}
}

The problem is that when I go to the TV to see if the target channel (to drop) is showing up or not, I see it is showing up, as always.

Note: To discover the destination IP address 239.0.0.81 I had to use tcpdump and capture packets with the IPTV channel set to the channel 156. After, I analyzed the packet capture with Wireshark and extracted the technical details of the channel.

Then, my question is, what do I have to do to effecively drop that TV channel? Is there any nftables command to apply the changes made? I searched on several resources in internet.

I also tried to delete the original table (fw4), and tested with only the manually created table (in case there were conflicts between the 2 rules), but I see the channel working too.

I'd also like to know how can I make the changes persistent accross reboots. Whenever I reboot the router, the newly added "kodi" table disappears.

If you can help me I'd appreciate a lot. Thanks

P.S.: If you want to understand what I want to do, and why I need nftables, or just curious about it, check the following link: (I'm the user Free in StackExchange)

You can translate ebtables to nftables rules.
The problem that I see is that you have define the kodi rule, but it is not called anywhere in a forward chain. And I am not sure the syntax you are using is correct. Better take an example from the wiki.

Hi @trendy ,
since I'm not used to iptables or ebtables, I prefer to directly learn nftables.
Regarding the nft commands I did, I think they are ok. I had to try several times with errors until I found the correct commands. Now these commands I posted are processed by nft without warnings or errors.
Thanks anyway.

I'm not sure that you need to add a bridge (layer 2) table here. I'd try just a simple traffic rule in LuCI first (remove or leave the TCP, as you see fit).

Hi @efahl ,
Thanks for your advice.
I have tried to set the rule you suggested (good idea!), but to my surprise, after adding the traffic rule, the TV channel still shows up. I also rebooted and still the same.


Do you know what I'm doing wrong?
Let me send you a capture made with tcpdump, after the rule was created, while the channel in question was being watched.
https://drive.google.com/drive/folders/1DuUNwu5G5vgmMeMgKvDVOBmD7Q0q-sP_?usp=sharing
The command I executed to create the capture6.pcap was:

tcpdump -i br-lan -w /mnt/sda1/tcpdump/capture6.pcap

Thanks

Is all the traffic in your pcap on the LAN? I assume the 224.0.0.0/4 is served on the lan from your kodi/ubuntu server, and the 172.26.0.0/16 is your local devices?

If the kodi server and clients are all connected to the same switch, then they could be evading the firewall altogether (just doing layer 2 switching). You might want to tcpdump -i eth0 (or whatever your wan interface is) and see what the IPTV channel data looks like on the upstream side of your kodi server and try blocking that.

Hi @efahl ,
The address 172.26.76.249 is from internet, the source of the IPTV channels. 239.0.0.81 is a multicast address and doesn't correspond to a device in my LAN.
I am attaching some images to better explain the scenario. MEDIATODECO is the name of my OpenWRT router (192.168.1.10).



Since the packets coming from internet to the IPTV decoder pass through MEDIATODECO only acting as a switch, that is why I created a bridge table in the begginning.
I'm thinking that maybe because of having installed nftables-json, maybe the functionality of the firewall can be affected, and because of that, the firewall rules don't work.
I'm going to restore the OpenWRT system to defaults, and I will try again.
Thanks

There is no WAN interface in the config as far as i can see. Which probably means that you connected both the upstream and the downstream to the switch ports. I might be wrong but i think that firewall rules won't do anything to traffic passing through the switch in your router in this configuration. Probably splitting the network into VLANs may allow you some control over the traffic. Or configuring the router to actually act as a router.

Hi @antonk
As far as I know, the firewall in OpenWRT 22 or higher is based on nftables, and nftables has the "bridge" family, which lets create rules that affect packets passing through the switch. Also I think that if you set Source / Destination zone to "Any zone (forward)" it acts at Layer 2.
Anyway I'm not sure if setting it to Any zone will make the rule to be created in "bridge" family, or how can I use the bridge functionality.
Thanks

Hi again,
Just to let you know that I flashed a new firmware image (I took the opportunity to upgrade to 22.05) and, after setting the firewall rule, the TV channel is still working. I don't know what I did wrong...

Also I'd like to tell you @efahl , My kodi Virtual Machine is not yet deployed. I'm trying to first drop the original channel packets, and after I will try to edit the packets coming from my PC (as a test), to mimic the original channel (changing the source/dest IP, source/dest MAC, and source/dest UPD ports to that of original IPTV channel), so that the IPTV decoder recognizes that stream as if it was the original TV channel, and I can visualize the video stream. And then, when all these networking stuff is ok, I would face the installation of a virtual machine with Kodi on my Ubuntu server.

Thanks

Note that bridge firewall needs a separate table unrelated to fw4 and it requires traffic to reach the bridge, which may not be the case when a hardware switch is involved.

Hi @vgaetera ,
MEDIATODECO is a Comtrend AR-5387un with OpenWRT 22.05
I also tried today substituting MEDIATODECO with another router, it is a TP-Link Archer C7 v5 with OpenWRT 22.05, and I call it MEDIATODECO2.
I still haven't been able to make them work.
Do you know if their hardwares admit the configuration with bridge firewall?
Also, I read the link you gave me "bridge firewall" and I see a complicated set of steps. also they are meant to intercept DNS queries and other things, different to my case.

Can you tell me some clues, or some approach I could do to solve this problem?

Also I want to tell you and others in this topic, that configuring MEDIATODECO to split the LAN into two subnets, and doing routing between them, would surely make it impossible for IPTV decoder to work. The IPTV is made to work in the same subnet that the Main router is working (in the LAN side).

Thanks

You could try bridge firewall as suggested above. For that to work, you will need to create a bridge interface and have the traffic pass through it. Perhaps you could bridge the WAN interface with the LAN and connect your decoder to the physical WAN port. Then configure bridge firewall following the instructions in the wiki.
Edit: looking more closely at the pictures, I see that you have a bridge interface and maybe (?) even it's already bridging WAN and LAN ports. Needs confirmation though.