My home server has two main interfaces,
eth1 (a standard internet connection) and
tun0 (an OpenVPN tunnel). I'd like to use
iptables to force all packets generated by a local process owned by UID 1002 to exit through
tun0, and all other packets to exit through
I can easily mark matched packets:
iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
Now, I'd like to put some rule in the POSTROUTING chain (probably of the mangle table) to match packets marked with 11 and send them to
tun0, followed by a rule that matches all packets and send them to
I found the ROUTE target, but that seems to only re-write the source interface (unless I'm reading it incorrectly).
Is iptables capable of this? Do I have to mess around with the routing table (via
ip route or just the legacy
route commands) instead?
Edit: I thought that maybe I should provide more information. I have no other iptables rules at present (although I may create some rules to carry out unrelated tasks in the future). Also, the output of
ip route is:
default via 192.168.1.254 dev eth1 metric 203 10.32.0.49 dev tun0 proto kernel scope link src 10.32.0.50 184.108.40.206 via 192.168.1.254 dev eth1 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.73 metric 203
I haven't touched the routing table - this is just how it is at present (although it looks fairly dirty). I'm sorry, but I don't have the legacy
route command installed on this machine.
And the output of
ip addr (of course, eth0 and eth2 can be ignored - they're NICs that aren't being used at present):
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1 inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link valid_lft forever preferred_lft forever 4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff 5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100 link/none inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0
Edit: I've gotten something sorta working, but it's not forwarding marked packets to tun0. Basically, I added a table (11), and used:
ip route add table 11 via 10.32.0.49 dev tun0 ip rule add priority 10000 fwmark 11 table 11
When I just
sudo -u user1000 wget -qO- whatismyip.org, I get my home's external IP address, but if I do
sudo -u user1002 wget -qO- whatismyip.org, I also get my home's IP address (but I should be getting the IP at the other end of the OpenVPN tunnel).
iptables -vL confirms that the packets are getting matched by the marking rule, but they don't appear to be following the routing rule.
EDIT: I've spent a long time on this, and although it still doesn't work, I think I'm a bit closer.
The iptables rule has to be in the
mangle table's OUTPUT chain. I think I also need a MASQUERADE rule in the
nat table's POSTROUTING chain, to set the source address. However, the re-routing that occurs after OUTPUT's mangle is not working correctly.
I've spent 5 hours on this now, so I'm taking a break and will probably return to it later tonight or sometime tomorrow.