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