WireGuard: Difference between revisions
imported>MarcoPolo m Move iptables routing within the wiregaurd definition. The previous setup did not work for me (Perhaps because of GCP networking?) |
imported>Wulfsta Add example configuration for wg-quick for a server setup with dnsmasq. |
||
Line 14: | Line 14: | ||
You can create as many keypairs as you like for different connections or roles; it is also possible to reuse the same keypair for every connection. | You can create as many keypairs as you like for different connections or roles; it is also possible to reuse the same keypair for every connection. | ||
==Server setup== | ===Server setup=== | ||
Enable Wireguard on the server via <tt>/etc/nixos/configuration.nix</tt>: | Enable Wireguard on the server via <tt>/etc/nixos/configuration.nix</tt>: | ||
<syntaxHighlight lang="nix"> | <syntaxHighlight lang="nix"> | ||
Line 74: | Line 74: | ||
</syntaxHighlight> | </syntaxHighlight> | ||
==Client setup== | ===Client setup=== | ||
<syntaxHighlight lang="nix"> | <syntaxHighlight lang="nix"> | ||
{ | { | ||
Line 118: | Line 118: | ||
Multiple connections can be configured by configuring multiple interfaces under {{nixos:option|networking.wireguard.interfaces}}. | Multiple connections can be configured by configuring multiple interfaces under {{nixos:option|networking.wireguard.interfaces}}. | ||
==Setting up Wireguard server/client with wg-quick and dnsmasq== | |||
===Server setup=== | |||
DNS requires opening TCP/UDP port 53. | |||
<syntaxHighlight lang="nix"> | |||
{ | |||
... | |||
# Enable NAT | |||
networking.nat = { | |||
enable = true; | |||
externalInterface = "eth0"; | |||
internalInterfaces = [ "wg0" ]; | |||
}; | |||
# Open ports in the firewall | |||
networking.firewall = { | |||
allowedTCPPorts = [ 53 ]; | |||
allowedUDPPorts = [ 53 51820 ]; | |||
}; | |||
... | |||
} | |||
</syntaxHighlight> | |||
The wg-quick setup is similar to the previous setup. | |||
<syntaxHighlight lang="nix"> | |||
{ | |||
... | |||
networking.wg-quick.interfaces = { | |||
# "wg0" is the network interface name. You can name the interface arbitrarily. | |||
wg0 = { | |||
# Determines the IP/IPv6 address and subnet of the client's end of the tunnel interface | |||
address = [ "10.0.0.1/24" "fdc9:281f:04d7:9ee9::1/64" ]; | |||
# The port that Wireguard listens to - recommended that this be changed from default | |||
listenPort = 51820; | |||
# Path to the server's private key | |||
privateKeyFile = "/root/wireguard-keys/privatekey"; | |||
# 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 | |||
''; | |||
peers = [ | |||
{ # peer0 | |||
publicKey = "{client public key}"; | |||
presharedKeyFile = "/root/wireguard-keys/preshared_from_peer0_key"; | |||
allowedIPs = [ "10.0.0.2/32" "fdc9:281f:04d7:9ee9::2/128" ]; | |||
} | |||
# More peers can be added here. | |||
]; | |||
}; | |||
}; | |||
... | |||
} | |||
</syntaxHighlight> | |||
To enable dnsmasq and only serve DNS requests to the Wireguard interface add the following: | |||
<syntaxHighlight lang="nix"> | |||
{ | |||
... | |||
services = { | |||
... | |||
dnsmasq = { | |||
enable = true; | |||
extraConfig = '' | |||
interface=wg0 | |||
''; | |||
}; | |||
... | |||
}; | |||
... | |||
} | |||
</syntaxHighlight> | |||
===Client setup=== | |||
The client will now point DNS to the server. | |||
<syntaxHighlight lang="nix"> | |||
{ | |||
... | |||
networking.wg-quick.interfaces = { | |||
wg0 = { | |||
address = [ "10.0.0.2/24" "fcd9:281f:04d7:9ee9::2/64" ]; | |||
dns = [ "10.0.0.1" "fcd9:281f:04d7:9ee9::1" ]; | |||
privateKeyFile = "/root/wireguard-keys/privatekey"; | |||
peers = [ | |||
{ | |||
publicKey = "{server public key}"; | |||
presharedKeyFile = "/root/wireguard-keys/preshared_from_peer0_key"; | |||
allowedIPs = [ "0.0.0.0/0" "::/0" ]; | |||
endpoint = "{server ip}:51820"; | |||
persistentKeepalive = 25; | |||
} | |||
]; | |||
}; | |||
}; | |||
... | |||
} | |||
</syntaxHighlight> | |||
=Setting up Wireguard with systemd-networkd= | ==Setting up Wireguard with systemd-networkd== | ||
Please note, that networkd support in NixOS is still [https://nixos.org/nixos/options.html#usenetworkd experimental]. | Please note, that networkd support in NixOS is still [https://nixos.org/nixos/options.html#usenetworkd experimental]. | ||
==Client setup== | ===Client setup=== | ||
<syntaxHighlight lang="nix"> | <syntaxHighlight lang="nix"> |
Revision as of 22:19, 26 July 2020
Setting up Wireguard
Generate keypair
Each peer needs to have a public-private keypair. The keys can be generated on any machine that already has Wireguard installed using the wg
utility. If Wireguard isn't installed yet, it can be made available by adding wireguard
to environment.systemPackages
or by running nix-env -iA wireguard
.
Creating a keypair is simple:
umask 077
mkdir ~/wireguard-keys
wg genkey > ~/wireguard-keys/private
wg pubkey < ~/wireguard-keys/private > ~/wireguard-keys/public
You can create as many keypairs as you like for different connections or roles; it is also possible to reuse the same keypair for every connection.
Server setup
Enable Wireguard on the server via /etc/nixos/configuration.nix:
{
...
# enable NAT
networking.nat.enable = true;
networking.nat.externalInterface = "eth0";
networking.nat.internalInterfaces = [ "wg0" ];
networking.firewall = {
allowedUDPPorts = [ 51820 ];
};
networking.wireguard.interfaces = {
# "wg0" is the network interface name. You can name the interface arbitrarily.
wg0 = {
# Determines the IP address and subnet of the server's end of the tunnel interface.
ips = [ "10.100.0.1/24" ];
# The port that Wireguard listens to. Must be accessible by the client.
listenPort = 51820;
# This allows the wireguard server to route your traffic to the internet and hence be like a VPN
# For this to work you have to set the dnsserver IP of your router (or dnsserver of choice) in your clients
postSetup = ''
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# This undoes the above command
postShutdown = ''
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
'';
# Path to the private key file.
#
# Note: The private key can also be included inline via the privateKey option,
# but this makes the private key world-readable; thus, using privateKeyFile is
# recommended.
privateKeyFile = "path to private key file";
peers = [
# List of allowed peers.
{ # Feel free to give a meaning full name
# Public key of the peer (not a file path).
publicKey = "{client public key}";
# List of IPs assigned to this peer within the tunnel subnet. Used to configure routing.
allowedIPs = [ "10.100.0.2/32" ];
}
{ # John Doe
publicKey = "{john doe's public key}";
allowedIPs = [ "10.100.0.3/32" ];
}
];
};
};
...
}
Client setup
{
...
# Enable Wireguard
networking.wireguard.interfaces = {
# "wg0" is the network interface name. You can name the interface arbitrarily.
wg0 = {
# Determines the IP address and subnet of the client's end of the tunnel interface.
ips = [ "10.100.0.2/24" ];
# Path to the private key file.
#
# Note: The private key can also be included inline via the privateKey option,
# but this makes the private key world-readable; thus, using privateKeyFile is
# recommended.
privateKeyFile = "path to private key file";
peers = [
# For a client configuration, one peer entry for the server will suffice.
{
# Public key of the server (not a file path).
publicKey = "{server public key}";
# Forward all the traffic via VPN.
allowedIPs = [ "0.0.0.0/0" ];
# Or forward only particular subnets
#allowedIPs = [ "10.100.0.1" "91.108.12.0/22" ];
# Set this to the server IP and port.
endpoint = "{server ip}:51820";
# Send keepalives every 25 seconds. Important to keep NAT tables alive.
persistentKeepalive = 25;
}
];
};
};
...
}
Multiple connections can be configured by configuring multiple interfaces under networking.wireguard.interfaces
.
Setting up Wireguard server/client with wg-quick and dnsmasq
Server setup
DNS requires opening TCP/UDP port 53.
{
...
# Enable NAT
networking.nat = {
enable = true;
externalInterface = "eth0";
internalInterfaces = [ "wg0" ];
};
# Open ports in the firewall
networking.firewall = {
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 51820 ];
};
...
}
The wg-quick setup is similar to the previous setup.
{
...
networking.wg-quick.interfaces = {
# "wg0" is the network interface name. You can name the interface arbitrarily.
wg0 = {
# Determines the IP/IPv6 address and subnet of the client's end of the tunnel interface
address = [ "10.0.0.1/24" "fdc9:281f:04d7:9ee9::1/64" ];
# The port that Wireguard listens to - recommended that this be changed from default
listenPort = 51820;
# Path to the server's private key
privateKeyFile = "/root/wireguard-keys/privatekey";
# 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
'';
peers = [
{ # peer0
publicKey = "{client public key}";
presharedKeyFile = "/root/wireguard-keys/preshared_from_peer0_key";
allowedIPs = [ "10.0.0.2/32" "fdc9:281f:04d7:9ee9::2/128" ];
}
# More peers can be added here.
];
};
};
...
}
To enable dnsmasq and only serve DNS requests to the Wireguard interface add the following:
{
...
services = {
...
dnsmasq = {
enable = true;
extraConfig = ''
interface=wg0
'';
};
...
};
...
}
Client setup
The client will now point DNS to the server.
{
...
networking.wg-quick.interfaces = {
wg0 = {
address = [ "10.0.0.2/24" "fcd9:281f:04d7:9ee9::2/64" ];
dns = [ "10.0.0.1" "fcd9:281f:04d7:9ee9::1" ];
privateKeyFile = "/root/wireguard-keys/privatekey";
peers = [
{
publicKey = "{server public key}";
presharedKeyFile = "/root/wireguard-keys/preshared_from_peer0_key";
allowedIPs = [ "0.0.0.0/0" "::/0" ];
endpoint = "{server ip}:51820";
persistentKeepalive = 25;
}
];
};
};
...
}
Setting up Wireguard with systemd-networkd
Please note, that networkd support in NixOS is still experimental.
Client setup
{ config, pkgs, lib, ... }:{
boot.extraModulePackages = [ config.boot.kernelPackages.wireguard ];
systemd.network = {
enable = true;
netdevs = {
"10-wg0" = {
netdevConfig = {
Kind = "wireguard";
MTUBytes = "1300";
Name = "wg0";
};
# See also man systemd.netdev
extraConfig = ''
[WireGuard]
# Currently, the private key must be world readable, as the resulting netdev file will reside in the Nix store.
PrivateKey=EMlybyTmXI/4z311xU9S3m82mC2OOMRfRM0Okiik83o=
ListenPort=9918
[WireGuardPeer]
PublicKey=OhApdFoOYnKesRVpnYRqwk3pdM247j8PPVH5K7aIKX0=
AllowedIPs=fc00::1/64, 10.100.0.1
Endpoint={set this to the server ip}:51820
'';
};
};
networks = {
# See also man systemd.network
"40-wg0".extraConfig = ''
[Match]
Name=wg0
[Network]
DHCP=none
IPv6AcceptRA=false
Gateway=fc00::1
Gateway=10.100.0.1
DNS=fc00::53
NTP=fc00::123
# IP addresses the client interface will have
[Address]
Address=fe80::3/64
[Address]
Address=fc00::3/120
[Address]
Address=10.100.0.2/24
'';
};
};
};
See also
- Wireguard homepage
- Arch Wiki has an exhaustive guide, including troubleshooting tips
- List of Wireguard options supported by NixOS
- Talk by @fpletz at NixCon 2018 about networkd and his Wireguard setup