What's new

OpenVPN automatic firewall rules (iptables)

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

protogen

Occasional Visitor
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.
If you want certain packets to bypass NAT, you can write
rules that match the packets you are interested in and jump
to the special target ACCEPT. You need to have such rules
before your other NAT rules.

iptables -t nat -i eth1 ... -j ACCEPT

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?
 
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

admin@merlin-lab1:/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

admin@merlin-lab1:/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  

admin@merlin-lab1:/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.
 
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.
 
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.

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:
I don't see any obvious reason the first rule would be needed.
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.
But most SNAT'ing is very specific to the firewall rules created in the GUI. IOW, there usually isn't some broad-based SNAT'ing taking place in the PREROUTING chain. Anything that shouldn't get through is then DROPped in the FORWARD chain of the filter table.
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.
That said, it wasn't all that long ago that ppl were routinely using the PREROUTING chain of the nat table to DROP packets... So it's my guess (and only a guess)... That process still thinks it has to get around the old DROP rule in the PREROUTING chain of the nat table.
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.
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.
I don't see any harm either. But, as you've said, the rule puzzled me.
 
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.
 
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:
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 it dominance.

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
 
In the end, I don't know whether to classify this "fixup" as brilliant, or stupid. (maybe just selfish!) LOL
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.
 

Similar threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top