Relevant to this reference http://lartc.org/howto/lartc.netfilter.html
I want to mark packets sent to a certain port (80 for simplicity sake) and route them to tun0 (which is created by openvpn).
Mark the packets that wlan0 sends to port 80 with 1
$ iptables -A PREROUTING -i wlan0 -t mangle -p tcp --dport 80 -j MARK --set-mark 1
$ echo 201 mytable >> /etc/iproute2/rt_tables
Add the rule that all packets marked with 1 are routed by mytable
$ ip rule add fwmark 1 table mytable
Add the rules which say any packets sent to the entire internet are routed by tun0
$ ip route add 184.108.40.206/1 via 10.8.0.13 dev tun0 table mytable $ ip route add 0.0.0.0/1 via 10.8.0.13 dev tun0 table mytable
Annndd it doesn't do anything
A couple things worth mentioning
1) When I start openvpn it adds a bunch of routes to table main which causes every packet to be routed through tun0. Ifconfig shows tun0 with inet 10.8.0.14 but all the routes added by OpenVPN are for 10.8.0.13. OpenVPN also adds the route
10.8.0.13 dev tun0 proto kernel scope link src 10.8.0.14
If I run OpenVPN with --route-nopull and create the routes myself but for 10.8.0.14 it has the exact same effect, I have no idea while OpenVPN does this thing with 10.8.0.13.
2) Any routes I add to table main work fine. The problem must be that iptables isn't marking the packets or that ip rules isn't sending the market packets to the right table. Very strange.
Output of my current settings:
$ ip route list table mytable 0.0.0.0/1 via 10.8.0.13 dev tun0 10.8.0.13 dev tun0 proto kernel scope link src 10.8.0.14 220.127.116.11/1 via 10.8.0.13 dev tun0 $ ip rule ls 0: from all lookup local 32765: from all fwmark 0x1 lookup mytable 32766: from all lookup main 32767: from all lookup default $ sudo iptables -t mangle -L Chain PREROUTING (policy ACCEPT) target prot opt source destination MARK tcp -- anywhere anywhere tcp dpt:http MARK set 0x1 Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination
Obviously no packets are being marked.
Before I was using iptables to filter wlan0 packets to port 80. I changed this to any interface for ports 80,all,443,22
$ sudo iptables -L -v -t mangle Chain PREROUTING (policy ACCEPT 10341 packets, 15M bytes) pkts bytes target prot opt in out source destination 0 0 MARK tcp -- any any anywhere anywhere tcp dpt:http MARK set 0x1 27110 39M MARK tcp -- any any anywhere anywhere MARK set 0x1 0 0 MARK tcp -- any any anywhere anywhere tcp dpt:https MARK set 0x1 0 0 MARK tcp -- any any anywhere anywhere tcp dpt:ssh MARK set 0x1
Note that 39M of packets were caught by iptables, but none matched the rule for ports 80, 443, or 22 even though I accessed services on all of those ports. Very strange.
Iptables started marking packets when I switched --dport to --sport but still nothing happened. I know ip rules get applied in order, so if the routes in mytable don't work than the packets will be routed by table main. I thought there might be a problem with DNS lookups, but I set resolv.conf nameservers to Google DNS and nothing changed.
Is there a way to see my external ip using the command line and without a dns lookup? I was using
$ curl 18.104.22.168 | grep "Your IP address"
And getting the data off the cloudflare dns error page, but there's probably a more official way.