0

I just installed openvpn on my server and my client. It seems to work fine.

Now, I would like to route all the traffic from my client through my VPN server, over internet, on demand, just in some cases, NOT ALWAYS !

my client    <->    routeur    <->    internet    <->    vpn server
192.168.5.3       192.168.5.1                            public IP
192.168.100.6        <------- vpn -------->            192.168.100.1

I'm able to route the traffic to an IP address (google) and ping it:

# ip route add 142.251.209.46 dev tun0 && ping -c 4 142.251.209.46 && ip route del 142.251.209.46 dev tun0
PING 142.251.209.46 (142.251.209.46) 56(84) octets de données.
64 octets de 142.251.209.46 : icmp_seq=1 ttl=107 temps=176 ms
64 octets de 142.251.209.46 : icmp_seq=2 ttl=107 temps=176 ms
64 octets de 142.251.209.46 : icmp_seq=3 ttl=107 temps=176 ms
64 octets de 142.251.209.46 : icmp_seq=4 ttl=107 temps=205 ms

--- statistiques ping 142.251.209.46 ---
4 paquets transmis, 4 reçus, 0 % paquets perdus, temps 3004 ms
rtt min/moy/max/mdev = 175,987/183,345/204,848/12,415 ms

But when I try to route all the traffic, with

ip route add default dev tun0

I can't ping anything on internet. And

# ip route add default via 192.168.100.1
Error: Nexthop has invalid gateway.
# ip route add default via 192.168.100.1 dev tun0
Error: Nexthop has invalid gateway.

I tried a lot of ways without any success.

# ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host proto kernel_lo 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether a8:a1:59:53:9b:9e brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.3/24 brd 192.168.5.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::aaa1:59ff:fe53:9b9e/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
6: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 192.168.100.6 peer 192.168.100.5/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::9295:73d5:f4b0:b892/64 scope link stable-privacy proto kernel_ll 
       valid_lft forever preferred_lft forever
# ip route list
default via 192.168.5.1 dev eth0 metric 2 
192.168.5.0/24 dev eth0 proto kernel scope link src 192.168.5.3 
192.168.100.1 via 192.168.100.5 dev tun0 
192.168.100.5 dev tun0 proto kernel scope link src 192.168.100.6

after reboot without vpn:

# ip route list
default via 192.168.5.1 dev eth0 metric 2 
192.168.5.0/24 dev eth0 proto kernel scope link src 192.168.5.3

In case my request is not clear enough for everyone, I will clarify. I want to route all traffic from my client to the VPN server WHEN I DECIDE TO. I want to be able to open a terminal, type an ip route... command and have all the traffic pass through the VPN, then open my terminal again type another ip route... command and have all the traffic go through my gateway again. That's all.

openvpn conf server:

tls-server
port 12112
proto udp
dev tun
ca keys/ca.crt
cert keys/vps1.crt
key keys/vps1.key
dh keys/dh.pem
server 192.168.100.0 255.255.255.0
persist-key
persist-tun
ifconfig-pool-persist ipp.txt
keepalive 10 120
user nobody
group nobody
status openvpn-status.log
log /var/log/openvpn/openvpn.log
verb 4

openvpn conf client:

client
dev tun
proto udp
remote SERVER_IP 12112
resolv-retry 30
nobind
persist-key
persist-tun
ca keys/ca.crt
cert keys/client.crt
key keys/client.key
script-security 2
log /var/log/openvpn/openvpn.log
verb 4
2
  • 192.168.100.1 via 192.168.100.5 looks weird. Could you provide a clean ip route list after a reboot? With and without VPN active.
    – Bob
    Commented Nov 1, 2023 at 6:49
  • @Bob edited, after reboot, with and without VPN active. I added too openvpn config. Something wrong there? Could you tell me what could be the right ip route... command to do what I want please?
    – Chris972
    Commented Nov 1, 2023 at 14:44

1 Answer 1

0

I suspect you need vpn_public_ip via original_gateway, i.e. vpn_public_ip via 192.168.5.1. Because when you replace the original default route, it then has no valid route to reach the VPN server.


When you configure default via vpn_internal_gateway, it will try to send all traffic that does not have a more specific route through the VPN. This becomes a bit of a problem because the VPN client itself needs to be able to communicate with its server (or other peers in the case of Wireguard).

Let's use an example:

