Replacing firewall service with "own" iptables

Hello community,

I've been trying to understand how actually a router works and what packets have to be forwarded, dropped, accepted, etc.
The default firewall rules worked pretty well for me, so I figured why not use these as a base for own iptable rules.
I have been checking both iptables-save and fw3 print in order to come up with the necessary rules to replicate.

I came up with the following

root@OpenWrt:~/sources# cat /etc/iptables.rules                     
*mangle
-A FORWARD -o eth1.2 -p tcp -m tcp --tcp-flags SYN,RST SYN -m comment --comment "Zone wan MTU fixing" -j TCPMSS --clamp-mss-to-pmtu
COMMIT

*nat
###############################################################################
#                ZONE LAN PREROUTING AND POSTROUTING CHAINS                   #
###############################################################################
#-----------------------------------------------------------------------------+
# chn_zone_lan_prerouting
#----------
# Description:
#   -----
#-----------------------------------------------------------------------------+
-N chn_zone_lan_prerouting
-A chn_zone_lan_prerouting -m comment --comment "Nothing in here at the moment"

#-----------------------------------------------------------------------------+
# chn_zone_lan_postrouting
#----------
# Description:
#   -----
#-----------------------------------------------------------------------------+
-N chn_zone_lan_postrouting
-A chn_zone_lan_postrouting -m comment --comment "Nothing in here at the moment"


###############################################################################
#                ZONE WAN PREROUTING AND POSTROUTING CHAINS                   #
###############################################################################
#-----------------------------------------------------------------------------+
# chn_zone_wan_prerouting
#----------
# Description:
#   -----
#-----------------------------------------------------------------------------+
-N chn_zone_wan_prerouting
-A chn_zone_wan_prerouting -m comment --comment "Nothing in here at the moment"

#-----------------------------------------------------------------------------+
# chn_zone_wan_postrouting
#----------
# Description:
#   Masquerade packets from WAN
#-----------------------------------------------------------------------------+
-N chn_zone_wan_postrouting
-A chn_zone_wan_postrouting -m comment --comment "Masquerade packets from WAN" -j MASQUERADE

-A PREROUTING -i br-lan -j chn_zone_lan_prerouting
-A PREROUTING -i pppoe-wan -j chn_zone_wan_prerouting
-A POSTROUTING -o br-lan -j chn_zone_lan_postrouting
-A POSTROUTING -o pppoe-wan -j chn_zone_wan_postrouting
COMMIT

*filter
###############################################################################
#                             CUSTOM CHAINS                                   #
###############################################################################
#-----------------------------------------------------------------------------+
# chn_syn_flood
#----------
# Description:
#   Check for possible SYN flood and drop the connection if there are more 
#   than 25 SYN packets per second as average or if the threshold of 50 packets
#   per second is reached.
#   Furthermore log any SYN flood
#-----------------------------------------------------------------------------+
-N chn_syn_flood
-A chn_syn_flood -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 25/sec --limit-burst 50 -m comment --comment "Limit SYN packets to 25 packets per second" -j RETURN
-A chn_syn_flood -j LOG --log-prefix "SYN flood: " --log-level 7
-A chn_syn_flood -m comment --comment "Drop SYN flood packets" -j DROP

#-----------------------------------------------------------------------------+
# chn_reject
#----------
# Description:
#   Before rejecting any packets, log them
#   Reject TCP packets with tcp-reset and all others with icmp-port-unreachable
#-----------------------------------------------------------------------------+
-N chn_reject
-A chn_reject -j LOG --log-prefix "rejected connection: " -m limit --limit 2/min --log-level 7
-A chn_reject -p tcp -m comment --comment "Reject TCP packet with TCP reset" -j REJECT --reject-with tcp-reset
-A chn_reject -m comment --comment "Reject non TCP packet with ICMP port unreachable" -j REJECT --reject-with icmp-port-unreachable


###############################################################################
#                            ZONE LAN CHAINS                                  #
###############################################################################
#-----------------------------------------------------------------------------+
# chn_zone_lan_dst_accept
#----------
# Description:
#   Accept any outgoing packet from br-lan
#-----------------------------------------------------------------------------+
-N chn_zone_lan_dst_accept
-A chn_zone_lan_dst_accept -o br-lan -m comment --comment "Accept any outgoing packet from br-lan" -j ACCEPT

