I'm running a VPN client on Ubuntu, and I'm looking for guidance on how to exclude certain ports from being routed through the VPN client (OpenVPN).
For example, how would one go about excluding ports 22 and 80 from being routed through the VPN?
I'm not an expert on networking, but I understand this would be called policy-based routing, and is possible on a Linux machine. However I couldn't find any clear guidance on how to achieve this.
EDIT: I have found a working solution here.
With the help of Piotr P. Karwasz, the following excludes traffic from being routed via VPN on the desired ports only (in this example, ports 22 and 80 of the machine running the VPN client):
# run with sudo
ip rule add sport 22 table 128
ip rule add sport 80 table 128
ip route add table 128 to y.y.y.y/y dev ethX
ip route add table 128 default via z.z.z.z
Where y.y.y.y/y should be the subnet of your [machine's] public IP address, ethX should be your [machine's] public Ethernet interface, and z.z.z.z should be the default gateway.
For example:
ip rule add sport 22 table 128
ip rule add sport 80 table 128
ip route add table 128 to 172.16.9.0/24 dev eth0
ip route add table 128 default via 172.16.9.1
Traffic on those ports (in particular outgoing) will go through the main interface [eth0
or whatever is relevant] instead of the VPN interface, which solves the following problem as explained in the above link:
this is a classic problem: when you connect to the [machine] by its public IP address, the return packets get routed over the VPN. You need to force these packets to be routed over the public eth interface.
Note that ip rule add sport
(or dport
for that matter) requires iproute2
version higher than 4.15
(otherwise one gets Error: argument "sport" is wrong: Failed to parse rule type
).
In my cases I used Ubuntu's backports channel to get version 4.18
which works: apt install iproute2/bionic-backports