qdm12 / gluetun

VPN client in a thin Docker container for multiple VPN providers, written in Go, and using OpenVPN or Wireguard, DNS over TLS, with a few proxy servers built-in.
https://hub.docker.com/r/qmcgaw/gluetun
MIT License
7.42k stars 350 forks source link

Feature request: default gateway configuration #1697

Open reinar opened 1 year ago

reinar commented 1 year ago

What's the feature 🧐

In case vpn service is providing nat-pmp for port forwarding (ProtonVPN. for example) downstream services would need an indication what is our actual default gateway capable of port forwarding (be it rtnetlink requests or just parsing ip route or something), which is not clear from the routing table (note - I'm using wireguard, maybe with openvpn it's different). In my case wireguard server gateway is 10.2.0.1, tun0 is 10.2.0.2.

/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.29.0.1      0.0.0.0         UG    0      0        0 eth0
10.2.0.0        *               255.255.255.252 U     0      0        0 tun0
172.29.0.0      *               255.255.0.0     U     0      0        0 eth0

I'm able to do ip route replace default via 10.2.0.1 dev tun0, which explicitly forwards all traffic to the tunnel.

/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         10.2.0.1        0.0.0.0         UG    0      0        0 tun0
10.2.0.0        *               255.255.255.252 U     0      0        0 tun0
172.29.0.0      *               255.255.0.0     U     0      0        0 eth0

But there's no way of automating this, from what I can see default gateway is detected on the start and applied automatically. Can we make this configurable somehow? Also this will act as a natural kill switch since in case uplink is broken traffic is naturally not going anywhere w/o any additional iptables rules - tun0 is our default gateway.

Please let me know if I'm missing something and thank you for your work.

1488 - somehow related. Of course you can maintain separate natpmpc binary, but a lot of software is perfectly capable to work with nat-pmp on it's own, it only needs an idea where to submit port forwarding request (something you tell explicitly to natpmpc). Basically any libtorrent-based software will work, I've tested it with libtorrent 2.0.9

Extra information and references

No response

qdm12 commented 1 year ago

Did you get that information from execing in Gluetun? Running with route only gives me

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 eth0

On the other hand, ip -c route show table all gives a lot more information.

ip route replace default via 10.2.0.1 dev tun0 would definitely be interesting πŸ‘

I am working on extracting the vpn gateway from this (see https://github.com/qdm12/gluetun/issues/1488#issuecomment-1611439732) which is a must the way I see it, for both port forwarding and to replace the default route as you did.

1488 - somehow related. Of course you can maintain separate natpmpc binary, but a lot of software is perfectly capable to work with nat-pmp on it's own, it only needs an idea where to submit port forwarding request (something you tell explicitly to natpmpc). Basically any libtorrent-based software will work, I've tested it with libtorrent 2.0.9

I actually implemented the natpmp client side of the protocol myself πŸ˜‰ So it's built-in the gluetun Go binary, there is no separate natpmpc binary. And yes, indeed a few programs/images have natpmp feature built-in, but it's a nice to have within gluetun I think, especially when the vpn fails and would reconnect etc.

qdm12 commented 1 year ago

76a92b90e3167f49ad5f53d7c6108a8bac1f3416 should now extract the vpn gateway. It works as follows (not necessarily bullet proof, but worth trying):

  1. Find all routes using the vpn link (tun0 usually)
  2. If the route destination is unspecified (0.0.0.0/0), then the vpn gateway is the route gateway (OpenVPN case, as before)
  3. If the route destination is a single IP address (like 10.2.0.2/32), the route destination ip is the same as the source ip (10.2.0.2), and the route table is local (255), then the vpn gateway is that source ip 10.2.0.2 with its last byte changed to 1. This looks like it should be working for Wireguard and especially for #1488
reinar commented 1 year ago

Did you get that information from execing in Gluetun? Running with route only gives me

Yes, I've put WIREGUARD_ADDRESSES=10.2.0.2/30 into env for gluetun and this route gets there automatically (not sure if intended πŸ˜‚), but this is nice and right behavior - wireguard should set up routing in case interface was set to something different than /32. Don't mind 192.168.0.0/16, this is my other docker config.

# docker exec -it gluetun /bin/sh
/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.80.1    0.0.0.0         UG    0      0        0 eth0
10.2.0.0        *               255.255.255.252 U     0      0        0 tun0
192.168.80.0    *               255.255.240.0   U     0      0        0 eth0

Not sure how portable it is, didn't set up openvpn for many years, but I'd imagine it will need to set up routing table in a similar fashion. In principle, I think it would be more straightforward to ask users to set up their interfaces to /30 and then gluetun would be able to get destination from tun0 in a simpler way without non-main tables lookup, but your option works well too.