#-----------------------------------------------------------------------------+
# chn_zone_lan_src_accept
#----------
# Description:
#   Accept new and untracked packets, which originate from LAN
#-----------------------------------------------------------------------------+
-N chn_zone_lan_src_accept
-A chn_zone_lan_src_accept -i br-lan -m conntrack --ctstate NEW,UNTRACKED -m comment --comment "Accept new and untracked packets, which originate from LAN" -j ACCEPT

#-----------------------------------------------------------------------------+
# chn_zone_wan_dst_accept
#----------
# Description:
#   Prevent NAT leakage if packet has state INVALID, accept everything else
#-----------------------------------------------------------------------------+
-N chn_zone_wan_dst_accept
-A chn_zone_wan_dst_accept -o pppoe-wan -m conntrack --ctstate INVALID -m comment --comment "Prevent NAT leakage" -j DROP
-A chn_zone_wan_dst_accept -o pppoe-wan -m comment --comment "Accept any packet to the outgoing interface" -j ACCEPT

#------------------------------------------------+
# chn_zone_wan_src_reject
#----------
# Description:
#   Simply reject the packets
#------------------------------------------------+
-N chn_zone_wan_src_reject
-A chn_zone_wan_src_reject -i pppoe-wan -m comment --comment "Reject" -j chn_reject

#-----------------------------------------------------------------------------+
# chn_zone_wan_dst_reject
#----------
# Description:
#   Simply reject any packet
#-----------------------------------------------------------------------------+
-N chn_zone_wan_dst_reject
-A chn_zone_wan_dst_reject -o pppoe-wan -m comment --comment "Reject" -j chn_reject

#-----------------------------------------------------------------------------+
# chn_zone_lan_input
#----------
# Description:
#   Accept any traffic from LAN
#-----------------------------------------------------------------------------+
-N chn_zone_lan_input
-A chn_zone_lan_input -m comment --comment "Accept any traffic from LAN" -j chn_zone_lan_src_accept

#-----------------------------------------------------------------------------+
# chn_zone_lan_forward
#----------
# Description:
#   Accept forwarding from LAN to WAN, accept port forwards and accept
#   everything with the destination LAN
#-----------------------------------------------------------------------------+
-N chn_zone_lan_forward
-A chn_zone_lan_forward -m comment --comment "Accept forwarding from LAN to WAN" -j chn_zone_wan_dst_accept
-A chn_zone_lan_forward -m conntrack --ctstate DNAT -m comment --comment "Accept port forwards" -j ACCEPT
-A chn_zone_lan_forward -m comment --comment "Accept" -j chn_zone_lan_dst_accept

#-----------------------------------------------------------------------------+
# chn_zone_lan_output
#----------
# Description:
#   Accept any outgoing packet from br-lan
#-----------------------------------------------------------------------------+
-N chn_zone_lan_output
-A chn_zone_lan_output -m comment --comment "Accept any outgoing packets" -j chn_zone_lan_dst_accept


###############################################################################
#                            ZONE WAN CHAINS                                  #
###############################################################################

#-----------------------------------------------------------------------------+
# chn_zone_wan_input
#----------
# Description:
#   Allow DHCP renew, DNAT and IGMP
#-----------------------------------------------------------------------------+
-N chn_zone_wan_input
-A chn_zone_wan_input -p icmp -m icmp --icmp-type 8 -m comment --comment "Accept Pings" -j ACCEPT
-A chn_zone_wan_input -p udp -m udp --dport 68 -m comment --comment "Allow DHCP renewal" -j ACCEPT
-A chn_zone_wan_input -p igmp -m comment --comment "Allow IGMP" -j ACCEPT
-A chn_zone_wan_input -m conntrack --ctstate DNAT -m comment --comment "Accept port redirections" -j ACCEPT
-A chn_zone_wan_input -m comment --comment "Reject packets" -j chn_zone_wan_src_reject

#-----------------------------------------------------------------------------+
# chn_zone_wan_forward
#----------
# Description:
#   Allow IPSec-ESP, ISAKMP and accept port forwards, reject everything else
#-----------------------------------------------------------------------------+
-N chn_zone_wan_forward
-A chn_zone_wan_forward -p esp -m comment --comment "Allow IPSec-ESP" -j chn_zone_lan_dst_accept
-A chn_zone_wan_forward -p udp -m udp --dport 500 -m comment --comment "Allow ISAKMP" -j chn_zone_lan_dst_accept
-A chn_zone_wan_forward -m conntrack --ctstate DNAT -m comment --comment "Accept port forwards" -j ACCEPT
-A chn_zone_wan_forward -m comment --comment "Reject everything else" -j chn_zone_wan_dst_reject

