WireGuard: Difference between revisions
→Proxy client setup: Route for specific user |
→Peer setup: add comment to indicate permissions needed for networkd secret |
||
| (17 intermediate revisions by one other user not shown) | |||
| Line 15: | Line 15: | ||
traffic on a per user basis. For example, you can route all torrenting traffic | traffic on a per user basis. For example, you can route all torrenting traffic | ||
through a wireguard tunnel, see below. | through a wireguard tunnel, see below. | ||
systemd.network is recommended due to its powerful configuration interface. | |||
wg-quick is suitable for common usage patterns. networking.wireguard seems to | |||
have issues with routing. NetworkManager does not supoort Proxy server setup, and | |||
is cubersome to use. | |||
Skip to Generate Keys section if you are in a hurry. | |||
= Use cases = | = Use cases = | ||
| Line 25: | Line 32: | ||
Internet via another peer. | Internet via another peer. | ||
== DNS for the proxy client == | == Secure DNS for the proxy client == | ||
You can use a secure DNS client such as knot dns resolver, | |||
which comes with a set of authenticated dns servers ips | |||
You can use | built in. | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
| Line 46: | Line 53: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Secure DNS hinders usage of captive portals. See [[systemd-resolved]] for solutions. | |||
= AllowedIPs = | = AllowedIPs = | ||
| Line 144: | Line 122: | ||
}; | }; | ||
</syntaxHighlight> | </syntaxHighlight> | ||
= systemd.network = | = systemd.network = | ||
Credit: this section is adapted from ArchWiki. | Credit: this section is adapted from ArchWiki. | ||
This section should fully support IPv4 and v6 dual stack. | |||
== Peer setup == | == Peer setup == | ||
| Line 394: | Line 166: | ||
wireguardConfig = { | wireguardConfig = { | ||
ListenPort = 51820; | ListenPort = 51820; | ||
# ensure file is readable by `systemd-network` user | |||
PrivateKeyFile = config.age.secrets.wg-key-vps.path; | |||
# To automatically create routes for everything in AllowedIPs, | # To automatically create routes for everything in AllowedIPs, | ||
| Line 402: | Line 177: | ||
# with the number 42, which can be used to define policy rules on these packets. | # with the number 42, which can be used to define policy rules on these packets. | ||
FirewallMark = 42; | FirewallMark = 42; | ||
}; | }; | ||
wireguardPeers = [ | wireguardPeers = [ | ||
| Line 473: | Line 246: | ||
# only works with systemd-resolved | # only works with systemd-resolved | ||
domains = [ "~." ]; | domains = [ "~." ]; | ||
dns = [ " | dns = [ "{proxy server internal ip}" ]; | ||
DNSDefaultRoute = true; | networkConfig = { | ||
DNSDefaultRoute = true; | |||
}; | |||
}; | }; | ||
}; | }; | ||
| Line 488: | Line 263: | ||
systemd.network = { | systemd.network = { | ||
netdevs."50-wg0" = { | netdevs."50-wg0" = { | ||
# FirewallMark simply marks all packets send and received by this wireguard | |||
# interface with the number 42, which can be used to define policy rules on these packets. | |||
wireguardConfig.FirewallMark = 42; | |||
wireguardPeers = [ | wireguardPeers = [ | ||
{ | { | ||
| Line 502: | Line 281: | ||
# for the wireguard interface, and no rules are set on the main routing table. | # for the wireguard interface, and no rules are set on the main routing table. | ||
RouteTable = 1000; | RouteTable = 1000; | ||
} | } | ||
]; | ]; | ||
| Line 520: | Line 295: | ||
FirewallMark = 42; | FirewallMark = 42; | ||
# we specify that the routing table 1000 must be used | # (... continued) we specify that the routing table 1000 must be used | ||
# (which is the wireguard routing table). This rule routes all traffic through wireguard. | # (which is the wireguard routing table). This rule routes all traffic through wireguard. | ||
# inside routingPolicyRules section is called Table, not RouteTable | # inside routingPolicyRules section is called Table, not RouteTable | ||
| Line 539: | Line 314: | ||
# We exempt our endpoint with a higher priority by routing it | # We exempt our endpoint with a higher priority by routing it | ||
# through the main table (Table=main is default). | # through the main table (Table=main is default). | ||
To = "2a01::1/128"; | To = "2a01::1/128"; | ||
Priority = 5; | Priority = 5; | ||
| Line 561: | Line 335: | ||
] | ] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Manually start and stop wg0 === | |||
The above steps will set up a <tt>wg0</tt> interface, managed by networkctl command. | |||
You can start it by typing the following in your terminal: | |||
<syntaxHighlight lang="sh"> | |||
sudo networkctl up wg0 | |||
</syntaxHighlight> | |||
To stop the service: | |||
<syntaxHighlight lang="sh"> | |||
sudo networkctl down wg0 | |||
</syntaxHighlight> | |||
=== Route for specific user === | === Route for specific user === | ||
| Line 598: | Line 388: | ||
Family = "both"; | Family = "both"; | ||
} | } | ||
] | ]; | ||
# Configure port forwarding for Transmission under NAT | |||
networking.nat.forwardPorts = | |||
[ | |||
{ | |||
destination = "10.0.0.1:80"; | |||
proto = "tcp"; | |||
sourcePort = 8080; | |||
} | |||
{ | |||
destination = "[fc00::2]:80"; | |||
proto = "tcp"; | |||
sourcePort = 8080; | |||
} | |||
]; | |||
</syntaxhighlight> | |||
== Test and Troubleshooting == | |||
Test the proxy with | |||
# ipv4 | |||
$ curl -4 zx2c4.com/ip | |||
# ipv6 | |||
$ curl -6 zx2c4.com/ip | |||
Check systemd-networkd log for any error and warning messages. | |||
$ journalctl -u systemd-networkd.service | |||
Invoke <code>wg</code> command from <code>wireguard-tools</code>. | |||
Use <code>ip route</code> to inspect the route table | |||
$ ip route show table 1000 | |||
default dev wg0 proto static scope link | |||
$ ip route show table all | |||
... many entries ... | |||
$ ip rule list | |||
10: not from all fwmark 0x2a lookup 1000 proto static | |||
$ ip route get 136.144.57.121 | |||
136.144.57.121 dev wg0 table 1000 src 192.168.26.9 uid 1000 | |||
$ ip route get 2600:1406::1 | |||
2600:1406::1 from :: dev wg0 table 1000 proto static src fd31:bf08:57cb::9 metric 1024 pref medium | |||
= wg-quick = | |||
== Peer setup == | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
networking.wg-quick.interfaces = { | |||
wg0 = { | |||
address = [ | |||
"fd31:bf08:57cb::9/128" | |||
"192.168.26.9/32" | |||
]; | |||
# use dnscrypt, or proxy dns as described above | |||
dns = [ "127.0.0.1" ]; | |||
privateKeyFile = config.age.secrets.wg-key-laptop.path; | |||
peers = [ | |||
{ | |||
# bt wg conf | |||
publicKey = "ejmbag/fcc9OLp8K62zfV0NCbp056DnA0qpNixLXwCo="; | |||
allowedIPs = [ | |||
"fd31:bf08:57cb::8/128" | |||
"192.168.26.8/32" | |||
]; | |||
endpoint = "192.168.1.56:51820"; | |||
} | |||
]; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
== Proxy server setup == | |||
Same as peer setup, skip the endpoint option, with the following | |||
addition: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
# enable NAT | |||
networking.nat = { | |||
enable = true; | |||
enableIPv6 = true; | |||
externalInterface = "ens6"; | |||
internalInterfaces = [ "wg0" ]; | |||
}; | |||
networking.wg-quick.interfaces = { | |||
wg0 = { | |||
# This allows the wireguard server to route your traffic to the internet and hence be like a VPN | |||
postUp = '' | |||
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o eth0 -j MASQUERADE | |||
${pkgs.iptables}/bin/ip6tables -A FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/ip6tables -t nat -A POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o eth0 -j MASQUERADE | |||
''; | |||
# Undo the above | |||
preDown = '' | |||
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.0.0.1/24 -o eth0 -j MASQUERADE | |||
${pkgs.iptables}/bin/ip6tables -D FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/ip6tables -t nat -D POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o eth0 -j MASQUERADE | |||
''; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
== Proxy client setup == | |||
Same as peer setup, specify proxy server ip or domain in the endpoint | |||
option. Use <code>[ "0.0.0.0/0" "::/0" ]</code> as allowed IPs. | |||
Optionally, configure proxy server as DNS server as described above. | |||
=== Proxy DNS with dnsmasq === | |||
You can also use the proxy server as DNS server with | |||
dnsmasq. | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
networking.firewall = { | |||
allowedTCPPorts = [ 53 ]; | |||
allowedUDPPorts = [ 53 ]; | |||
}; | |||
services = { | |||
dnsmasq = { | |||
enable = true; | |||
settings.interface = "wg0"; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
For wg-quick peer, use the | |||
following option | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
networking.wg-quick.interfaces.wg0.dns = | |||
[ {internal v4 & v6 ip addr of server} ]; | |||
} | |||
</syntaxhighlight> | |||
== Manually start and stop wg-quick == | |||
The above steps will set up a <tt>wg-quick-wg0.service</tt> systemd unit. | |||
You can start it by typing the following in your terminal: | |||
<syntaxHighlight lang="sh"> | |||
sudo systemctl start wg-quick-wg0.service | |||
</syntaxHighlight> | |||
To stop the service: | |||
<syntaxHighlight lang="sh"> | |||
sudo systemctl stop wg-quick-wg0.service | |||
</syntaxHighlight> | |||
== Reuse existing wg-quick config file == | |||
If you have WireGuard configuration files that you want to use as-is | |||
(similarly how you would | |||
[https://wiki.debian.org/WireGuard#Step_2_-_Configuration configure | |||
WireGuard e.g. in Debian], without converting them to a declarative | |||
NixOS configuration, you can also configure <code>wg-quick</code> to | |||
use them. For example, if you have a configuration file | |||
<code>/etc/nixos/wireguard/wg0.conf</code>, add the following line to | |||
your <code>configuration.nix</code>: | |||
<syntaxHighlight lang="nix"> | |||
networking.wg-quick.interfaces.wg0.configFile = "/etc/nixos/files/wireguard/wg0.conf"; | |||
</syntaxHighlight> | |||
This will set up a <code>wg-quick-wg0.service</code> systemd unit. | |||
= networking.wireguard = | |||
Note: does not automatically configure routes, see comments. | |||
== Peer setup == | |||
<syntaxhighlight lang="nix"> | |||
{ config, ... }: | |||
{ | |||
age.secrets.wg-key-peer0 = { | |||
file = "./secrets/wg-key-peer0.age"; | |||
}; | |||
networking.firewall.allowedUDPPorts = [ 51820 ]; | |||
networking.wireguard = { | |||
enable = true; | |||
interfaces = { | |||
# network interface name. | |||
# You can name the interface arbitrarily. | |||
wg0 = { | |||
# the IP address and subnet of this peer | |||
ips = [ "fd31:bf08:57cb::9/128" "192.168.26.9/32" ]; | |||
# WireGuard Port | |||
# Must be accessible by peers | |||
listenPort = 51820; | |||
# Path to the private key file. | |||
# | |||
# Note: can also be included inline via the privateKey option, | |||
# but this makes the private key world-readable; | |||
# using privateKeyFile is recommended. | |||
privateKeyFile = config.age.secrets.wg-key-laptop.path; | |||
peers = [ | |||
{ | |||
name = "home nas"; | |||
publicKey = "ejmbag/fcc9OLp8K62zfV0NCbp056DnA0qpNixLXwCo="; | |||
allowedIPs = [ | |||
"fd31:bf08:57cb::8/128" | |||
"192.168.26.8/32" | |||
]; | |||
endpoint = "192.168.1.56:51820"; | |||
# ToDo: route to endpoint not automatically configured | |||
# https://wiki.archlinux.org/index.php/WireGuard#Loop_routing | |||
# https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577 | |||
# Send keepalives every 25 seconds. Important to keep NAT tables alive. | |||
# persistentKeepalive = 25; | |||
} | |||
]; | |||
}; | |||
}; | |||
} | |||
# it’s not imperative but it does not know how to do it : | |||
# sudo ip route add 11.111.11.111 via 192.168.1.11 dev wlo1 | |||
# the ip adresse 11: external and 192: local. | |||
</syntaxhighlight> | |||
== Proxy server setup == | |||
Same as peer setup, skip the endpoint option, with the following | |||
addition, Remember to update the internal IP addresses in the script: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
# enable NAT | |||
networking.nat = { | |||
enable = true; | |||
enableIPv6 = true; | |||
externalInterface = "ens6"; | |||
internalInterfaces = [ "wg0" ]; | |||
}; | |||
networking.wireguard.interfaces.wg0 = { | |||
# This allows the wireguard server to route your traffic to the internet and hence be like a VPN | |||
postSetup = '' | |||
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o eth0 -j MASQUERADE | |||
${pkgs.iptables}/bin/ip6tables -A FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/ip6tables -t nat -A POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o eth0 -j MASQUERADE | |||
''; | |||
# Undo the above | |||
postShutdown = '' | |||
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.0.0.1/24 -o eth0 -j MASQUERADE | |||
${pkgs.iptables}/bin/ip6tables -D FORWARD -i wg0 -j ACCEPT | |||
${pkgs.iptables}/bin/ip6tables -t nat -D POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o eth0 -j MASQUERADE | |||
''; | |||
}; | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== Proxy client setup == | |||
Same as peer setup, specify proxy server ip or domain in the endpoint | |||
option. Use <code>[ "0.0.0.0/0" "::/0" ]</code> as allowed IPs. | |||
= NetworkManager Proxy client setup = | = NetworkManager Proxy client setup = | ||
| Line 717: | Line 792: | ||
* [https://www.youtube.com/watch?v=us7V2NvsQRA Talk by @fpletz at NixCon 2018 about networkd and his WireGuard setup] | * [https://www.youtube.com/watch?v=us7V2NvsQRA Talk by @fpletz at NixCon 2018 about networkd and his WireGuard setup] | ||
* [https://web.archive.org/web/20210101230654/https://www.the-digital-life.com/wiki/wireguard-troubleshooting/ WireGuard Troubleshooting (on Web Archive)] shows how to enable debug logs | * [https://web.archive.org/web/20210101230654/https://www.the-digital-life.com/wiki/wireguard-troubleshooting/ WireGuard Troubleshooting (on Web Archive)] shows how to enable debug logs | ||
= Additional routing setups = | |||
For documentation on more routing and topology setups, such as | |||
* Point to Point Configuration, | |||
* Hub and Spoke Configuration, | |||
* Point to Site Configuration, | |||
* Site to Site Configuration, | |||
see [https://docs.procustodibus.com/guide/wireguard/ Pro Custodibus Documentation], [https://web.archive.org/web/20250920231827/https://docs.procustodibus.com/guide/wireguard/ Mirror on Internet Archive]. | |||
[[Category:Networking]] | [[Category:Networking]] | ||
[[Category:VPN]] | [[Category:VPN]] | ||