Skip to content

Instantly share code, notes, and snippets.

@Nithanim
Created November 28, 2020 15:33
Show Gist options
  • Save Nithanim/9204f562a40847d6336538e6b19fbe3c to your computer and use it in GitHub Desktop.
Save Nithanim/9204f562a40847d6336538e6b19fbe3c to your computer and use it in GitHub Desktop.
Allow binding a specific program to wireguard for full internet access

This config allows the usage of a dedicated interface from wireguard (or openvpn or whatever) to be used by programs without tunneling all internet traffic to it (default gateway). The program must be able to bind to a specific network interface (the one from wireguard or openvpn). Since only one default route can exist, we use the fact that with iproute2 it is possible to have muliple routing tables where one default route for each table is allowed. The findigns are based on the article here: https://www.thomas-krenn.com/de/wiki/Zwei_Default_Gateways_in_einem_System

Pre-defined (rather "named") tables can be found in /etc/iproute2/rt_tables. This file holds a mapping between the id and the name (separated by whitespace). In commands these names can be used instead of the id but this is not required but might be easier to remember what table is used for what connection. Pretty much any free id can be used. If you look closely when using the wireguard default routing, you can see table 51821 in the output which means that the table with id 51821 is used automatically.

The most important part of the wireguard config is the AllowedIPs bit, it MUST be 0.0.0.0/0 (plus ipv6 decl if needed) because this also acts as a packet filter inside wireguard! However, by using this, wireguard assumes that you want to route everything ands sets up a default gateway for all you traffic. Therefore, Table = off is used to prevent automatic creation of routs and rules.

The most crucial part is the PostUp where we now can insert our own routs and rules. We pretty much want the following, assuming that the Address is 10.69.159.188 and using routing table with id 1007:

ip route add default dev %i table 1007
ip route add 10.69.159.188/32 dev %i src 10.69.159.188 table 1007
ip rule add from 10.69.159.188/32 table 1007
ip rule add to 10.69.159.188/32 table 1007

I don't really know how or why this works but it does for me. What I could not find out is, if there is a placeholder that holds the ip address which would make it a lot more convenient than replacing the ipaddress everywhere. %i holds the name of the interface, e.g. wg0. To add this to the wireguard config, it has to be put in PostUp but these are multiple commands, so we just put them in one long line separated by ;.

The program that should use the interface must den bind itself to the interface. Ping for example has the -I flag accepting the ip address of the interface. In our example this would be ping -I 10.69.159.188 8.8.8.8 resulting in pinging 8.8.8.8 over the wireguard interface instead of the default one. For curl this can be achieved by curl --interface 10.69.159.188 http://myexternalip.com/raw.

[Interface]
PrivateKey = 46346346346343646334
Address = <addr>/32
Table = off
PostUp = ip route add default dev %i table <table>; ip route add <addr>/32 dev %i src <addr> table <table>; ip rule add from <addr>/32 table <table>; ip rule add to <addr>/32 table <table>;
[Peer]
PublicKey = 234234234234234234423234
AllowedIPs = 0.0.0.0/0
Endpoint = 23423432432432423
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment