.
This commit is contained in:
commit
73ff9ee8ee
31 changed files with 4906 additions and 0 deletions
166
wireguard.nix
Normal file
166
wireguard.nix
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.wireguard-netns;
|
||||
|
||||
vpnOptions =
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = "Name of the network namespace and WireGuard interface";
|
||||
};
|
||||
|
||||
dns = mkOption {
|
||||
type = types.str;
|
||||
description = "Network DNS";
|
||||
example = "1.1.1.1";
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
description = "Address";
|
||||
example = "10.2.0.1/32";
|
||||
};
|
||||
|
||||
conf = mkOption {
|
||||
type = types.str;
|
||||
description = "Path to sops secret containing WireGuard configuration";
|
||||
example = "wg0/conf";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options.services.wireguard-netns = {
|
||||
enable = mkEnableOption "WireGuard network namespaces";
|
||||
|
||||
namespaces = mkOption {
|
||||
type = types.attrsOf (types.submodule vpnOptions);
|
||||
default = { };
|
||||
description = "WireGuard VPN configurations in separate network namespaces";
|
||||
example = literalExpression ''
|
||||
{
|
||||
wg0ns = {
|
||||
dns = "10.2.0.1";
|
||||
address = "10.2.0.2/32";
|
||||
conf = "wg0/conf";
|
||||
};
|
||||
wg1ns = {
|
||||
dns = "10.3.0.1";
|
||||
address = "10.3.0.2/32";
|
||||
conf = "wg1/conf";
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services = listToAttrs (
|
||||
flatten (
|
||||
imap1 (
|
||||
index: elem:
|
||||
let
|
||||
name = elem.name;
|
||||
vpnCfg = elem.value;
|
||||
ns = "${name}ns";
|
||||
nsIP = "10.200.${toString index}.2/24";
|
||||
hostIP = "10.200.${toString index}.1/24";
|
||||
vethHost = "veth-${name}";
|
||||
vethNS = "veth-${name}-ns";
|
||||
proxyIP = "10.200.${toString index}.2"; # IP without CIDR for binding
|
||||
proxyPort = 1080;
|
||||
in
|
||||
[
|
||||
{
|
||||
name = "netns@${ns}";
|
||||
value = {
|
||||
description = "${ns} network namespace";
|
||||
before = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = pkgs.writers.writeBash "${ns}-up" ''
|
||||
${pkgs.coreutils}/bin/mkdir -p /etc/netns/${ns}
|
||||
echo "nameserver ${vpnCfg.dns}" > /etc/netns/${ns}/resolv.conf
|
||||
${pkgs.iproute2}/bin/ip netns add ${ns}
|
||||
|
||||
${pkgs.iproute2}/bin/ip link add ${vethHost} type veth peer name ${vethNS}
|
||||
${pkgs.iproute2}/bin/ip link set ${vethNS} netns ${ns}
|
||||
|
||||
${pkgs.iproute2}/bin/ip addr add ${hostIP} dev ${vethHost}
|
||||
${pkgs.iproute2}/bin/ip link set ${vethHost} up
|
||||
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} addr add ${nsIP} dev ${vethNS}
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} link set ${vethNS} up
|
||||
'';
|
||||
ExecStop = pkgs.writers.writeBash "${ns}-down" ''
|
||||
${pkgs.iproute2}/bin/ip link del ${vethHost} || true
|
||||
${pkgs.iproute2}/bin/ip netns del ${ns}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
name = name;
|
||||
value = {
|
||||
description = "${name} network interface";
|
||||
bindsTo = [ "netns@${ns}.service" ];
|
||||
requires = [ "network-online.target" ];
|
||||
after = [ "netns@${ns}.service" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = pkgs.writers.writeBash "${name}-up" ''
|
||||
${pkgs.iproute2}/bin/ip link add ${name} type wireguard
|
||||
${pkgs.iproute2}/bin/ip link set ${name} netns ${ns}
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} address add ${vpnCfg.address} dev ${name}
|
||||
${pkgs.iproute2}/bin/ip netns exec ${ns} \
|
||||
${pkgs.wireguard-tools}/bin/wg setconf ${name} ${config.sops.secrets.${vpnCfg.conf}.path}
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} link set lo up
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} link set ${name} up
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} route add default dev ${name}
|
||||
'';
|
||||
ExecStop = pkgs.writers.writeBash "${name}-down" ''
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} route del default dev ${name} || true
|
||||
${pkgs.iproute2}/bin/ip -n ${ns} link del ${name} || true
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
name = "socks-${name}";
|
||||
value = {
|
||||
description = "SOCKS5 proxy for ${name} namespace";
|
||||
after = [ "${name}.service" ];
|
||||
requires = [ "${name}.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
RestartSec = "5s";
|
||||
ExecStart = "${pkgs.iproute2}/bin/ip netns exec ${ns} ${pkgs.microsocks}/bin/microsocks -i ${proxyIP} -p ${toString proxyPort}";
|
||||
};
|
||||
};
|
||||
}
|
||||
]
|
||||
) (lib.attrsToList cfg.namespaces)
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue