Route Only HTTP Traffic Over VPN

Jun 22, 2021

I searched the internet on how to route only HTTP packets over a specific interface, like a VPN interface, but I saw that a lot of solutions not worked. Here I show how to do this on a GNU/Linux system. I used Debian buster.

Step 1 - mark the packets

The first step is to mark the packets. To HTTP traffic I consider TCP 80/443. Starting on buster, Debian by default uses iptables-nft when you use the command iptables, so I repeat the command using iptables-legacy to ensure that the mark will be done.

iptables -t mangle -A OUTPUT -p tcp --dport 80 -j MARK --set-mark 0x1
iptables-legacy -t mangle -A OUTPUT -p tcp --dport 80 -j MARK --set-mark 0x1
iptables -t mangle -A OUTPUT -p tcp --dport 443 -j MARK --set-mark 0x1
iptables-legacy -t mangle -A OUTPUT -p tcp --dport 443 -j MARK --set-mark 0x1

You can also use multiport.

Step 2 - create a rt_table

You can use numbers in ip commands, but a name make it more readable. To create a new table named httpvpn:

echo "100 httpvpn" > /etc/iproute2/rt_tables.d/httpvpn.conf

Step 3 - redirect packets to the new table

The packets with the mark 0x1 must be routed to the table httpvpn.

ip rule add fwmark 0x1 lookup httpvpn

Step 4 - create a default route on the new table

The new table httpvpn is empty. Let’s add one entry.

VPNGW="VPN GATEWAY IP ADDR"
VPNDEV="interface of the VPN"
ip route add table httpvpn default via $VPNGW dev $VPNDEV

Step 5 - NAT the packets

Do NAT on the packets that leave the VPN interface.

VPNDEV="interface of the VPN"
iptables -t nat -A POSTROUTING -o $VPNDEV -j MASQUERADE
iptables-legacy -t nat -A POSTROUTING -o $VPNDEV -j MASQUERADE

Check routing

By doing the five steps, the traffic of your host will be routed to the VPN.

You can test it by using elinks/lynx to a website that shows your current IP address.

Also to check the route, you can use ip route, like this:

ip route get to IP_ADDRESS
ip route get to IP_ADDRESS mark 0x1
vpn

Back to talau's home