Recently, I added several new iptables (RE: code snippet below) rules to route traffic through my VPN (0x1000/0x1000) for a specific destination ( over port 443. The new rules NAT over the VPN as desired, but they've created an undesired effect causing other HTTP requests, unrelated to the aforementioned destination, to produce an error response 400 Bad Request.

# Create the RPDB rules
ip rule add from 0/0 fwmark "0x1000/0x1000" table ovpnc1 prio 9993        # VPN 1 fwmark

iptables -t mangle -A PREROUTING -i br0 -p tcp -d --dport 443 -j MARK --set-mark 0x1000/0x1000
iptables -t nat -A PREROUTING -i br0 -p tcp -m mark --mark 0x1000/0x1000 -j DNAT --to-destination

Any idea why other HTTP requests would be affected (400 Bad Request) by the new NAT rules when the destination address and port are clearly specified?

Thank you for your time and assistance.

Kind Regards,


  • What on earth are you trying to do here? This looks completely unnecessary. It looks like you are doing a DNAT instead of the expected routing. – Michael Hampton Oct 12 '20 at 12:06
  • The goal is to mark the specified destination packets for traversal of the VPN (oppose to the WAN). The iptables rules work, they just break other HTTP requests (400 Error) on the VPN. It sounds like you're suggesting there is more than one way to implement this task? – Gary C. New Oct 12 '20 at 13:25
  • But why did you DNAT? You're supposed to route. – Michael Hampton Oct 12 '20 at 13:28
  • It has been quite some time since I've developed iptables rules and the examples I found on this site suggested DNAT was the way to implement it. I'm open to alternate iptables routing, if you'd like to provide an example. – Gary C. New Oct 12 '20 at 13:34

VPN Server: Assuming eth0 (IP is the physical interface that is directly attached to or at least has the route to the target web-server's IP or network, you can monitor any traffic destined to the web-server IP, to be forced through the VPN tunnel and then NATted out to eth0's IP address ( in this example). In this case, br0 interface (IP is the virtual interface that the VPN server is using to tunnel the traffic. While the VPN is up and running, it already knows how to route packets to destination IP

If not, then you have to add a static route:

$ ip route show via dev br0 metric 101

Once the route statement is satisfied, then you can force traffic destined to IP to be routed through the tunnel and exit on the other side as en-route

$ sudo iptables -t nat -A POSTROUTING -o eth0 -p tcp -m tcp -d --dport 443 -j SNAT --to-source
$ sudo iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

If a client sends a packet to for example, the source IP will not change, and the packet may be discarded if not allowed by subsequent chains.



It turns out my original iptables -t nat rule was missing the --dport 443 definition and the reason why it was interacting with Other HTTP requests.

# Create the RPDB rules
ip rule add from 0/0 fwmark "0x1000/0x1000" table ovpnc1 prio 9993        # VPN 1 fwmark

iptables -t mangle -A PREROUTING -i br0 -p tcp --dport 443 -d -j MARK --set-mark 0x2000/0x2000
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 443 -j DNAT --to-destination -m mark --mark 0x2000/0x2000

Once the --dport 443 definition was added to the iptables -t nat rule the issue was resolved.

Hope this helps someone else in the future.



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.