Let's say your VPN server is hosted on 203.0.113.5. Let's also say your VPN assigns its client the address 192.168.100.6 and its server/internal gateway 192.168.100.1.

Let's say you make this your routing table:

default via 192.168.100.1
192.168.100.0/24 dev tun0 scope link src 192.168.100.6

Here's what happens if you try to make a request to 198.51.100.123 (target website/etc.):

  1. To send a packet to 198.51.100.123 (target website/etc.), the most specific match in the routing table is picked. In this case it is default because there is no more specific match, so it forwards the packet on to 192.168.100.1.

  2. To reach 192.168.100.1 it finds that the 192.168.100.0/24 subnet is on a local network, and therefore does not need to be routed. It can send that packet directly out via the relevant interface.

  3. The interface is actually a software NIC (a tun device) that is handled by your VPN software. So the packet reaches your VPN software, which then realises it needs to send it on to the other end of the VPN tunnel.

  4. Your VPN software encapsulates the packet in another packet, this time addressed to the VPN server: 203.0.113.5. This is then sent towards the VPN server for further processing.

  5. So now we need to send a packet to 203.0.113.5 (VPN server). Again the most specific match in the routing table is picked. Again it is default, which is via 192.168.100.1.

Do you see the problem here? Your VPN server is now trying to send the original packet (destination 198.51.100.123) encapsulated in another packet (destination 203.0.113.5, the VPN server), but it's being sent via 192.168.100.1 (the VPN gateway), which then reaches the VPN software which encapsulates the packet and tries to send it to the VPN server at 203.0.113.5, which then ...

Yup, we got stuck in a loop. Because it's trying to send the encapsulated packet to the VPN server but instead reaches the client software which only knows to encapsulate any packets received to that interface and send it onwards via the same method that just reached itself.

So how do we fix this?

default via 192.168.100.1
192.168.100.0/24 dev tun0 scope link src 192.168.100.6
203.0.113.5 via 192.168.5.1
192.168.5.0/24 dev eth0 scope link src 192.168.5.3

Notice there's two additional entries.

The first new line is quite important: it tells the system that 203.0.113.5 (VPN public IP) should be sent via 192.168.5.1, i.e. the original default gateway that (presumably) leads directly to the public internet, and not via the VPN. This makes sure that the VPN client can always reach the VPN server and does not try to send encapsulated packets (destined to the VPN server) through itself. Because this rule is more specific, it has precedence over the default one.

The last one should already be there by default and effectively tells the system that your LAN is a local network and should be reachable directly without routing. This line is necessary for the system to locate the gateway 192.168.5.1.


As an addendum, there's a more convenient way to add a high-priority 'default' route without having to delete and later re-create the original default. Consider this routing table:

default via 192.168.5.1
192.168.100.0/24 dev tun0 scope link src 192.168.100.6
203.0.113.5 via 192.168.5.1
192.168.5.0/24 dev eth0 scope link src 192.168.5.3
0.0.0.0/1 via 192.168.100.1
128.0.0.0/1 via 192.168.100.1

Notice that we've left the default alone. But this still routes everything (except the VPN public IP) through the VPN! How?

default is actually equivalent to 0.0.0.0/0, which covers all addresses. Remember earlier how we said the most specific match wins? Turns out the 0.0.0.0/0 space can be split into two halves. The pair of networks 0.0.0.0/1 and 128.0.0.0/1 identify the two halves. Together, they cover the entire 0.0.0.0/0 network but because they are separate entries, individually they are considered more specific.

Long story short, those two lines:

0.0.0.0/1 via 192.168.100.1
128.0.0.0/1 via 192.168.100.1

effectively override the default route. But the advantage of this approach is you don't need to delete the actual default, you can make your scripts simply add or remove the two new lines and leave everything else alone.

4
  • Sorry but I don't understand. On the client ?
    – Chris972
    Commented Nov 1, 2023 at 14:37
  • It seems like you're so right and it shows how much I don't understand any of this. It's obvious. THANKS !
    – Chris972
    Commented Nov 1, 2023 at 14:59
  • @Chris972 I've added an extended explanation. I wrote the original answer on my phone while sitting on a train, so didn't really feel like writing a short novel at the time...
    – Bob
    Commented Nov 1, 2023 at 16:59
  • I'm going to need time to read this and understand, especially since my English is very average. But I promise, I will do it. Thanks again.
    – Chris972
    Commented Nov 1, 2023 at 20:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .