Firewall Egress Filtering

I plan to implement Port and ICMP filtering outbound from the SANS Institute recommendations here on my Home network.

Currently running 18.06.1 on an EdgeRouter Lite 3

  1. Does anyone have an example of how to configure egress filtering of ports like RPC 137, SMB 445 for IPv4 and IPv6?

  2. Anyone know why this isn't turned on by default?

  3. Any downsides for a home network?

I can't speak to why they are or aren't blocked by default (other than blocking most of the Microsoft-related protocols would break file sharing, which many users seem to like to run on their routers).

I personally block the Microsoft-related protocols (and a few more) on ingress to my router, especially as most of it is on-link "noise" to me. I also am very selective about what ICMP I allow in and out, again dropping everything I don't explicitly allow on ingress and on egress.

Some of the other things I "silently" block, as otherwise my logs overflow (not a complete list) also include all Microsoft-related protocols, various application "phone home", IGMP, mDNS, Dropbox discovery, UPnP, and a few IoT discovery protocols.

Implementing your personal list shouldn't be too difficult with LuCI or direct configuration of your OpenWrt firewall rules.

You could create some iptables rules manually; the UCI/LuCI interface does not offer direct control over the zone_wan_output chain. You can put custom iptables rules in /etc/firewall.user.

Here is an example which should inhibit port 445:
iptables -I zone_wan_output -p tcp -m tcp --dport 445 -j DROP

No.

No. SMB traffic does not need to leave the home LAN for the Internet.

If I'm not wrong, "zone_lan_forward" handles the traffic flow from internal to external, while "zone_wan_output" is only for router to external.

OpenWRT's fw3 design has helpfully created a custom chain called "forwarding_lan_rule" for your case. Hence custom filtering rules can be appended there in the order that you like. Example for SANS egress rules:

iptables -A forwarding_lan_rule -s 192.168.0.0/24 -p tcp --dport 135 -j reject
iptables -A forwarding_lan_rule -s 192.168.0.0/24 -p udp --dport 135 -j reject
iptables -A forwarding_lan_rule -s 192.168.0.0/24 -p tcp --match multiport --dports 137:139 -j reject
iptables -A forwarding_lan_rule -s 192.168.0.0/24 -p udp --match multiport --dports 137:139 -j reject
iptables -A forwarding_lan_rule -s 192.168.0.0/24 -p tcp --dport 445 -j reject
iptables -A forwarding_lan_rule -s 192.168.0.0/24 -p udp --dport 445 -j reject

By way of a stanza in /etc/config/firewall

config rule
	option name 'Block-Outbound-SMB'
	option enabled '0'
	option src 'lan'
	option dest 'wan'
	option dest_port '135 137 138 139 445'
	option proto 'tcpudp'
	option family 'any'
	option target 'REJECT'
1 Like

Almost. The flow through iptables can take a while to grasp. "zone_wan_output" does not necessarily refer to traffic generated by the router. Rather, it is the final chain before handoff to the next hop. All traffic exiting the router's WAN interface, regardless of its origin, will go through the "zone_wan_output" chain.

Dropping SMB traffic during the LAN-WAN forwarding will work, but only for traffic from a single LAN zone. In contrast, dropping SMB traffic in the "zone_wan_output" chain will drop all outbound SMB traffic, no matter where it came from, e.g. VPN zone, second LAN zone, and more.

Either approach will work. The only difference is, one approach will drop outbound SMB traffic from a single zone. The other approach will drop outbound SMB traffic from all zones.

@iplaywithtoys

Does this mean your method will ensure that my guest network on a separate VLAN will have the same egress rules applied?

I haven't built it yet but that will be another thread :wink:

That's the idea. Assuming you want to block specific traffic regardless of source, then applying the DROP at the furthest point in the traffic flow allows for more scope, e.g. additional VLANs.

I tried what you suggested:

iptables -I zone_wan_output -p tcp --match multiport --dports 80,443 -j reject

Unfortunately this doesn't block any traffic behind the router, just egress from the router itself:

root@router:~# telnet www.google.com 80
telnet: can't connect to remote host (172.217.27.100): Connection refused

root@ubuntu:~#$ telnet -4 www.google.com 80
Trying 172.217.27.100...
Connected to www.google.com.
Escape character is '^]'.

I'm not sure if my rules are correct.

This above is a much cleaner and easier to read way of adding SANS' egress filtering rules.

Hmm. That's odd. I might need to revisit my work; I could have made a mistake. I've had a heavy cold all day so I've not always been thinking straight. I'll take another look in the morning, along with some aspirin.

Take care of your self.

For @Dr_Fambo, if you're planning on adding custom rules manually instead of using /etc/config/firewall, the right chain to insert are those referred to on comments as "Custom rule". Those are the Type: User" chain in the following table:

https://wiki.openwrt.org/doc/uci/firewall#packet_flow


config defaults
	option syn_flood '1'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'

config zone
	option name 'lan'
	list network 'lan'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'

config zone
	option name 'wan'
	list network 'wan'
	list network 'wan6'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'

config forwarding
	option src 'lan'
	option dest 'wan'

config rule
	option name 'Allow-DHCP-Renew'
	option src 'wan'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option src_ip 'fc00::/6'
	option dest_ip 'fc00::/6'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-IPSec-ESP'
	option src 'wan'
	option dest 'lan'
	option proto 'esp'
	option target 'ACCEPT'

config rule
	option name 'Allow-ISAKMP'
	option src 'wan'
	option dest 'lan'
	option dest_port '500'
	option proto 'udp'
	option target 'ACCEPT'

config rule
	option name 'Block-Outbound-TFTP'
	option enabled '0'
	option src 'lan'
	option dest 'wan'
	option dest_port '69'
	option proto 'udp'
	option family 'any'
	option target 'REJECT'

config rule
	option name 'Block-Outbound-Syslog'
	option enabled '0'
	option src 'lan'
	option dest 'wan'
	option dest_port '514'
	option proto 'udp'
	option family 'any'
	option target 'REJECT'

config rule
	option name 'Block-Outbound-SNMP'
	option enabled '0'
	option src 'lan'
	option dest 'wan'
	option dest_port '161 162'
	option proto 'udp'
	option family 'any'
	option target 'REJECT'

config rule
	option name 'Block-Outbound-SMB'
	option enabled '0'
	option src 'lan'
	option dest 'wan'
	option dest_port '135 137 138 139 445'
	option proto 'tcpudp'
	option family 'any'
	option target 'REJECT'

config include
	option path '/etc/firewall.user'

config redirect 'adblock_dns_53'
	option name 'Adblock DNS, port 53'
	option src 'lan'
	option proto 'tcp udp'
	option src_dport '53'
	option dest_port '53'
	option target 'DNAT'

config redirect 'adblock_dns_853'
	option name 'Adblock DNS, port 853'
	option src 'lan'
	option proto 'tcp udp'
	option src_dport '853'
	option dest_port '853'
	option target 'DNAT'

config redirect 'adblock_dns_5353'
	option name 'Adblock DNS, port 5353'
	option src 'lan'
	option proto 'tcp udp'
	option src_dport '5353'
	option dest_port '5353'
	option target 'DNAT'

config include 'bcp38'
	option type 'script'
	option path '/usr/lib/bcp38/run.sh'
	option family 'IPv4'
	option reload '1'

New URL: https://openwrt.org/docs/guide-user/firewall/firewall_configuration#packet_flow
The old page is for archival purposes only and does not receive updates any more.

1 Like

Right. It's astounding what a good night's sleep and shaking off a cold can do. I was giving you bad advice yesterday. Apologies for that. It was almost right, but not quite.

You're trying to prevent certain traffic from making the transition from one zone (LAN) to another one (WAN). The chain in question is FORWARD. You can insert a rule at the top of that chain to either DROP or REJECT the traffic you don't want to permit. (DROP will not respond to the source so the source has to time out; REJECT will actively tell the source to go away.)

Today I set up a test enviroment in VMware, which looks like this:

image

On OpenWRT 2 there are three firewall zones, LAN1, LAN2, and WAN, corresponding to the three network segments. I have configured the firewall to permit LAN1 and LAN2 to talk freely with each other, in addition to the default rules permitting outbound traffic.

I tested with ubuntudesktop1 (192.168.11.101) and ubuntudesktop2 (192.168.12.100). I also used my physical perimeter router (192.168.2.1 - on the far side of the cloud, not on the diagram) as a target "somewhere else on the Internet", to demonstrate what happens for connection attempts which go via the WAN.

Without any additional iptables shenanigans:

iplaywithtoys@ubuntudesktop1:~$ ssh 192.168.12.100
iplaywithtoys@192.168.12.100's password:

iplaywithtoys@ubuntudesktop1:~$ ssh admin@192.168.2.1
admin@192.168.2.1's password:
iplaywithtoys@ubuntudesktop2:~$ ssh 192.168.11.101
iplaywithtoys@192.168.11.101's password:

iplaywithtoys@ubuntudesktop2:~$ ssh admin@192.168.2.1
admin@192.168.2.1's password:

I can insert an iptables rule at the top of the FORWARD chain to reject all SSH traffic, regardless of where it's going: root@OpenWrt2:~# iptables -I FORWARD -p tcp -m tcp --dport 22 -j REJECT

Now, if I attempt the same tests as before, here's the result:

