OpenVPN + iptables / NAT routing
I'm trying to set up an OpenVPN VPN, which will carry some (but not all) traffic from the clients to the internet via the OpenVPN server.
My OpenVPN server has a public IP on eth0, and is using tap0 to create a local network, 192.168.2.x. I have a client which connects from local IP 192.168.1.101 and gets VPN IP 192.168.2.3.
On the server, I ran:
iptables -A INPUT -i tap+ -j ACCEPT
iptables -A FORWARD -i tap+ -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
On the client, the default remains to route via 192.168.1.1. In order to point it to 192.168.2.1 for HTTP, I ran
ip rule add fwmark 0x50 table 200
ip route add table 200 default via 192.168.2.1
iptables -t mangle -A OUTPUT -j MARK -p tcp --dport 80 --set-mark 80
Now, if I try accessing a website on the client (say, wget google.com), it just hangs there. On the server, I can see
$ sudo tcpdump -n -i tap0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap0, link-type EN10MB (Ethernet), capture size 96 bytes
05:39:07.928358 IP 192.168.1.101.34941 > 74.125.67.100.80: S 4254520618:4254520618(0) win 5840 <mss 1334,sackOK,timestamp 558838 0,nop,wscale 5>
05:39:10.751921 IP 192.168.1.101.34941 > 74.125.67.100.80: S 4254520618:4254520618(0) win 5840 <mss 1334,sackOK,timestamp 559588 0,nop,wscale 5>
Where 74.125.67.100 is the IP it gets for google.com .
Why isn't the MASQUERADE working? More precisely, I see that the source showing up as 192.168.1.101 -- shouldn't there be something to indicate that it came from the VPN?
Edit: Some routes [from the client]
$ ip route show table main
192.168.2.0/24 dev tap0 proto kernel scope link src 192.168.2.4
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.101 metric 2
169.254.0.0/16 dev wlan0 scope link metric 1000
default via 192.168.1.1 dev wlan0 proto static
$ ip route show table 200
default via 192.168.2.1 dev tap0
Can you post the output of ip route show table main and ip route show table 200? I suspect you are missing a couple routes in your '200' table. Your '200' route table should have pretty much the same routes as the 'main' table the only difference being the default route.
I see that you updated, and I believe my original suggestion was correct. Notice how your main table has the 'scope link' route for both your local network and the vpn link? Those routes have to be added to the '200' table as well.
Try running these commands in addition to the other commands you use.
ip route add 192.168.2.0/24 dev tap0 proto kernel scope link src 192.168.2.4 table 200
ip route add 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.101 metric 2 table 200
ip route flush cache
If you want to script the creation of these routes you can use this. It will copy all the 'scope link' routes from the main route table into your other table.
#!/bin/bash
IFACE=wlan0
RT=200
/sbin/ip route list scope link table main proto kernel dev ${IFACE} \
| while read ROUTE ; do
# and add that route to all the tables mentioned in the rrtables option
# in the interfaces file
/sbin/ip route add table ${RT} scope link proto kernel dev ${IFACE} ${ROUTE}
done
Another update. I just noticed I missed something rather obvious earlier.
Your MASQ statement seems to be working on eth0. From the route tables you posted, your output device isn't eth0. Instead of this.
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE
You probably should just use a statement like this.
iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE
Try on the server:
echo 1 > /proc/sys/net/ipv4/ip_forward
That, I think, will enable it temporarily. If it works add:
net.ipv4.conf.default.forwarding=1
to your /etc/sysctl.conf to make it permanent.