#-----------------------------------------------------------------------------+
# chn_zone_wan_output
#----------
# Description:
#   Simply accept any packet
#-----------------------------------------------------------------------------+
-N chn_zone_wan_output
-A chn_zone_wan_output -m comment --comment "Accept" -j chn_zone_wan_dst_accept


# Allow all loopback (lo) traffic
-A INPUT -i lo -m comment --comment "Accept traffic on lo" -j ACCEPT

# Keep established and related connections
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "Accept related and established connections" -j ACCEPT

# Check for SYN flood
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "!fw3" -j chn_syn_flood

# Handle incoming LAN packets in chn_zone_lan_input
-A INPUT -i br-lan -m comment --comment "Call chn_zone_lan_input" -j chn_zone_lan_input

# Handle incoming WAN packets in chn_zone_wan_input
-A INPUT -i pppoe-wan -m comment --comment "Call chn_zone_wan_input" -j chn_zone_wan_input

# Allow forwarding of related and established connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "Allow forwarding of related and established connections" -j ACCEPT

# Handle forwarding for LAN in chn_zone_lan_forward
-A FORWARD -i br-lan -m comment --comment "Call chn_zone_lan_forward" -j chn_zone_lan_forward

# Handle forwarding for WAN in chn_zone_wan_forward
-A FORWARD -i pppoe-wan -m comment --comment "!fw3" -j chn_zone_wan_forward

# Reject any other forwardings
-A FORWARD -m comment --comment "Reject any other forwardings" -j chn_reject

# Accept outgoing connections from loopback
-A OUTPUT -o lo -m comment --comment "Accept outgoing loopback traffic" -j ACCEPT

# Accept outgoing related and established connections
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "Allow outgoing of related and established connections" -j ACCEPT

# Handle outgoing traffic for LAN in chn_zone_lan_output
-A OUTPUT -o br-lan -m comment --comment "Call chn_zone_lan_output" -j chn_zone_lan_output

# Handle outgoing traffic for WAN in chn_zone_wan_output
-A OUTPUT -o pppoe-wan -m comment --comment "Call chn_zone_wan_output" -j chn_zone_wan_output

COMMIT

I simply stopped the firewall service (service firewall stop - i know, that I have to disable it, when I want to completely replace the firewall and load my own iptables rules on boot via /etc/rc.local) and did an iptables-restore < /etc/iptables.rules

  • Do I have to something else?
  • Are my rules replicating the "default" configuration properly?
  • Are there any downsides of using iptables over the built-in firewall service, when it comes to performance? I am absolutely aware, that I have to do port forwardings and all that kind of stuff via CLI, but I am fine with that.

Information:
Router: Linksys WRT3200ACM
OS: OpenWrt 18.06.2, r7676-cddd7b4c77

Thank you very much!

Cheers,
Steffen

When generating my custom images, I always omit openwrts firewall, and include my own minimal ipt-rules, to be started from rc.local
Coming from full linux, this makes it easier for me to merge some specialities.
And easier to read, for a linux guy.

Hello reinerotto,

I would do pretty much the same, but I soon realized I am not able to understand how a router (should) work as some connections did not get through, which should have and some services stop to work.
With services I mean for example Netflix.
While writing this post Netflix is not working on my LG TV - using the builtin firewall rules it works again like a charm.

Would you mind pasting your "default" iptable rules?

Thanks!

Cheers,
Steffen

The default is to allow practically everything, and to enable NAT.
But this depends upon the services, to be run.
Minimum:
LAN_IF=br-lan
iptables -F
iptables -X
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
WAN_IF=uci get network.wan.ifname
#Basic protection
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i "$LAN_IF" -j ACCEPT

iptables -I INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --destination-port 22 -j ACCEPT

iptables -t nat -I POSTROUTING -o "$WAN_IF" -j MASQUERADE

Necessary to confirm in sysctl, forwarding of packets to be allowed.

1 Like

if you want to run a fully custom firewall, I strongly suggest to look into nftables. it's the future of Linux firewalls and even iptables is going to be replaced in next Debian with a version that just uses nftables as back end.

