Openvpn access LAN behind client behind nat and dynamic IP from other VPN clients

openvpn

I've read and tried many guides, including the official guide about this, but I'm still unable to get this to work. Here's the setup:

(client1 LAN: 192.168.10.0/24
(OpenVPN client: client1, 192.168.10.101)
             |
             |
             v
       (NAT router,
        *dynamic* internet IP: 178.1.2.3)
             |
             |
     (...internet...)
             |
             |
             v
    (OpenVPN server,
     *static* IP:
     1.2.3.4)      <--- (...internet...)  <--- (OpenVPN client,
                                                *dynamic* internet IP:
                                                client2, 88.1.2.3)

What I want is for client2 to be able to access ALL of the client1's network. As I said in EDIT #2 below, I got it to work properly only by setting static routes on all machines in the clien1 LAN (for some reason, a static route on the NAT router doesn't quite work, see EDIT #2 below).

All machines run Ubuntu 16.04 with OpenVPN 2.3.10. The NAT router is a TP-Link MR200 In case it matters, client1 runs a KVM virtual machine server, and the OpenVPN server runs a docker container.

The tunnel works fine between the server, client1 and client2. client2 can also ping 192.168.10.101 but cannot ping 192.168.10.211, for example. I have dedicated certificates for each client which work fine and I enabled IP forwarding on the openvpn server and on client1.

This is the server's config:

# cat /etc/openvpn/graphyc.conf
server 10.8.0.0 255.255.255.0
verb 3
key server-key.pem
ca ca.pem
cert server-cert.pem
dh dh.pem
keepalive 10 120
persist-key
persist-tun
comp-lzo

user nobody
group nogroup

# dir "clients" is chown'ed to nobody:nogroup
client-config-dir clients

client-to-client
push "route 192.168.10.0 255.255.255.0"
route 192.168.10.0 255.255.255.0

proto udp
port 1194
dev tun

content of /etc/openvpn/client1 on the server (static vpn lease)

# cat /etc/openvpn/clients/client1
ifconfig-push 10.8.0.101 10.8.0.5
iroute 192.168.10.0 255.255.255.0

content of client1's config

# cat /etc/openvpn/client1.conf
client
remote 1.2.3.4 1194 udp
nobind
dev tun
comp-lzo yes
verb 3
explicit-exit-notify 5    
key /etc/openvpn/client1-key.pem
cert /etc/openvpn/client1-cert.pem
ca /etc/openvpn/ca.pem

content of client2's config

# cat /etc/openvpn/client2.conf
client
remote 1.2.3.4 1194 udp
nobind
dev tun
comp-lzo yes
verb 3
explicit-exit-notify 5    
key /etc/openvpn/client2-key.pem
cert /etc/openvpn/client2-cert.pem
ca /etc/openvpn/ca.pem

I can ping 192.168.10.101 from client2, but cannot ping 192.168.10.211 for instance. When trying the latter, the server sees the ping and routes it to the internet IP of the client1's router 178.1.2.3:

Sat Nov 18 11:48:29 2017 client2/88.1.2.3:48069 MULTI: Learn: 192.168.10.211 -> client1/178.1.2.3:52928

The official guide says that I should also add a route on the NAT router. Specifically it says: "if the client machine running OpenVPN is not also the gateway for the client LAN, then the gateway for the client LAN must have a route which directs all subnets which should be reachable through the VPN to the OpenVPN client machine".

However, I am unable to do so right now as I don't have access to the router's web interface, but I also am unsure what route to add exactly on the NAT router (i'm not sure this is needed since I don't need to access the LAN behind the server).

I'd be grateful for some concrete steps that I still need to do (or correct).

EDIT:**

Here are the routing tables for the server, client1 and client2 after they connect to the OpenVPN server.

server:

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         1.1.1.1         0.0.0.0         UG    0      0        0 eth0
10.8.0.0        10.8.0.2        255.255.255.0   UG    0      0        0 tun
10.8.0.2        *               255.255.255.255 UH    0      0        0 tun
localnet        *               255.255.255.0   U     0      0        0 eth0
link-local      *               255.255.0.0     U     1000   0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 docker0
192.168.10.0    10.8.0.2        255.255.255.0   UG    0      0        0 tun

client1:

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.10.1    0.0.0.0         UG    0      0        0 eno1
10.8.0.0        10.8.0.5        255.255.255.0   UG    0      0        0 tun
10.8.0.5        *               255.255.255.255 UH    0      0        0 tun
link-local      *               255.255.0.0     U     1000   0        0 eno1
192.168.10.0    *               255.255.255.0   U     0      0        0 eno1
192.168.122.0   *               255.255.255.0   U     0      0        0 virbr0

client2:

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         178.1.1.1       0.0.0.0         UG    0      0        0 eth0
10.8.0.0        10.8.0.5        255.255.255.0   UG    0      0        0 tun
10.8.0.5        *               255.255.255.255 UH    0      0        0 tun
88.1.2.0        *               255.255.255.0   U     0      0        0 eth0
192.168.10.0    10.8.0.5        255.255.255.0   UG    0      0        0 tun

EDIT #2:

Ok, this is weird (to me): I added a static route on the NAT router to route all packets destined for 10.8.0.0/24 via 192.168.10.101. I then tried to ping 192.168.10.211 from client2 and it didn't work. I then logged into 192.168.10.211 and ping'ed client2 on 10.8.0.6, and it said:

# ping 10.8.0.6
PING 10.8.0.6 (10.8.0.6) 56(84) bytes of data.
64 bytes from 10.8.0.6: icmp_seq=1 ttl=63 time=83.5 ms
From 192.168.10.1: icmp_seq=2 Redirect Host(New nexthop: 192.168.10.101)
64 bytes from 10.8.0.6: icmp_seq=2 ttl=63 time=75.4 ms
64 bytes from 10.8.0.6: icmp_seq=3 ttl=63 time=79.9 ms

Whoa! Hold on … I then when back to client2 and ping'ed 192.168.10.211 and it now works:

# ping 192.168.10.201
PING 192.168.10.201 (192.168.10.201) 56(84) bytes of data.
64 bytes from 192.168.10.201: icmp_seq=1 ttl=63 time=78.6 ms
64 bytes from 192.168.10.201: icmp_seq=2 ttl=63 time=77.5 ms
64 bytes from 192.168.10.201: icmp_seq=3 ttl=63 time=75.1 ms

It looks like the NAT router doesn't route just the ping reply, possibly because it never saw the forward ping packet — and I tried to see if it has a stateful firewall that can be disabled, but it does not.

I then went on another machine 192.168.10.207 and created a static route on itself specifically for 10.8.0.0/24 via 192.168.10.101 (overrides the NAT router):

route add -net 10.8.0.0 netmask 255.255.255.0 gw 192.168.10.101

And then ping'ing 192.168.10.207 from client2 worked fine.

Isn't there a way to avoid creating static rules on every local machine in the client1 LAN? Should the rule on the NAT router just work, but for some reason it does not?

Best Answer

Do not forget configuing client1 as a gateway (packet forwarder). You can verify that with

# sysctl  net.ipv4.ip_forward

It should have a value of 1. If it does not, please configure it

# sysctl -w net.ipv4.ip_forward=1

You can also access this value checking / changing /proc/sys/net/ipv4/ip_forward

Related Topic