1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Optimizing IPTABLES (on FORWARD chain)

Discussion in 'Tomato Firmware' started by phuque99, Feb 9, 2011.

  1. phuque99

    phuque99 LI Guru Member

    @Toastman: I'm not sure if this is the appropriate thread to discuss this, but you're the only person I know that has a comprehensive iptables customization in your residential routers.

    I've been reviewing my own iptables rule list again (I know that could be eccentric), and I found an interesting article: http://www.dd-wrt.com/phpBB2/viewtopic.php?t=69050

    This person claimed that moving the existing RELATED,ESTABLISHED rule above any FORWARD chain rules could speed up his connection. I believe that logic is sound, since established connections, shouldn't be made to go down the entire iptables again.

    My firewall rules (shortened for simplicity) are to allow only a specific set of CIDR ranges to access various port. Simple example of allowing 10.0.x.x and 10.1.x.x from WAN to SSH port, denying everything else:

    Code:
    iptables -I FORWARD -p tcp -d 192.168.1.10 --dport 22 -j DROP
    iptables -I FORWARD -p tcp -s 10.0.0.0/24 -d 192.168.1.10 --dport 22 -m state --state NEW -j ACCEPT
    iptables -I FORWARD -p tcp -s 10.1.0.0/24 -d 192.168.1.10 --dport 22 -m state --state NEW -j ACCEPT
    iptables -I FORWARD -p tcp -d 192.168.1.10 --dport 21 -m state --state RELATED,ESTABLISHED -j ACCEPT
    The resulting FORWARD table would look something like this:

    Code:
    iptables -vnL
    Chain FORWARD (policy DROP 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.1.10        tcp dpt:22 state RELATED,ESTABLISHED 
        0     0 ACCEPT     tcp  --  *      *       10.1.0.0/24          192.168.1.10        tcp dpt:22 state NEW
        0     0 ACCEPT     tcp  --  *      *       10.0.0.0/24          192.168.1.10        tcp dpt:22 state NEW
        0     0 DROP       tcp  --  *      *       0.0.0.0/0            192.168.1.10        tcp dpt:22
        0     0 ACCEPT     all  --  br0    br0     0.0.0.0/0            0.0.0.0/0           
        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           state INVALID 
        0     0 TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp flags:0x06/0x02 TCPMSS clamp to PMTU 
        0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
    Any existing incoming packets, especially ones from regular web browsing, on other computers, has to travel down to the 7th rule to be accepted. I have a large number of CIDR to white list for various port, so this would mean any established TCP connection would have to travel down the entire list to before passing through.

    Now if that dd-wrt user was right, placing RELATED,ESTABLISHED rule first, things may look more optimized if I revised my rules this way:

    Code:
    iptables -I FORWARD -p tcp -d 192.168.1.10 --dport 22 -j DROP
    iptables -I FORWARD -p tcp -s 10.0.0.0/24 -d 192.168.1.10 --dport 22 -m state --state NEW -j ACCEPT
    iptables -I FORWARD -p tcp -s 10.1.0.0/24 -d 192.168.1.10 --dport 22 -m state --state NEW -j ACCEPT
    ## Optimized established connection
    iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
    Resulting IPTABLES will look like:

    Code:
    iptables -vnL
    Chain FORWARD (policy DROP 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
        0     0 ACCEPT     tcp  --  *      *       10.1.0.0/24          192.168.1.10        tcp dpt:22 state NEW
        0     0 ACCEPT     tcp  --  *      *       10.0.0.0/24          192.168.1.10        tcp dpt:22 state NEW
        0     0 DROP       tcp  --  *      *       0.0.0.0/0            192.168.1.10        tcp dpt:22
        0     0 ACCEPT     all  --  br0    br0     0.0.0.0/0            0.0.0.0/0           
        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           state INVALID 
        0     0 TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp flags:0x06/0x02 TCPMSS clamp to PMTU 
    All currently established packets would not need to traverse down the entire FORWARD table if there were additional rules added. If you or anyone who has extensive rules on the FORWARD table, let me know this could be helpful with throughput or efficiency.
     
  2. rhester72

    rhester72 Network Guru Member

    FWIW, my experience agrees with the finding - putting RELATED/ESTABLISHED high in the chain does indeed result in better performance as a result of connection tracking/less chain traversal.

    Rodney
     
  3. phuque99

    phuque99 LI Guru Member

    I'm guessing the only way to test this is to perform "internal" tests with computers connected to the LAN and WAN port to test actual routing?
     
  4. rhester72

    rhester72 Network Guru Member

    Correct.

    Rodney
     
  5. Toastman

    Toastman Super Moderator Staff Member Member

    phuque99, no, I've never tried to optimise things by shifting rules manually in iptables. I wouldn't expect it to make much difference to my relatively slow ( 5 - 16 Mbps) connections, but if anyone is getting near the limit it would probably be worth doing.
     
  6. RonWessels

    RonWessels Network Guru Member

    By that same argument, you wouldn't expect overclocking your CPU to make much difference to your relatively slow connections.

    This change reduces the per-packet processing of established connections (the bulk of the processing a router should be doing unless undergoing serious attack), and will have the same effect as further overclocking your CPU, but without the "danger" associated with overclocking.
     
  7. Toastman

    Toastman Super Moderator Staff Member Member

    True, I guess. But this has to be done manually, or it will keep getting changed with new GUI updates? Should Tomato not be writing established connections closer to/at the beginning of the list ?

    I'm changing the order too, and will keep an eye on how it performs. There is no noticeable difference here, but I can't do a proper test though.

    Interesting, the re-allocated place sticks after a reboot.
     
  8. WRobertE

    WRobertE Addicted to LI Member

    Should this same technique also be used on the INPUT chain?

    I added the following to the Firewall script dialog and haven't seen any problems:

    # Optimize FORWARD chain
    iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

    This basically moves this rule to the top of the chain.

    I'm using Victek's Tomato RAF Firmware v1.28.8525 _RAF ND VPN and the only thing I notice is that starting the VPN client on the router, for example, inserts the following item at the start of the chain:

    Chain FORWARD (policy DROP 0 packets, 0 bytes)
    pkts bytes target prot opt in out source destination
    0 0 ACCEPT all -- tun11 * 0.0.0.0/0 0.0.0.0/0

    Shutting down the VPN client removes this entry and the RELATED,ESTABLISHED entry returns to the top of the chain again.
     
  9. phuque99

    phuque99 LI Guru Member

    Tomato is writing that close to the "top" of the forward chain. However, default forward chain rules assumes no other "firewall" exist. So if you need do granular filtering, it is necessary to run "iptables -I" to insert granular/specific filtering rules above the broader "accept-all" rules that tomato inserted by default.

    Thus if you have 20 or more lines of multiple firewall rules, the related,established rules that most packet use after connection handshake goes right below them.

    I don't see any lesser load or lesser memory usage on E3000. Perhaps benefits could be more evident on older WRT54GL routers.
     
  10. RonWessels

    RonWessels Network Guru Member

    You can always do "iptables -I INPUT 2" to insert the rule as the second entry, after the global "established -> accept" entry. Only if the optional positional argument is not specified does the rule get inserted at the very beginning of the chain.
     
  11. teddy_bear

    teddy_bear Network Guru Member

    Tomato does nothing wrong when writing the FORWARD chain - if you manually re-arrange it you may loose some functionality or it won't work properly (webmon, access restrictions). And if you're not using the functionality mentioned, the corresponding rules won't be created, so the suggested re-arrange won't do anything at all to the standard generated rules.

    That being said, it's obviously not optimal to insert your custom rules on the top of the FORWARD chain (as in the script in the 1st post). But instead of re-creating "RELATED,ESTABLISHED" rule as phuque99 suggested to solve that inefficiency, just add the custom rules to the "wanin" chain (which is called from the FORWARD chain) - that's the proper way to do it. At least doing this you won't accidentally mess anything up (besides, it's easier). Almost the same applies if you need any custom rules in the INPUT chain - use "-A" parameter to add them to the end, never inset them on the top of "RELATED,ESTABLISHED" rule.

    Also - just so you know - to restrict the SSH access from WAN to certain addresses (what OP tried to do with his script) you don't actually need any custom rules - just use the Tomato GUI to setup the allowed addresses on the "Admin Access" page.

    That's wrong too. There's no such rule in the standard Tomato firewall to "accept-all" from WAN - neither in the FORWARD, nor the INPUT chain. It drops everything unless you explicitly accept it.
     
  12. WRobertE

    WRobertE Addicted to LI Member

    Yep...I can confirm teddy_bear's warnings. Moving the "RELATED,ESTABLISHED" rule to the top of the FORWARD chain in an attempt to "optimize" does indeed break web monitoring. I had turned off web monitoring and didn't notice that before.

    So, like the old saying goes ... "If it ain't broke, don't fix it."

    Back to the defaults for me.
     
  13. phuque99

    phuque99 LI Guru Member

    @teddy_bear: Perhaps the context wasn't clearly defined. I have port forwarding setup on the GUI, SSH port 22 to a one private IP, FTP port 21 to another internal private IP. I have 7 CIDR to whitelist for SSH and 5 others for FTP whitelist. The default FORWARD chain looks like this:

    Code:
        0     0 ACCEPT     all  --  br0    br0     0.0.0.0/0            0.0.0.0/0           
        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           state INVALID 
        0     0 TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp flags:0x06/0x02 TCPMSS clamp to PMTU 
        1   386 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
        0     0 wanin      all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0           
        0     0 wanout     all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0           
        0     0 ACCEPT     all  --  br0    *       0.0.0.0/0            0.0.0.0/0           
    
    If I appended (-A) my whitelisted CIDRs into the FORWARD table, instead of insert above (-I), the rules goes under those rules above, and the jump to wanin in line 6 will "accept all" port forwarded traffic. That's the reason why whitelist only rules has to be inserted above the existing FORWARD chain rules.

    I guess I wasn't aware that inserting would break some functionality, since I don't use those modules. If inserting rules above the default in the FORWARD table is not optimal, is there a better way to achieve what I'm doing manually:

    1. Set port forwarding on GUI
    2. Custom IPTABLES to allow only listed CIDRs to access these ports
     
  14. teddy_bear

    teddy_bear Network Guru Member

    Where do you see this? The only "accept-all" is the last rule in the FORWARD chain which only applies to the traffic originated from your LAN (br0).

    But as I mentioned above, instead of adding custom forwarding rules for incoming traffic to the FORWARD chain directly, the proper way is to add them to the "wanin" chain - that's what it's for.
     
  15. phuque99

    phuque99 LI Guru Member

    Thanks for the pointer. Let me re-format and migrate my firewall rules into wanin table and see how things go.
     
  16. phuque99

    phuque99 LI Guru Member

    Just want to conclude on this that moving the RELATED,ESTABLISHED rules in FORWARD chain is not necessary. In fact, as reported by Teddy_bear, this will break some of the functionality in Tomato.

    My rules were migrated from dd-wrt, and thus were all inserted above the FORWARD chain rules. There is a "wanin" and "wanout" chain in Tomato and any custom allow/deny firewall rules should be inserted there. When this is done correctly, they are "optimized" because routed packets would hit the RELATED,ESTABLISHED in the FORWARD chain, before going to the "wanin" or "wanout" chain
     

Share This Page