What's new

WireGuard DNS Traffic From All Clients Sent Over First WireGuard Client Connection

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

HarryMuscle

Senior Member
I've completely rewritten this post to better explain the issue ...

I have several WireGuard VPN connections setup with different clients directed through each VPN connection. Here's an illustrated view of the setup:

Code:
192.168.1.2 -> VPN Tunnel #1 -> Germany
192.168.1.3 -> VPN Tunnel #2 -> France
192.168.1.4 -> VPN Tunnel #3 -> USA

When I specify a DNS server to use for each of those WireGuard VPN connections, the router software automatically adds the following iptables rules to enforce the use of those DNS servers.

Code:
-A PREROUTING -p tcp -m tcp --dport 53 -j DNSVPN
-A PREROUTING -p udp -m udp --dport 53 -j DNSVPN
-A DNSVPN -s 192.168.1.2/32 -j DNAT --to-destination 1.1.1.1
-A DNSVPN -s 192.168.1.3/32 -j DNAT --to-destination 1.1.1.1
-A DNSVPN -s 192.168.1.4/32 -j DNAT --to-destination 1.1.1.1

The issue happens when I specify the same DNS server for each of the VPN connections (using 1.1.1.1 in this example). The router adds this route for the DNS server in question:

Code:
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
1.1.1.1         *               255.255.255.255 UH    0      0        0 wgc1

This seems to send all of the traffic destined to this DNS server over the first WireGuard VPN connection which obviously isn't what should be happening. I believe there are also other routes involved in making sure that each of the above IP addresses send all of their traffic over the various VPN interefaces, however, I haven't figured out which ones yet. If anyone has any input on this and possibly any suggestions on how to enable the ability to use the same DNS server for multiple VPN connections that would be greatly appreciated.

Thanks,
Harry
 
Last edited:
I'm not 100% sure but I think Asus adds a route to dns, whilst @RMerlin adds a dnat rule instead. So, this route may be some left-over?
Sure seems that way. If I delete all of the routes related to the DNS servers for the VPN clients everything starts to work correctly. Also if you take a look at the actual routes it definitely seems like this is some left over and/or a bug. For example, routes for client X will be present in the default table and all client route tables that are numerically higher than X, meaning that the DNS routes for client X are never present in its own table, only the default and other clients' tables.
 
Sure seems that way. If I delete all of the routes related to the DNS servers for the VPN clients everything starts to work correctly. Also if you take a look at the actual routes it definitely seems like this is some left over and/or a bug. For example, routes for client X will be present in the default table and all client route tables that are numerically higher than X, meaning that the DNS routes for client X are never present in its own table, only the default and other clients' tables.
After giving it a bit more thought I think I might actually understand the logic behind how these rules are supposed to work. I don't think it's left overs or a bug anymore, but it sets things up in a way that's counter to how most people will expect things to work. I think the logic is that if you enter a specific DNS server for client X it assumes that you want all traffic from your LAN that is destined to this DNS server to go over the client X connection. This makes sense if for example you are connecting two offices together via a WireGuard VPN connection. You would want things to work this way because if you are trying to resolve clients in office 2 from office 1 you always want to use the VPN connection to send traffic to the DNS server in office 2. However, I'm pretty sure that's the minority of situations. Most people will be using the WireGuard VPN clients with VPN providers which usually only offer 2 DNS servers or you might be using it with commercial DNS servers like 1.1.1.1 for example and you want each connection to send traffic to the DNS server through their own connection.
 
For anyone who would like the traffic to the VPN client's configured DNS server to actually use the VPN client, here's a script that will remove the routes explained in my previous post:

Code:
#!/bin/ash

# Loop through all of the WireGuard VPN clients
client=1
while [[ $client -le 5 ]]
do
  # Check if this VPN client is enabled
  if [[ "$(nvram get wgc${client}_enable)" == "1" ]]
  then
    # Get the DNS server for this VPN client
    dns="$(nvram get wgc${client}_dns)"

    # Check if this VPN client has a valid DNS server configured
    # Note: the DNS server used via a VPN client is enforced via VPN Director iptables rules so the
    #       code below deletes DNS server routes that route all traffic via the first VPN client
    #       that is configured with a specific DNS server (ie: if VPN client 1 and 2 are both
    #       configured with the same DNS server, all traffic to that DNS server will be routed
    #       through VPN client 1)
    if echo "$dns" | grep -E -q -x "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
    then
      # Check if the DNS server route exists in the default table
      if [[ "$(ip route list ${dns} dev wgc${client} scope link)" != "" ]]
      then
        # Delete the DNS server route in the default table
        ip route del $dns dev wgc${client} scope link
      fi

      # Loop through the route tables for VPN clients that are numerically larger than the current
      #   VPN client
      table=$(( client + 1 ))
      while [[ $table -le 5 ]]
      do
        # Check if the VPN client for this table is enabled
        if [[ "$(nvram get wgc${table}_enable)" == "1" ]]
        then
          # Check if the DNS server route exists in this table
          if [[ "$(ip route list ${dns} dev wgc${client} scope link table wgc${table})" != "" ]]
          then
            # Delete the DNS server route in this table
            ip route del $dns dev wgc${client} scope link table wgc${table}
          fi
        fi

        # Increase the table counter  
        table=$(( table + 1 ))
      done
    fi
  fi

  # Increase the client counter  
  client=$(( client + 1 ))
done

exit 0
 
Instead of dealing with these, delete the DNS address entries in the WireGuard client files and type the DNS address you want to use in the relevant field in the DNS directory, then configure your devices to use the DNS address you added. Or add the desired DNS address to the DHCP server settings.

Don't these methods ensure that your devices make DNS queries through the WireGuard tunnel they belong to?
 
Instead of dealing with these, delete the DNS address entries in the WireGuard client files and type the DNS address you want to use in the relevant field in the DNS directory, then configure your devices to use the DNS address you added. Or add the desired DNS address to the DHCP server settings.

Don't these methods ensure that your devices make DNS queries through the WireGuard tunnel they belong to?
It would but it's an approach that requires changes on every single device using the VPN tunnel and is prone to end user error which could result in leaking your location.
 
For anyone who would like the traffic to the VPN client's configured DNS server to actually use the VPN client, here's a script that will remove the routes explained in my previous post:

Code:
#!/bin/ash

# Loop through all of the WireGuard VPN clients
client=1
while [[ $client -le 5 ]]
do
  # Check if this VPN client is enabled
  if [[ "$(nvram get wgc${client}_enable)" == "1" ]]
  then
    # Get the DNS server for this VPN client
    dns="$(nvram get wgc${client}_dns)"

    # Check if this VPN client has a valid DNS server configured
    # Note: the DNS server used via a VPN client is enforced via VPN Director iptables rules so the
    #       code below deletes DNS server routes that route all traffic via the first VPN client
    #       that is configured with a specific DNS server (ie: if VPN client 1 and 2 are both
    #       configured with the same DNS server, all traffic to that DNS server will be routed
    #       through VPN client 1)
    if echo "$dns" | grep -E -q -x "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
    then
      # Check if the DNS server route exists in the default table
      if [[ "$(ip route list ${dns} dev wgc${client} scope link)" != "" ]]
      then
        # Delete the DNS server route in the default table
        ip route del $dns dev wgc${client} scope link
      fi

      # Loop through the route tables for VPN clients that are numerically larger than the current
      #   VPN client
      table=$(( client + 1 ))
      while [[ $table -le 5 ]]
      do
        # Check if the VPN client for this table is enabled
        if [[ "$(nvram get wgc${table}_enable)" == "1" ]]
        then
          # Check if the DNS server route exists in this table
          if [[ "$(ip route list ${dns} dev wgc${client} scope link table wgc${table})" != "" ]]
          then
            # Delete the DNS server route in this table
            ip route del $dns dev wgc${client} scope link table wgc${table}
          fi
        fi

        # Increase the table counter
        table=$(( table + 1 ))
      done
    fi
  fi

  # Increase the client counter
  client=$(( client + 1 ))
done

exit 0
So it turns out if you're deleting the rules via the wgclient-start script you don't actually need to loop through the other clients' route tables to delete anything. The other clients only create routes in their own tables if a DNS route already exists in the default table. If we delete the route in the default table in the wgclient-start script, when the next client starts up it simply creates the rule again in the default table (instead of it's own) and we just again delete it via the script. And so on.

So here's the new and improved script that also checks if other client's have the same DNS server configured to only "mess" with routes if absolutely necessary:
Code:
#!/bin/ash

# Get the DNS server for this WireGuard client
dns="$(nvram get wgc${1}_dns)"

# Check if this WireGuard client has a valid DNS server configured
# Note: the DNS server used via a WireGuard client is enforced by the VPN Director iptables rules so
#       the code below deletes DNS server routes that route traffic via the first WireGuard client
#       that is configured with a specific DNS server (ie: if WireGuard client 1 and 2 are both
#       configured with the same DNS server, all traffic to that DNS server will be routed through
#       WireGuard client 1)
if echo -n "$dns" | grep -E -q -x "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
then
  # Loop through the other WireGuard clients to check if any have the same DNS server configured
  same=0
  client=1
  while [[ $client -le 5 ]]
  do
    # Check if this client is the current loop client
    if [[ $1 == $client ]]
    then
      # Increase the client counter
      client=$(( client + 1 ))

      # Continue to the next client
      continue
    fi

    # Check if this client's DNS server is the same as the current loop client's DNS server
    if [[ "$dns" == "$(nvram get wgc${client}_dns)" ]]
    then
      # Set the same flag
      same=1

      # Stop looping through the clients
      break
    fi

    # Increase the client counter
    client=$(( client + 1 ))
  done

  # Check if we found any WireGuard clients with the same DNS server configured
  if [[ $same == 1 ]]
  then
    # Check if the DNS server route exists in the default table
    if [[ "$(ip route list ${dns} dev wgc${1} scope link)" != "" ]]
    then
      # Delete the DNS server route in the default table
      logger -p "user.info" -t "wgclient-start" "Deleting WireGuard client #${1} DNS route ..."
      ip route del $dns dev wgc${1} scope link
    fi
  fi
fi

exit 0
 
Last edited:

Similar threads

Latest threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top