I've switched all my firewalls on my Linux machines, and only use openwrt as access points so no firewall there.

3 Likes

As far I know the nftables package is much bigger than firewall.

As far I know the openwrt's firewall is in fact just a command line tool fw3 that generates iptables from uci config /etc/config/firewall. You can call fw3 print to see generated iptables rules.
So yes, you definitely can use iptables instead of firewall.
https://openwrt.org/docs/guide-user/firewall/overview
https://openwrt.org/docs/guide-user/firewall/fw3_configurations/fw3_config_examples
https://openwrt.org/docs/guide-user/firewall/firewall_configuration

Hello reinerotto,

thanks for your answer, this really showed me, that routing is not that complicated (at least for the basic routing stuff).

I came up with the following rules in the meanwhile, which work pretty well for me:

LAN_INTERFACE_NAME="br-lan"
WAN_INTERFACE_NAME="pppoe-wan"

# clear iptable rules
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X

# reset counters
iptables -Z

# set default policies
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

###############################################################################
#                             CUSTOM CHAINS                                   #
###############################################################################
#-----------------------------------------------------------------------------+
# chn_reject
#----------
# Description:
#   Reject TCP packets with tcp-reset and all others with icmp-port-unreachable
#-----------------------------------------------------------------------------+
iptables -N chn_reject
iptables -A chn_reject -p tcp -j REJECT --reject-with tcp-reset
iptables -A chn_reject -j REJECT --reject-with icmp-port-unreachable
###############################################################################
#                           END CUSTOM CHAINS                                 #
###############################################################################


# wan MTU fixing
iptables -t mangle -A FORWARD -o "${WAN_INTERFACE_NAME}" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

# masquerade outgoing packets to WAN
iptables -t nat -A POSTROUTING -o "${WAN_INTERFACE_NAME}" -j MASQUERADE


# Allow all loopback (lo) traffic
iptables -A INPUT -i lo -j ACCEPT

# Allow all traffic from br-lan
iptables -A INPUT -i "${LAN_INTERFACE_NAME}" -j ACCEPT

# Allow everything from the modem
iptables -A INPUT -s 10.1.1.2/32 -j ACCEPT

# Allow ICMP
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
iptables -A FORWARD -p icmp --icmp-type 8 -j ACCEPT

# Keep established and related connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow traffic on br-lan
iptables -A INPUT -i "${LAN_INTERFACE_NAME}" -j ACCEPT

# Allow all forwardings from LAN to WAN
iptables -A FORWARD -i "${LAN_INTERFACE_NAME}" -o "${WAN_INTERFACE_NAME}" -j ACCEPT

# Allow forwardings from WAN to LAN for established and related connections aswell as for DNAT
iptables -A FORWARD -i "${WAN_INTERFACE_NAME}" -o "${LAN_INTERFACE_NAME}" -m conntrack --ctstate ESTABLISHED,RELATED,DNAT -j ACCEPT

# Log any packets which don't fit the rules above
iptables -A INPUT -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 7
iptables -A FORWARD -j LOG --log-prefix "iptables_FORWARD_denied: " --log-level 7

# and then reject them
iptables -A INPUT -j chn_reject
iptables -A FORWARD -j chn_reject

# accept all outgoing packets
iptables -A OUTPUT -j ACCEPT

Just for anybody might stumble upon this topic some day:
iptables-save -c (as iptables -vL is not present in OpenWrt) helped me big time to understand which rules have to be placed in front. With -c you can show how often a rule actually got matched and I had quite a bunch of rules, which didn't match anything at all, but would still slow down the routing process as iptables are evaluated from top to bottom (so any rule was basically evaluated until the DROP came in). I don't think this made a huge performance issue on this small amount of rules, however when you have thousands of rules in place, I think iptables-save -c can come in pretty handy.

Thanks a lot for your answers, guys - I really appreciate it.

Cheers,
Steffen

1 Like

Hello dlakelan,

I've taken a brief look into nftables - I will surely consider it in the next few weeks, but for now iptables are my (somewhat) comfort zone and I first want to try and accomplish a decent routing with them.

Thanks for your advice however! :slight_smile:

Cheers,
Steffen

1 Like

Hello stokito,

as far as I understood it in the meanwhile, that is exactly what happens and therefore answers my initial question whether its preferable to use iptables or the uci cli. Turns out, it doesn't matter at all :slight_smile:

Cheers,
Steffen

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.