iplaywithtoys@ubuntudesktop1:~$ ssh 192.168.12.100
ssh: connect to host 192.168.12.100 port 22: Connection refused

iplaywithtoys@ubuntudesktop1:~$ ssh admin@192.168.2.1
ssh: connect to host 192.168.2.1 port 22: Connection refused
iplaywithtoys@ubuntudesktop2:~$ ssh 192.168.11.101
ssh: connect to host 192.168.11.101 port 22: Connection refused

iplaywithtoys@ubuntudesktop2:~$ ssh admin@192.168.2.1
ssh: connect to host 192.168.2.1 port 22: Connection refused

Let's remove that rule - iptables -D FORWARD -p tcp -m tcp --dport 22 -j REJECT - and replace it with one which rejects all SSH traffic which is destined for the WAN, regardless of its origin. This is done by modifying the iptables directive to include a specific outbound interface: iptables -I FORWARD -o eth1 -p tcp -m tcp --dport 22 -j REJECT

And the results now are:

iplaywithtoys@ubuntudesktop1:~$ ssh 192.168.12.100
iplaywithtoys@192.168.12.100's password:

iplaywithtoys@ubuntudesktop1:~$ ssh admin@192.168.2.1
ssh: connect to host 192.168.2.1 port 22: Connection refused
iplaywithtoys@ubuntudesktop2:~$ ssh 192.168.11.101
iplaywithtoys@192.168.11.101's password:

iplaywithtoys@ubuntudesktop2:~$ ssh admin@192.168.2.1
ssh: connect to host 192.168.2.1 port 22: Connection refused

This approach allows you to block traffic regardless of source. If you add the appropriate iptables rule to /etc/firewall.user then it will apply regardless of any zones you may add.

As has already been mentioned, you can also achieve similar results by manipulating /etc/config/firewall or even using the GUI.

As another example, I used the GUI to create a rule to block SSH only from lan2:

image

The corresponding entry in /etc/firewall/user is:

config rule
        option enabled '1'
        option proto 'tcp'
        option dest_port '22'
        option name 'Block SSH from lan2'
        option family 'ipv4'
        option src 'lan2'
        option dest 'wan'
        option target 'REJECT'

And the test:

iplaywithtoys@ubuntudesktop1:~$ ssh admin@192.168.2.1
admin@192.168.2.1's password:
iplaywithtoys@ubuntudesktop2:~$ ssh admin@192.168.2.1
ssh: connect to host 192.168.2.1 port 22: Connection refused

The above approach could be taken with any new interfaces: create the interface, create a firewall zone for that interface, configure any inter-zone forwarding, configure custom rules to allow or block certain traffic. But if you never want to allow specific traffic, regardless of how many new interfaces or zones you might add, then just use /etc/firewall.user and an explicit iptables command to insert the drop/reject rule at the top of the FORWARD chain.

Lastly, if you don't care about segregating the two LAN interfaces, you could add them both to the same LAN zone, and just use one set of rules to allow or block traffic to and from the WAN. You could also add new interfaces to the same LAN zone, and have the existing firewall rules automatically take effect.

2 Likes

Here are the rules I have created. None are enabled because I wanted to run it by you guys first. Thanks for all the responses.

Taken from /etc/config/firewall

config rule
        option name 'Block-Egress-SMTP'
        option proto 'tcp'
        option dest_port '25'
        option target 'REJECT'
        option src 'lan'
        option dest 'wan'
config rule
        option name 'Block-Egress-IRC'
        option proto 'tcp'
        option dest_port '6660-6669'
        option target 'REJECT'
        option src 'lan'
        option dest 'wan'
config rule
        option target 'REJECT'
        option name 'Block-Egress-SMB'
        option dest_port '135 137-139'
        option src 'lan'
        option dest 'wan'
config rule
        option name 'Block-Egress-TFTP'
        option proto 'udp'
        option dest_port '69'
        option target 'REJECT'
        option src 'lan'
        option dest 'wan'
config rule
        option target 'REJECT'
        option proto 'udp'
        option name 'Block-Egress-Syslog'
        option dest_port '514'
        option src 'lan'
        option dest 'wan'
config rule
        option name 'Block-Egress-SNMP'
        option proto 'udp'
        option target 'REJECT'
        option dest_port '161-162'
        option src 'lan'
        option dest 'wan'

To be clear, when I add a guest Wi-Fi only VLAN later, these rules will apply as well?

On a side note I decided against implementing the ICMP blocks on IPv4 and v6 because it might not be worth it on a home network.

Depends what zone you add the Wi-Fi network to. Those rules target traffic moving from the LAN to WAN zones. If your new Wi-Fi network belongs to one of those zones, then those rules should apply.