# [SOLVED] Source based routing over OpenVPN

## psychedup

I've been playing with iptables/iproute2/openvpn but can't quite get it to work the way I want. Hopefully somebody here can point out some detail that I'm missing.

I currently have what I'll call "Host A", which is a Gentoo box in my house that's set up as a home router, among other things. Host A has 2 physical network interfaces - one is connected to a DSL modem and the other connects to my internal LAN, and all of my other devices are able to connect to the internet via Host A. This works very well.

For a new project, I'm adding "Host B" which is a tiny instance running on AWS. The idea is to set this machine up as a second router, and for Host A to send "certain" traffic to the internet via Host B, due to certain ports being blocked on the DSL connection.

I have successfully set up an OpenVPN connection between the two hosts, and they are able to reach each other just fine. This created a tun1 interface on Host A with IP 172.16.1.2, and tun0 on Host B with IP 172.16.1.2.

I set up iptables rules on Host B, similarly to what is set up on Host A. The trick is, how do I make Host A to send traffic over the tun interface rather than the default gateway? I think I found the solution using iproute2 to set up source-based routing, but it doesn't seem to be working.

Here's what I've done so far:

1) On Host A, added a line for "vpn" in /etc/iproute/rt_tables:

```
#

# reserved values

#

255     local

254     main

253     default

0       unspec

#

# local

#

#1      inr.ruhep

10      vpn

```

2) On Host A, executed these commands to set up the new table's route and rules:

```
ip route add 172.16.1.0/24 dev tun1 src 172.16.1.1 table vpn

ip route add default via 172.16.1.2 dev tun1 table vpn

ip rule add from 172.16.1.1/32 table vpn

ip rule add to 172.16.1.1/32 table vpn
```

3) On Host B, executed these commands to set up the iptables rules and enable forwarding:

```
iptables -F

iptables -t nat -F

iptables -P INPUT ACCEPT

iptables -P OUTPUT ACCEPT

iptables -P FORWARD DROP

export LAN=tun0

export WAN=eth0

iptables -I INPUT 1 -i ${LAN} -j ACCEPT

iptables -I INPUT 1 -i lo -j ACCEPT

iptables -A INPUT -p UDP --dport bootps ! -i ${LAN} -j REJECT

iptables -A INPUT -p UDP --dport domain ! -i ${LAN} -j REJECT

iptables -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT

iptables -A INPUT -p TCP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

iptables -A INPUT -p UDP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

iptables -I FORWARD -i ${LAN} -d 172.16.1.0/255.255.255.0 -j DROP

iptables -A FORWARD -i ${LAN} -s 172.16.1.0/255.255.255.0 -j ACCEPT

iptables -A FORWARD -i ${WAN} -d 192.16.1.0/255.255.255.0 -j ACCEPT

iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE

echo 1 > /proc/sys/net/ipv4/ip_forward

for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done
```

Now from Host A, this works:

```
telnet -b 172.16.1.1 172.16.1.2 22
```

But when I try this, it just times out:

```
telnet -b 172.16.1.1 www.google.com 80
```

Any ideas what I'm missing?Last edited by psychedup on Sun Sep 03, 2017 6:41 pm; edited 1 time in total

----------

## chiefbag

Try the following, it looks like you currently are too explicit by defining subnets in your rules.

```
-A FORWARD -i ${LAN} -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

-A FORWARD -o ${LAN} -m state --state RELATED,ESTABLISHED -j ACCEPT
```

----------

## psychedup

 *chiefbag wrote:*   

> Try the following, it looks like you currently are too explicit by defining subnets in your rules.
> 
> ```
> -A FORWARD -i ${LAN} -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
> 
> ...

 

I tried those (on Host B) but it's still not working.

What's strange is when I run tcpdump on both machines, when I telnet directly from Host A to Host B, I can see activity on both sides, but if I telnet to www.google.com, tcpdump shows activity on Host A's tun1, but nothing on Host B's tun0. From what I've heard, tcpdump should show anything even if iptables drops it.

Maybe it's an openvpn problem?

----------

## russK

Try strace-ing the telnet to see if it's doing something you aren't expecting.  Either this:

```
strace -f -e trace=network telnet -b 172.16.1.1 www.google.com 80
```

or, to get all of it:

```
strace -f telnet -b 172.16.1.1 www.google.com 80
```

----------

## chiefbag

What iptables rules do you have on Host A?

----------

## psychedup

I tried this from Host A:

```
chris@HostA ~ $ strace -f -e trace=network telnet -b 172.16.1.1 www.google.com 80

socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3

bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("172.16.1.1")}, 16) = 0

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4

connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0

send(4, "E\356\1\0\0\1\0\0\0\0\0\0\3www\6google\3com\0\0\1\0\1", 32, MSG_NOSIGNAL) = 32

recvfrom(4, "E\356\201\200\0\1\0\1\0\0\0\0\3www\6google\3com\0\0\1\0\1"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, [28->16]) = 48

Trying 172.217.3.196...

setsockopt(3, SOL_IP, IP_TOS, [16], 4)  = 0

connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("172.217.3.196")}, 16) = -1 ETIMEDOUT (Connection timed out)

telnet: Unable to connect to remote host: Connection timed out

+++ exited with 1 +++

```

These are the iptables rules on HostA:

```
chris@HostA ~ $ sudo iptables -L -v -n

Chain INPUT (policy ACCEPT 44606 packets, 45M bytes)

 pkts bytes target     prot opt in     out     source               destination         

    7   414 ACCEPT     all  --  tun1   *       0.0.0.0/0            0.0.0.0/0           

 359M  197G ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           

1154M  911G ACCEPT     all  --  eth0   *       0.0.0.0/0            0.0.0.0/0           

4287K 3584M ACCEPT     all  --  tun0   *       0.0.0.0/0            0.0.0.0/0           

   13  4433 REJECT     udp  --  !eth0  *       0.0.0.0/0            0.0.0.0/0            udp dpt:67 reject-with icmp-port-unreachable

 6112  423K REJECT     udp  --  !eth0  *       0.0.0.0/0            0.0.0.0/0            udp dpt:53 reject-with icmp-port-unreachable

    0     0 ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:25

76650 8766K ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:587

1220K 1405M ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:1587

 882K   79M ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:993

 221K   15M ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

  12M 9961M ACCEPT     tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443

 972K   46M DROP       tcp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            tcp dpts:0:1023

 186K   14M DROP       udp  --  ppp0   *       0.0.0.0/0            0.0.0.0/0            udp dpts:0:1023

Chain FORWARD (policy DROP 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source               destination         

 102K 9861K DROP       all  --  eth0   *       0.0.0.0/0            192.168.0.0/24      

  25M 1440M TCPMSS     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:0x06/0x02 TCPMSS clamp to PMTU

1917M  205G ACCEPT     all  --  eth0   *       192.168.0.0/24       0.0.0.0/0           

  13M 1212M ACCEPT     all  --  tun0   *       172.16.0.0/24        0.0.0.0/0           

1791K  196M ACCEPT     all  --  tun0   *       0.0.0.0/0            0.0.0.0/0           

 1712  129K ACCEPT     all  --  tun0   *       0.0.0.0/0            192.168.0.0/24      

5488M 7703G ACCEPT     all  --  ppp0   *       0.0.0.0/0            192.168.0.0/24      

  13M   13G ACCEPT     all  --  ppp0   *       0.0.0.0/0            172.16.0.0/24       

    0     0 ACCEPT     all  --  *      tun1    0.0.0.0/0            0.0.0.0/0           

    0     0 ACCEPT     all  --  *      tun1    0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 551K packets, 259M bytes)

 pkts bytes target     prot opt in     out     source               destination         

chris@HostA ~ $ sudo iptables -L -v -n -t nat

Chain PREROUTING (policy ACCEPT 41M packets, 3716M bytes)

 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 22M packets, 2185M bytes)

 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 16M packets, 1114M bytes)

 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 3820K packets, 275M bytes)

 pkts bytes target     prot opt in     out     source               destination         

  29M 2172M MASQUERADE  all  --  *      ppp0    0.0.0.0/0            0.0.0.0/0  
```

----------

## psychedup

I figured out what was wrong here. It was my Openvpn setup.

I had configured Host A as the openvpn "server" and Host B as the "client". Apparently openvpn does some filtering so that the clients only receive traffic that is specifically addressed to them.

I switched around the openvpn setup so now Host A is the "client" and Host B is the "server" and now the routing / forwarding works using the iptables / iproute2 configurations I had set up already.

----------

