Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set-default-gateway blocking routing issue #435

Open
lrodorigo opened this issue Jan 7, 2024 · 10 comments
Open

set-default-gateway blocking routing issue #435

lrodorigo opened this issue Jan 7, 2024 · 10 comments

Comments

@lrodorigo
Copy link

lrodorigo commented Jan 7, 2024

I noticed that setting the set-default-gateway: true option creates a sort of "routing hole" since the vpn packets are routed via the "default gateway" (which is the VPN itself), the first "Ping" is lost and the VPN disconnects.

There are multiple ways to solve the issue, such as:

  1. Add a specific route (after the DNS resolution of the server):
    ip route add <SERVER IP>/32 via <PREVIOUS_DEFAULT_GW>

Basic idea:

#!/bin/bash
TARGET_HOST="wsvpn.myhost.com"
VPN_IP="192.168.9.1"
while true; do
    TARGET_HOST_IP=$(nslookup "$TARGET_HOST" | grep -A1 "Name:" | tail -n 1 | awk '{print $2}')
    OLD_GW=$(route -n | grep -v $VPN_IP | grep "0.0.0.0" | head -n 1 | awk '{print $2}')

    ip route add $TARGET_HOST_IP via $OLD_GW
    
    ./wsvpn-linux-amd64 --mode client --config client.yaml

    echo "VPN Disconnected - Deleting route"
    
    ip route del $TARGET_HOST_IP || /bin/true

    sleep 5

done
  1. Fw Mark + IP tables (look at Wireguard docs https://www.wireguard.com/netns/, section Routing All Your Traffic)

NOTE:
An additional issue when using the automatic reconnection is that, after the first disconnection, the DNS resolution is also routed on the (disconnected) VPN gateway, so after the first disconnection, the connections drops forever and it is not able to connect again.

@Doridian
Copy link
Owner

Doridian commented Jan 7, 2024

For 2: Wireguard's connection marking code seems to be implemented in Go here: https://git.zx2c4.com/wireguard-go/tree/conn/mark_unix.go
I should be able to make a similar implementation in WSVPN.

There is also 3: Run the VPN as a specific dedicated UID and use iptables UID filtering (-m uid --uid-owner X matcher)

@lrodorigo
Copy link
Author

lrodorigo commented Jan 7, 2024

Good catch for IP Tables.

Packet marking it is a really neat solution... I would like to contribute on this fantastic project, but my Go knowledge is quite limited, sorry.

Just an additional note:
consider that when the automatic reconnection is enabled, the DNS resolution of the server address must be performed using the "previous" default-gateway...

@Doridian
Copy link
Owner

Doridian commented Jan 7, 2024

Firewall marking has now been released in v5.35.0 :)
There isn't much more that can be done from WSVPN's end so I will be closing this issue.

@Doridian Doridian closed this as completed Jan 7, 2024
@lrodorigo
Copy link
Author

I think that when using the default GW option, wsvpn itself should setup the right ip rules, in order to route all the non-marked traffic on the vpn gateway and all the marked traffic on the old default GW... or an handler.sh script could be provided.

Moreover:
is also the DNS resolution traffic marked?
I think that is better to manually resolve the server hostname before changing the default GW.

@Doridian
Copy link
Owner

Doridian commented Jan 7, 2024

@lrodorigo For WSVPN to actually set rules/routing itself, it would require a lot more logic, such as determining what the default gateway interface is. I do not think I have the time available to spearhead such an effort.

As for the DNS traffic issue: WSVPN only reroutes the gateway once it has successfully connected, therefor DNS traffic should not need to be marked. (Furthermore, in most cases your DNS server should be on your LAN, which has a more specific route and therefor does not get rerouted)

@lrodorigo
Copy link
Author

lrodorigo commented Jan 7, 2024 via email

@Doridian Doridian reopened this Jan 7, 2024
@Doridian
Copy link
Owner

Doridian commented Jan 7, 2024

@lrodorigo Yeah, fair point. Maybe we could modify the ip route commands to exclude marked traffic, or only add rotues for non-marked traffic. I didn't work with those rules in a while.

As for the DNS issue, yeah that makes sense with reconnection. I could try marking DNS traffic as well, but WSVPN currently does not handle DNS resolutions on its own, so that would have to be a change with some involvement as well.

@lrodorigo
Copy link
Author

lrodorigo commented Jan 7, 2024

I know that handling manual DNS resolution is cumbersome, at this point an external bash script could do the job, and you can make mutually exclusive the automatic reconnection and the default gateway options.
It is important that the routes are properly reverted on wsvpn termination.

https://ro-che.info/articles/2021-02-27-linux-routing
Well written doc about the wireguard routing and the handling of the ip rule table and prefix length suppressor.

@Doridian
Copy link
Owner

@lrodorigo I found a way to do this in Golang for DNS as well, see the newest release https://github.com/Doridian/wsvpn/releases/tag/v5.36.0

WSVPN will (or, should) properly revert the routing table once it terminates and deletes its interface.

@lrodorigo
Copy link
Author

lrodorigo commented Jan 13, 2024

Great work, I am going to test it as soon as possible.

I am using wsvpn as startup systemd service, I am routing all my network traffic and it is great... Really stable and fast.
Often I forgot that I am behind an 'home built' vpn.

I will try to contribute with an example handler script that routes all non marked traffic on the wsvpn gateway.

Many thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants