Tools: Using Tailscale and ProtonVPN side-by-side on Linux

Tools: Using Tailscale and ProtonVPN side-by-side on Linux

Source: Dev.to

Disclaimer ## Introduction ## Materials and Methods ## Basic configuration for systemd-networkd ## Wired connection ## Wireless connection ## Installing Tailscale ## Understanding iprules ## Configuring Wireguard VPN ## Generating Proton VPN configuration file ## Creating a Wireguard Connection ## [Extra] Setting your AdGuard Home / PiHole as your DNS server ## [Extra] Using ufw as a killswitch ## [Extra] Configuring IP based split tunnels ## [Extra] Creating multiple Wireguard configuration for easy swap This article is a review of my personal configuration. Although I will try my best to describe each step to replicate the results I achieved, I can't guarantee that it will work on every system, so follow it at your own risk. I highly advise against configuring it over the network/headless (such as ssh connection), because a misconfiguration can lead to loss of connection until fixed. But the final result will allow running both VPNs on a headless setup. Note that while I have some familiarity with technology, I am no expert in system security and I don't know what the possible consequences can be (such as packet/DNS leaks). I welcome every one to point suggestions and improvements to the setup, so we, together, can create an useful and safe setup for the community to use :). This setup came from the motivation of running Proton VPN and Tailscale VPN alongside with each other. For me, each one of them serves a different purpose: Proton VPN allows me to access the web privately, while Tailscale offers security while connecting to my personal LAN/home lab. The tools chosen to create such configuration came from the idea of utilizing the least amount of package requirements possible, since I keep pushing myself on creating minimal setups, to utilize the least amount of RAM and energy as possible. Before this setup I would configure each of my devices individually to access both VPNs, but I had multiple instances where a Proton VPN server would go down and I found myself having to reconfigure every device to a new server (which was kind of painful, since my router can't work as a VPN client). Setting one device as an Tailscale exit node, while keeping it connected to Proton VPN, allowed me to centralize the configuration, where the changes to one device would be applied to the rest. Even though I am pretty satisfied with the final result, nothing is perfect. There's are some drawbacks to such setup: there's a noticeable loss of connection speed when having your connection going through multiple VPNs (for this setup, I would say around 20%, I am on a 700mbps link and I can reach around 550-600mbps using it), the dependency on one device to be constantly powered on and connected to the network (which is fairly common for home lab enthusiasts, so that shouldn't be a problem) and the dependency on the route chosen by Tailscale VPN (best results are found when devices are direct connected. There's a speed penalty when connection goes through relay servers). I will have some references for the steps described in this article, so anyone can check where the ideas came from and further explore new possibilities of this configuration. My setup was created using Arch Linux, so every package name and file paths will be as seen on an Arch Linux installation. For this article I will be using: For the extra sections of this article, I will be using ufw to explore the possibility of having a killswitch for the setup. Although I won't be able to provide much information on this part, since I am still experimenting with it, I believe it's possible to use it as a fairly good replacement for a proper killswitch. In case you have your own a DNS server, I will show how to use it as your exit node's primary DNS server. Systemd is one of the foundations of most Linux distributions nowadays. It's a set of tools to manage services, containers, networks, logs and other system resources[1]. Since it's present by default on Arch Linux, I try to use (and abuse) it as much as I can. The Arch Wiki has a detailed article on how to setup networks using it[2], but in this article I will try to go through the basic to get the setup up and running. This configuration should only be done to the device that will be running as the exit node. Other devices can be configured to your liking, as long as it's set to use the exit node via Tailscale. [!WARNING] If you have any other software that manages network connections, such as NetworkManager, I advise uninstalling it, since it can conflict with the setup.[3]. If systemd is already installed, the first thing to do is to get the service running. This can be achieved by executing the following command: This command will enable both systemd-networkd and systemd-resolved services to auto-start on device boot, and the --now flag will also start for the current boot[4], so you can have both services started and running, so further configuration can be done. Since you will be using systemd-resolved for domain name resolution, you need to link its configuration to the commonly used configuration, /etc/resolv.conf, to make sure some programs won't run into problems[5]. This is achieved by creating the symbolic link: For the next steps, you will need to know the names of our network interfaces. They can be listed with the following command: For this article, I will use eno1 for the ethernet (wired) interface and wlan0 for the wireless interface, so replace them with the name of your interface. You don't need to configure both, only the one that you will be using. The configuration files are located at /etc/systemd/network/. That's the default place systemd looks for network configuration. There are two types of configuration files that it will be needed for this setup: .network[6] and .netdev[7]. The first one is used to setup how network interfaces will interact with the network, while the second one is to setup a network device (which is used to created Wireguard connections). The basic configuration for a wired connection would be creating a wired.network file at /etc/systemd/network/ with the following content[8]: Once the file is created, run the following commands to reload the configuration and reconfigure the network interface: This should be enough to give your device the ability to communicate with the DHCP server and connect to the internet. Please test your connection before going further. The basic configuration for a wireless connection would be creating a wireless.network file at /etc/systemd/network/ with the following content[9]: Once the file is created, run the following commands to reload the configuration and reconfigure the network interface: While systemd is able to manage network connections, it can't manage Wi-Fi credentials. For this, you can use iwd[10]. Once installed, you can run it[11] and then connect to your preferred network[12]. Please test your connection before going further. Tailscale offers a tutorial on how to install their services on Linux[13]. If you are using Arch Linux, you can refer to the Arch Wiki[14]. Once you get your device connected to your tailnet, run the following commands to proper advertise your device as an exit node[15]: You also need to go to the Admin Console, on Tailscale dashboard, and allow the device to be an exit node. If everything worked, you will see the offers exit node when prompting tailscale status. Now that Tailscale is installed, I will explain how I was able to run it alongside with another Wireguard VPN (in my case, Proton VPN). I am no expert on iprules, but messing around a bit, I was able to figure out a way to configure the priority of each network connection and have them both working graciously. If you run the following commands, you will see the ip rules that are currently configured on your setup: This should return something similar to: I have obscured some of the information, because I am not sure how critical it would be sharing them, but what matters here is the first number in each line. That's the priority of each rule. From messing with the configuration, I found that rules 5210 to 5270 are the ones used by Tailscale to route its traffic. The layout for the final setup would be something like: This way, the setup has Device 1 through 4 mutually connected via Tailscale VPN and Device 3 set as an exit node, communicating to the internet via Proton VPN. Note that if you ask Proton VPN to send a packet to address 100.100.100.100 (an example of tailnet device address), it wouldn't be able to do it, because Proton servers don't have access to your tailnet. So the setup needs to first check if the packet is to be sent to a tailnet device, if not it should send it to the internet instead, via Proton. That's when the IP rules come into play. The lower the priority of the rule, the sooner it will be checked. So when Proton VPN is configured, its rule priority needs to be higher than the last tailscale rule, but lower than main/default. Now that Tailscale is configured and a plan based on the IP rules is set, it's time to configure the Wireguard VPN. It should work for any Wireguard VPN, as long as you can generate a generic configuration file. I will use Proton VPN as an example, which is the provider I use. To generate a Wireguard configuration file, the following steps are done using their dashboard. Once in the dashboard, navigate on the left menu to the Wireguard section. This section is where you can generate Wireguard files to connect your device without using Proton's official app. For the first part, Give a name to the config to be generated, give a symbolic name to the configuration. This information won't matter much, but can be helpful if you want to invalidate the generated configuration later. For the second part, Select platform, select GNU/Linux. This shouldn't matter much, since it will only change the format of the output file, but selecting this option will be the closest to what you need. For the third part, Select VPN options, select the configuration you want to the VPN connection. Once the file is generated, you can't change these values, so explore the articles referred in the Learn More links to make sure you select the proper values for your taste. The default options should be the best for privacy. If, later, you want to change any of these settings, you would only need to generate a new file and edit the configuration that will be created later in this article. For the last part, Select a server to connect to, select the server where you want to connect your devices to. Same as last step, once selected, you can only swap servers by generating a new file. Later in the article, I will explain how you can have multiple files ready for easy server swap, if needed. Lastly, click on the Create button and this will generate a new configuration file. Download it, as it will be needed for the configuration. To create a Wireguard connection using systemd-networkd, two files will need to be created, as mentioned before: .network and .netdev. This section is heavily inspired by Ihor Kalnytskyi's tutorial[16]. These files will be created at the default configuration folder, /etc/systemd/network. First file to be created will be proton1.netdev, with the following content: The to-be-replaced values should be replaced by the values found for the same key in the file you generated and downloaded from Proton. The FirewallMark configuration is used to “tag” any packet originated by this Wireguard device. It will be used in the next configuration file. For the next file, it will be named proton1.network, with the following content: This file will configure how packets will use Proton network. A few configuration to be commented on: So it's set a priority higher than Tailscale, which means that it will be run later than Tailscale, and, since the InvertRule is present, it will use this network for any packet that is not originated from Proton, since it will be looking for packets without the FirewallMark that was created. This will guarantee that every packet will go through Proton VPN (unless it's a Tailscale packet). Last step is to guarantee that the setup won't be using the DHCP DNS server. To do this, Go to the file /etc/systemd/network/wired.network (or the wireless.network file) and add the following line inside the [Network] block: Now, to show the configured proton connection, run the following command: The new network device, proton1, should be visible when running command: If it's not, you can't try reloading systemd configuration files and restart systemd-networkd service: Now you can test your IP address and DNS leak to make sure all connections are going through proton connection. Do the same tests with the devices connected to your exit node device. If you already have an instance of AdGuard Home/PiHole and it's accessible by your device, you can set if as your default DNS server. In my setup, I have a quadlet running AdGuard Home on the same device, so here's how to use it. [!NOTE] Since it's being set as your exit node device DNS server, it will also be used by any device connected, using it as an exit node. To do this, go to the .network file that was created for proton's connection and edit the DNS entry with your DNS route: Now run the following commands to reconfigure the proton device and apply the changes: You can check which DNS servers are being used by running: If your AdGuard Home / PiHole is hosted on the same device that was configured as the exit node with Proton connection, you can set the upstream DNS server as seen in Proton's configuration file (ex. 10.2.0.1), to use Proton VPN DNS server. [!WARNING] Experimental: I haven't done much testing, but should be possible if configured right Ufw is a software for managing a netfilter firewall[17]. With it, you can allow or block connections based on IP, port or interface. [!CAUTION] You can create strict filters that would only allow connections you permitted. Note that Tailscale uses a wide range of IP addresses to function properly. Mapping them can be difficult and blocking needed connections can lead to unstable setups. Some of Tailscale's needed connections are documented here[18]. If you have ufw installed[19], you could run something like this to block, by default, any incoming and any outgoing packet: If you want to only allow packets going out via Proton device, you could do: Note that this would not be enough to get Proton connections working, because you need to allow outgoing packets on eno1 or wlan0 to Proton's IP address as well: Replace the with the same endpoint used in proton1 configuration file. This would be enough to block any connection not going to Proton. The same could be done to Tailscale, creating a hardened setup. You can configure IP based split tunnels using the combination of RoutingPolicyRule and Route previously seen. For this example, I will show how to connect to all LAN devices, without passing through either Tailscale or Proton. To achieve this, you need to edit the /etc/systemd/network/wired.network (or the wireless.network file) that was created and add the following: Adding this to the wired.network file, would make any connection going to the subnet 192.168.0.0/24 use eno1 device. Since the RoutingPolicyRule is set with priority 1, it would be executed before checking either Tailscale or Proton rules, so leaving the setup without using any VPN. You can create multiple RoutingPolicyRule to create complex configurations and multiple split tunnels[20]. After any change, run: Repeating the steps to create the Wireguard connection, you should be able to have multiple connections set, as long as you keep unique names (although only the one with lowest priority would be used). You could create proton2 from a new configuration file like: For this extra configuration, I added a new setting: ActivationPolicy[21]. This is used by systemd to know if the configuration should be started automatically or manually. The default value (if absent) is to automatically start the network. So having proton1 to automatically start, you can set numerous connections to manually start and swap them using following commands: This would swap the connection from the server configured in proton1 to the server configured in proton2. And since the device is being used as an exit node, it would also change to all its clients. https://wiki.archlinux.org/title/Systemd-networkd https://wiki.archlinux.org/title/Systemd-networkd#Required\_services\_and\_setup https://wiki.archlinux.org/title/Systemd#Using\_units https://wiki.archlinux.org/title/Systemd-resolved#DNS https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html https://www.freedesktop.org/software/systemd/man/latest/systemd.netdev.html https://wiki.archlinux.org/title/Systemd-networkd#Wired\_adapter\_using\_DHCP https://wiki.archlinux.org/title/Systemd-networkd#Wireless\_adapter https://wiki.archlinux.org/title/Iwd https://wiki.archlinux.org/title/Iwd#Usage https://wiki.archlinux.org/title/Iwd#Connect\_to\_a\_network https://tailscale.com/kb/1031/install-linux https://wiki.archlinux.org/title/Tailscale#Usage https://tailscale.com/kb/1103/exit-nodes?tab=linux#advertise-a-device-as-an-exit-node https://kalnytskyi.com/posts/setup-wireguard-client-systemd-networkd/ https://wiki.archlinux.org/title/Uncomplicated\_Firewall https://tailscale.com/kb/1082/firewall-ports https://wiki.archlinux.org/title/Uncomplicated\_Firewall#Installation https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#%5BRoutingPolicyRule%5D%20Section%20Options https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#ActivationPolicy= Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse COMMAND_BLOCK: sudo systemctl enable --now systemd-networkd.service systemd-resolved.service Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo systemctl enable --now systemd-networkd.service systemd-resolved.service COMMAND_BLOCK: sudo systemctl enable --now systemd-networkd.service systemd-resolved.service COMMAND_BLOCK: sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf COMMAND_BLOCK: sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf CODE_BLOCK: networkctl Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=eno1 # Replace with your network interface name [Network] DHCP=ipv4 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=eno1 # Replace with your network interface name [Network] DHCP=ipv4 COMMAND_BLOCK: [Match] Name=eno1 # Replace with your network interface name [Network] DHCP=ipv4 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure eno1 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure eno1 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure eno1 COMMAND_BLOCK: [Match] Name=wlan0 # Replace with your network interface name [Network] DHCP=ipv4 IgnoreCarrierLoss=3s Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=wlan0 # Replace with your network interface name [Network] DHCP=ipv4 IgnoreCarrierLoss=3s COMMAND_BLOCK: [Match] Name=wlan0 # Replace with your network interface name [Network] DHCP=ipv4 IgnoreCarrierLoss=3s COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure wlan0 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure wlan0 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure wlan0 CODE_BLOCK: echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf sudo sysctl -p /etc/sysctl.d/99-tailscale.conf sudo tailscale set --advertise-exit-node sudo tailscale up Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf sudo sysctl -p /etc/sysctl.d/99-tailscale.conf sudo tailscale set --advertise-exit-node sudo tailscale up CODE_BLOCK: echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf sudo sysctl -p /etc/sysctl.d/99-tailscale.conf sudo tailscale set --advertise-exit-node sudo tailscale up CODE_BLOCK: ip rule Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: 0: from all lookup local 5210: from all fwmark 0x12345/0xab1234 lookup main 5230: from all fwmark 0x12345/0xab1234 lookup default 5250: from all fwmark 0x12345/0xab1234 unreachable 5270: from all lookup 12 32766: from all lookup main 32767: from all lookup default Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: 0: from all lookup local 5210: from all fwmark 0x12345/0xab1234 lookup main 5230: from all fwmark 0x12345/0xab1234 lookup default 5250: from all fwmark 0x12345/0xab1234 unreachable 5270: from all lookup 12 32766: from all lookup main 32767: from all lookup default CODE_BLOCK: 0: from all lookup local 5210: from all fwmark 0x12345/0xab1234 lookup main 5230: from all fwmark 0x12345/0xab1234 lookup default 5250: from all fwmark 0x12345/0xab1234 unreachable 5270: from all lookup 12 32766: from all lookup main 32767: from all lookup default COMMAND_BLOCK: [NetDev] Name=proton1 Kind=wireguard [WireGuard] PrivateKey=<your-private-key> FirewallMark=1000 # theorically, you can set as any valid value [WireGuardPeer] PublicKey=<your-public-key> AllowedIPs=<your-allowed-ips> Endpoint=<your-endpoint> Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [NetDev] Name=proton1 Kind=wireguard [WireGuard] PrivateKey=<your-private-key> FirewallMark=1000 # theorically, you can set as any valid value [WireGuardPeer] PublicKey=<your-public-key> AllowedIPs=<your-allowed-ips> Endpoint=<your-endpoint> COMMAND_BLOCK: [NetDev] Name=proton1 Kind=wireguard [WireGuard] PrivateKey=<your-private-key> FirewallMark=1000 # theorically, you can set as any valid value [WireGuardPeer] PublicKey=<your-public-key> AllowedIPs=<your-allowed-ips> Endpoint=<your-endpoint> COMMAND_BLOCK: [Match] Name=proton1 [Network] Address=<your-address> DNS=<your-dns> DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 # Keep the same as previous file Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=proton1 [Network] Address=<your-address> DNS=<your-dns> DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 # Keep the same as previous file Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 COMMAND_BLOCK: [Match] Name=proton1 [Network] Address=<your-address> DNS=<your-dns> DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 # Keep the same as previous file Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 COMMAND_BLOCK: [Match] Name=eno1 [Network] DHCP=ipv4 DNSDefaultRoute=no # <--- This line Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=eno1 [Network] DHCP=ipv4 DNSDefaultRoute=no # <--- This line COMMAND_BLOCK: [Match] Name=eno1 [Network] DHCP=ipv4 DNSDefaultRoute=no # <--- This line COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure proton1 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure proton1 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure proton1 CODE_BLOCK: networkctl Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo systemctl daemon-reload sudo systemctl restart systemd-networkd.service Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo systemctl daemon-reload sudo systemctl restart systemd-networkd.service COMMAND_BLOCK: sudo systemctl daemon-reload sudo systemctl restart systemd-networkd.service COMMAND_BLOCK: [Match] Name=proton1 [Network] Address=<your-address> DNS=<your-dns> # <--- This line DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=proton1 [Network] Address=<your-address> DNS=<your-dns> # <--- This line DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 COMMAND_BLOCK: [Match] Name=proton1 [Network] Address=<your-address> DNS=<your-dns> # <--- This line DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure proton1 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure proton1 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure proton1 CODE_BLOCK: networkctl status Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: networkctl status CODE_BLOCK: networkctl status COMMAND_BLOCK: sudo ufw default deny incoming sudo ufw default deny outgoing Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo ufw default deny incoming sudo ufw default deny outgoing COMMAND_BLOCK: sudo ufw default deny incoming sudo ufw default deny outgoing COMMAND_BLOCK: sudo ufw allow out on proton1 from any to any Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo ufw allow out on proton1 from any to any COMMAND_BLOCK: sudo ufw allow out on proton1 from any to any COMMAND_BLOCK: sudo ufw allow out on eno1 from any to <your-proton-endpoint> Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo ufw allow out on eno1 from any to <your-proton-endpoint> COMMAND_BLOCK: sudo ufw allow out on eno1 from any to <your-proton-endpoint> COMMAND_BLOCK: [Match] Name=eno1 [Network] DHCP=ipv4 DNSDefaultRoute=no # vvvv ADDED LINES vvvv [RoutingPolicyRule] To=192.168.0.0/24 Table=1 Priority=1 [Route] Gateway=192.168.0.1 GatewayOnLink=yes Table=1 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=eno1 [Network] DHCP=ipv4 DNSDefaultRoute=no # vvvv ADDED LINES vvvv [RoutingPolicyRule] To=192.168.0.0/24 Table=1 Priority=1 [Route] Gateway=192.168.0.1 GatewayOnLink=yes Table=1 COMMAND_BLOCK: [Match] Name=eno1 [Network] DHCP=ipv4 DNSDefaultRoute=no # vvvv ADDED LINES vvvv [RoutingPolicyRule] To=192.168.0.0/24 Table=1 Priority=1 [Route] Gateway=192.168.0.1 GatewayOnLink=yes Table=1 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure eno1 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure eno1 COMMAND_BLOCK: sudo networkctl reload sudo networkctl reconfigure eno1 COMMAND_BLOCK: [NetDev] Name=proton2 Kind=wireguard [WireGuard] PrivateKey=<your-private-key> FirewallMark=1000 # theorically, you can set as any valid value [WireGuardPeer] PublicKey=<your-public-key> AllowedIPs=<your-allowed-ips> Endpoint=<your-endpoint> Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [NetDev] Name=proton2 Kind=wireguard [WireGuard] PrivateKey=<your-private-key> FirewallMark=1000 # theorically, you can set as any valid value [WireGuardPeer] PublicKey=<your-public-key> AllowedIPs=<your-allowed-ips> Endpoint=<your-endpoint> COMMAND_BLOCK: [NetDev] Name=proton2 Kind=wireguard [WireGuard] PrivateKey=<your-private-key> FirewallMark=1000 # theorically, you can set as any valid value [WireGuardPeer] PublicKey=<your-public-key> AllowedIPs=<your-allowed-ips> Endpoint=<your-endpoint> COMMAND_BLOCK: [Match] Name=proton2 [Link] ActivationPolicy=manual <--- NEW LINE [Network] Address=<your-address> DNS=<your-dns> DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 # Keep the same as previous file Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: [Match] Name=proton2 [Link] ActivationPolicy=manual <--- NEW LINE [Network] Address=<your-address> DNS=<your-dns> DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 # Keep the same as previous file Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 COMMAND_BLOCK: [Match] Name=proton2 [Link] ActivationPolicy=manual <--- NEW LINE [Network] Address=<your-address> DNS=<your-dns> DNSDefaultRoute=yes [RoutingPolicyRule] InvertRule=yes FirewallMark=1000 # Keep the same as previous file Table=6000 Priority=6000 [Route] Gateway=10.0.0.1 GatewayOnLink=yes Table=6000 COMMAND_BLOCK: sudo networkctl up proton2 sudo networkctl down proton1 Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK: sudo networkctl up proton2 sudo networkctl down proton1 COMMAND_BLOCK: sudo networkctl up proton2 sudo networkctl down proton1 - systemd (which is pretty much present on every modern Linux installation) - iwd (if you need wireless connection) - ufw (if you want a killswitch) - DNSDefaultRoute: This will make sure that the address for DNS used in this configuration will be the one used as default. - InvertRule: When creating a RoutingPolicyRule, any rule specified inside the block is used to decide if the packet will or not use the route defined by the Table. Setting it to invert, it's saying to use the Table route if there's no match. - FirewallMark: This would try to match the packet FirewallMark. - Table: The IP table used for this configuration. - Priority: The priority of executing this rule (as previously discussed) - ^ https://systemd.io/ - ^ https://wiki.archlinux.org/title/Systemd-networkd - ^ https://wiki.archlinux.org/title/Systemd-networkd#Required\_services\_and\_setup - ^ https://wiki.archlinux.org/title/Systemd#Using\_units - ^ https://wiki.archlinux.org/title/Systemd-resolved#DNS - ^ https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html - ^ https://www.freedesktop.org/software/systemd/man/latest/systemd.netdev.html - ^ https://wiki.archlinux.org/title/Systemd-networkd#Wired\_adapter\_using\_DHCP - ^ https://wiki.archlinux.org/title/Systemd-networkd#Wireless\_adapter - ^ https://wiki.archlinux.org/title/Iwd - ^ https://wiki.archlinux.org/title/Iwd#Usage - ^ https://wiki.archlinux.org/title/Iwd#Connect\_to\_a\_network - ^ https://tailscale.com/kb/1031/install-linux - ^ https://wiki.archlinux.org/title/Tailscale#Usage - ^ https://tailscale.com/kb/1103/exit-nodes?tab=linux#advertise-a-device-as-an-exit-node - ^ https://kalnytskyi.com/posts/setup-wireguard-client-systemd-networkd/ - ^ https://wiki.archlinux.org/title/Uncomplicated\_Firewall - ^ https://tailscale.com/kb/1082/firewall-ports - ^ https://wiki.archlinux.org/title/Uncomplicated\_Firewall#Installation - ^ https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#%5BRoutingPolicyRule%5D%20Section%20Options - ^ https://www.freedesktop.org/software/systemd/man/latest/systemd.network.html#ActivationPolicy=