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

Welcome To SNBForums

SNBForums is a community for anyone who wants to learn about or discuss the latest in wireless routers, network storage and the ins and outs of building and maintaining a small network.

If you'd like to post a question, simply register and have at it!

While you're at it, please check out SmallNetBuilder for product reviews and our famous Router Charts, Ranker and plenty more!

OpenVPN automatic firewall rules (iptables)

Discussion in 'Asuswrt-Merlin' started by protogen, Apr 21, 2019.

  1. protogen

    protogen Occasional Visitor

    Joined:
    May 22, 2016
    Messages:
    19
    After upgrading to 384.10_2 recently, I took a look at the automatic firewall rules created for OpenVPN server. The short script on my router looks like this.
    Code:
    #!/bin/sh
    iptables -t nat -I PREROUTING -p udp --dport 1194 -j ACCEPT
    iptables -I INPUT -p udp --dport 1194 -j ACCEPT
    iptables -I OVPN -i tun21 -d 192.168.9.0/24 -j ACCEPT
    iptables -t mangle -I PREROUTING -i tun21 -j MARK --set-mark 0x01/0x7
    
    The first rule above looked interesting to me because the target ACCEPT is normally never used with the nat table. Also, the rule is inserted at the very top (i.e. first) of the PREROUTING chain, which is also somewhat unusual.

    I did some digging and found the following paragraph in the Linux iptables Pocket Reference.
    This explains what the rule is doing but not why it is being done.

    Am I correct that the purpose of this rule is performance enhancement? In other words, bypassing NAT will speed up the VPN?
     
  2. eibgrad

    eibgrad Regular Contributor

    Joined:
    Feb 20, 2017
    Messages:
    148
    Normally you wouldn't see the first rule in a situation where the service being accessed is running on the primary router itself. You would only see the second rule, where the relevant port (1194 in this case) is opened on the INPUT chain. Not unless there was something in the PREROUTING chain of the nat table that would otherwise interfere (block, filter) that traffic before it could get to the INPUT chain of the filter table.

    FWIW, I took a look at one of my lab routers, and although I'm not running the OpenVPN server at the moment, nor have I configured port forwarding, I don't see any obvious reason the first rule would be needed.

    Code:
    ASUSWRT-Merlin RT-AC68U 384.5-0 Sun May 13 01:53:17 UTC 2018
    
    [email protected]:/tmp/home/root# iptables -t nat -vnL PREROUTING
    Chain PREROUTING (policy ACCEPT 311K packets, 31M bytes)
     pkts bytes target     prot opt in     out     source               destination
     2634  142K VSERVER    all  --  *      *       0.0.0.0/0            192.168.61.60
    
    [email protected]:/tmp/home/root# iptables -t nat -vnL VSERVER
    Chain VSERVER (1 references)
     pkts bytes target     prot opt in     out     source               destination
     2631  137K DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8443 to:192.168.1.1:8443
       23  6481 VUPNP      all  --  *      *       0.0.0.0/0            0.0.0.0/0  
    
    [email protected]:/tmp/home/root# iptables -t nat -vnL VUPNP
    Chain VUPNP (1 references)
     pkts bytes target     prot opt in     out     source               destination
    As you can see, there's nothing in the above that would prevent access to port 1194 on the INPUT chain, provided that port was opened. Then again, I'm running an older build (384.5). Maybe something has changed w/ more recent builds.
     
    protogen likes this.
  3. RMerlin

    RMerlin Super Moderator

    Joined:
    Apr 14, 2012
    Messages:
    30,248
    Location:
    Canada
    I assume it's there to prevent traffic from being NATed by the port forwarding rules that follow, and ensure that traffic only gets routed without NAT. I'm not sure, the firewall code was lifted from the original Tomato implementation years ago.
     
  4. eibgrad

    eibgrad Regular Contributor

    Joined:
    Feb 20, 2017
    Messages:
    148
    But most DNAT'ing is very specific to the firewall rules created in the GUI. IOW, there usually isn't some broad-based DNAT'ing taking place in the PREROUTING chain. Anything that shouldn't get through is then DROPped in the FORWARD chain of the filter table.

    That said, it wasn't all that long ago that ppl were routinely using the PREROUTING chain of the nat table to DROP packets unless there was an appropriate port forward. But that was *always* considered inappropriate. The most recent releases of iptables don't even allow that anymore. It will generate an error. The PREROUTING and POSTROUTING chains of the nat table are only for the purposes of manipulating packets. You must now use the filter table to DROP packets.

    So it's my guess (and only a guess) that at some point DROPs were being made in the PREROUTING chain of the nat table. Then iptables was updated and it was discovered that wouldn't work anymore, so they moved the DROP to the filter table, where it belongs. But they failed to remove this PREROUTING rule from the OpenVPN server. That process still thinks it has to get around the old DROP rule in the PREROUTING chain of the nat table.

    Doesn't do any harm to keep it there, at least I don't see any harm. But it does cause some confusion for anyone analyzing the iptables dump.
     
    Last edited: Apr 21, 2019
    protogen likes this.
  5. protogen

    protogen Occasional Visitor

    Joined:
    May 22, 2016
    Messages:
    19
    I agree. I couldn't see any reason either, apart from maybe performance enhancement, which is why I started the thread. I was interested to see what others thought about why the rule was being used.
    This matches my understanding too. On my router, I've actually disabled the automatic firewall rules (via openvpn postconf) and implemented my own instead. I use only two rules, both on the OVPN chain.
    Code:
    Chain OVPN (2 references)
    num   pkts bytes target     prot opt in     out     source               destination
    1        1    82 ACCEPT     udp  --  eth0   *       <client IP>          <my external ip>     udp spts:1024:65535 dpt:1194
    2        2   168 ACCEPT     all  --  tun21  *       0.0.0.0/0            0.0.0.0/0
    
    My rules above are the equivalent of automatic rules 2 and 3. I've added both of mine to the OVPN chain since both the INPUT and FORWARD chains link to OVPN.
    I didn't know that about the PREROUTING chain. Very interesting. Thanks for providing the background and history. I'm willing to bet your guess is correct - it does makes sense.
    I don't see any harm either. But, as you've said, the rule puzzled me.
     
  6. eibgrad

    eibgrad Regular Contributor

    Joined:
    Feb 20, 2017
    Messages:
    148
    Made a small correction to post #4.

    DNAT takes place in the PREROUTING chain of the nat table (I originally said SNAT), whereas SNAT takes place in the POSTROUTING chain. All your port forwards use DNAT to change the public IP of the destination field in the packet to a local IP before being passed to the FORWARD chain of the filter table. At that point, you typically see a DROP rule on the WAN (iow, by default every connection initiated from the internet is blocked), preceded by ACCEPT rules for all your port forwards.

    None of this changes the gist of my analysis, I just wanted to clarify before someone became confused by my own statements.
     
    L&LD and protogen like this.
  7. ColinTaylor

    ColinTaylor Part of the Furniture

    Joined:
    Mar 31, 2014
    Messages:
    8,309
    Location:
    UK
    I think RMerlin is correct and the PREROUTING rule is there simply to give precedence to the VPN server over any port forwarding (DNAT) rules. Without it, if say your VPN server was on port 443, and a UPnP client forwarded that port to itself it would break the VPN server.

    I don't think it's any more cryptic than that. Admittedly it's not particularly aesthetic but it works. I think you have to regard the OpenVPN server rules as largely stand-alone rather than something that was part of the original design. As such it takes a rather "brute force" approach by inserting itself into the beginning of the iptables chains to ensure its dominance.
     
    Last edited: Apr 22, 2019
    eibgrad, john9527, L&LD and 1 other person like this.
  8. eibgrad

    eibgrad Regular Contributor

    Joined:
    Feb 20, 2017
    Messages:
    148
    Sounds plausible. But it also suggests an inherent conflict between using UPnP (which let's individual clients on your network manage port forwards), vs. those the admin has configured directly w/ port forwarding on the router, or those ports directly opened on the WAN as the result of local processes on the router. I suppose just another reason to avoid UPnP. You're letting individual clients participate in what should only be administrative operations, and thus (potentially anyway) creating conflicts. As you describe it, the OpenVPN server simply takes over that port, even if currently in-use by UPnP. That should never be allowed to happen. So it's more than an aesthetic issue. The "fixup" in the PREROUTING chain is simply ignoring a problem, as you say, w/ brute force.

    Again, I've never seen this type of rule in any other third-party firmware, at least not that I can recall. I wonder how many ppl would even think to consider such a potential conflict happening. I know I didn't. Then again, I always keep UPnP disabled (but for other reasons).

    In the end, I don't know whether to classify this "fixup" as brilliant, or stupid. (maybe just selfish!) LOL
     
    protogen and martinr like this.
  9. ColinTaylor

    ColinTaylor Part of the Furniture

    Joined:
    Mar 31, 2014
    Messages:
    8,309
    Location:
    UK
    I would call it a "necessary botch".:D It's not just UPnP or course. I've just defined a manual port forwarding rule on the same port/protocol that my VPN server uses and it created the conflicting rules without objection.

    I think this just demonstrates the way the firmware has developed and been added to over time. To avoid the conflicts mentioned above would require the firewall code to take a holistic overview of all the separate components, something that it just doesn't do particularly well.
     
    protogen, eibgrad and martinr like this.