My home router is just an older pc running the server version of xenial. Pertinent to the issue presented here, my wan interface is labeled enp6s0, my lan interface is labeled enp7s0.
I have installed openvpn on my router which connects as a client to an aws ec2 instance (also xenial server) running openvpn in server mode. I have no trouble routing ipv4 and ipv6 traffic from the router through the ec2 instance. I have no trouble using routing rules to select traffic from specific hosts on my internal network to route either through the ec2 instance or through my isp.
I do however run into trouble when I try to route traffic based on protocol and port number by marking packets in the mangle table. Specifically the traffic routed through the ec2 sucessfully reaches its destination, the reponse successfully traverses it's way back to my router but then never reaches my lan interface.
I normally use a script to start my ec2 instance, connect with openvpn and then setup my router routing tables and rules, but the following are the essential commands:
STARTING EC2 INSTANCE AND CONNECTING:
clifford@router:~$ aws ec2 describe-instances --instance-ids $( < vpn.sluggishmail.com-instance-id) | grep PublicIpAddress
"PublicIpAddress": "54.245.59.110",
clifford@router:~$ sudo openvpn --daemon --config /etc/openvpn/client.conf --remote 54.245.59.110 1194 udp
NETWORK INTERFACES AFTER VPN CONNECTION:
clifford@router:~$ ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 68:1c:a2:12:66:b5 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.3/16 brd 192.168.255.255 scope global enp7s0
valid_lft forever preferred_lft forever
inet6 2600:XXXX:XXXX:XXXX::3/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::6a1c:a2ff:fe12:66b5/64 scope link
valid_lft forever preferred_lft forever
3: enp6s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 68:1c:a2:12:66:b6 brd ff:ff:ff:ff:ff:ff
inet 68.XXX.XXX.XXX/24 brd 68.XXX.XXX.255 scope global enp6s0
valid_lft forever preferred_lft forever
inet6 fe80::6a1c:a2ff:fe12:66b6/64 scope link
valid_lft forever preferred_lft forever
4: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:25:22:10:d0:7b brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 brd 10.0.0.255 scope global enp2s0
valid_lft forever preferred_lft forever
inet6 fe80::225:22ff:fe10:d07b/64 scope link
valid_lft forever preferred_lft forever
6: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.8.0.6 peer 10.8.0.5/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 2600:XXXX:XXXX:XXXX::1000/64 scope global
valid_lft forever preferred_lft forever
After manually setting up the routing table (ISP traffic through the main routing table, VPN through the custom AWS table) using the ip command,
ROUTES:
clifford@router:~$ ip route show
default via 68.XXX.XXX.1 dev enp6s0
10.0.0.0/24 dev enp2s0 proto kernel scope link src 10.0.0.3
68.XXX.XXX.0/24 dev enp6s0 proto kernel scope link src 68.XXX.XXX.XXX
192.168.0.0/16 dev enp7s0 proto kernel scope link src 192.168.1.3
clifford@router:~$ ip route show table AWS
default via 10.8.0.5 dev tun0
10.8.0.1 via 10.8.0.5 dev tun0
10.8.0.5 dev tun0 scope link src 10.8.0.6
Then MASQUERADEing traffic outband through the VPN:
clifford@router:~$ sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
At this point, traffic still successfully travels through my ISP without touching the VPN. If I add the rule:
clifford@router:~$ sudo ip rule add from 192.168.1.12 table AWS
Traffic from host 192.168.1.12 successfully routes over the VPN. I have analogous rules and routes for ipv6 traffic that also successfully routes. The reverse, setting up the default routing table to use the VPN and then exempting specific hosts to use the ISP, also works.
But I run into trouble when I try to route traffic on specific protocols and ports over the VPN.
Deleting:
clifford@router:~$ sudo ip rule del from 192.168.1.12
And marking tcp traffic on ports 80 and 443 from host 192.168.1.12:
clifford@router:~$ sudo iptables -t mangle -A PREROUTING -s 192.168.1.12 -m multiport -p tcp --dports 80,443 -j MARK --set-mark 1
And adding a rule to route marked traffic through the VPN table:
clifford@router:~$ sudo ip rule add fwmark 1 table AWS
At this point, traffic successfully routes over the VPN to its destination:
clifford@router:~$ sudo tcpdump -n -i enp7s0 tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
07:54:42.056497 IP 192.168.1.12.56414 > 52.38.255.144.80: Flags [S], seq 2097315203, win 64240, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
The response successully routes all the back to the address associated with my router's tun0 interface ( 10.8.0.6):
clifford@router:~$ sudo tcpdump -n -i tun0 tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
07:54:10.719152 IP 52.38.255.144.80 > 10.8.0.6.56395: Flags [S.], seq 1816310859, ack 2633952775, win 26883, options [mss 1198,nop,nop,sackOK,nop,wscale 7], length 0
But traffic is "dropped" there, never making it back to interface enp7s0 or the host. I put drop in quotes because I don't mean there is an iptable rule that evaluates to -j DROP. Even if I make the filter table rules as liberal as possible (ACCEPT everything) the traffic still disappears.
I have been playing with this for two weekends now, and I am still not able to remedy the problem. If anyone made it all the way through this post, I thank you. And if you can spot my mistake, I would appreciate if you would point it out.