Connect home network with IPv6 addresses
It adds a bit of latency (and is definitely not the best solution in theory), but finally allows dropping IPv6 NAT and it works within the constraits my home network has to live in.
This commit is contained in:
parent
771489a176
commit
959f7be3d0
|
@ -1,3 +1,4 @@
|
|||
wg-he-private-key: ENC[AES256_GCM,data:bT1G2nZHJO9j04I4j3QZYn7BxGX4XHxzgXDr3iFTnu/kirik6+0Eh/AUp+4=,iv:SeowjlP64t8lPn+WXqrOtZJWA3geTSO9ST9JNuPQwu0=,tag:ctLXe7BP0Ob/ADD4q7yOmg==,type:str]
|
||||
wg-home-private-key: ENC[AES256_GCM,data:gm4INfmp226u4wp+LuKgf5m2nTFFw4S24w4PRPcW/A7CU713c9NtQ+kPDKg=,iv:JAir9z5/Db6+Oroq+0vXPZLZLA2gjY2Be6hRAmgV5AE=,tag:fxL9nK3v5xERfcoBbCUsXg==,type:str]
|
||||
wg-upstream-private-key: ENC[AES256_GCM,data:CO50H7QsLQ2x0QQXnB7c0leG8NdV66gWrdWBWOR9z4ukSN7qj/qqe83t82k=,iv:2as2HfTfRje3TEap8QpPfzz4saNDgjo6Ty1DTF23JVE=,tag:ZYe+59wrpX7mV1HcDllMdg==,type:str]
|
||||
hostapd-config: ENC[AES256_GCM,data:a0ESrrsquLq6VRJM588C5A+FmVxJwJSzwRuv2o//LL5OybcDS8jkVUajosXEs0qmQ6Xfc1gFDcevCYUwJ24eZ+ynKLWwoNx8RXXwbpllO7FkI68vcauUij1CtUgVb8aHheKfrFuyW7WU1wE3NTtOt2gij1+nM3iKS3vFXtX2n9L2fuy2b3EhOUBiakxAeQmyVmclSVBDYt12i4h4tW7GpPr8AjoIiZgz0Hyx5zA5f/JTPzz/P200eM0tCttNPbMNPBGztJfw7raRIX+v6xw7QNPMgf03TOae17mt6uggTNKJfEPeanzcEMA3xR6xoFUqJL6Hvowyl4MrSFc+E5Rvft+qhp8m6tAqQln9Z3MzaDtxSBWnWdvWEcyeK1aDBQ57/aIwo8kVs47Iblqbi5+jM/n4DoeQtqTM1kS7sZ3XDQ26suW5KCw+VIeqEEqdu6g5ZXMO2SipSOzP5jPjX+5ubX3SXcyoAIo41Efa6YGdWtl3,iv:oLk5tatZEY5AI/PlTBJHShGCKiyvve9rPhGARAtMMj4=,tag:Bkan2Hff8L8ZcC67r+fWjg==,type:str]
|
||||
|
@ -7,8 +8,8 @@ sops:
|
|||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2023-08-08T09:43:37Z"
|
||||
mac: ENC[AES256_GCM,data:lxoKzGyPwdfeI5Dlmgx9K9SBhfRIaokvum+dJWABUoGtIMtrhp4K4ZRF1Rjja8oTi4w3b+s9aUBpxt8TLu9vJZFsUkhY2gqW5bX3Ub/3xMAR9YSG3LtijRSMuKkdVlAkdjB6Guz9aHNVBG3fTZ+SfTlyOQdImW6bK4tydbGHKgY=,iv:6kVR4zZfHnqhcOT3N2tClGST8h7FLjIseXDu2xS2DEY=,tag:rd/f7cHSoxLT3O7HluVWLA==,type:str]
|
||||
lastmodified: "2024-08-26T18:50:19Z"
|
||||
mac: ENC[AES256_GCM,data:k26ZEKuFtS0GLMqFIbY0QiVfHvmpxt3JgLvZIhEHcC3wQ80OhRNeyKocZhua1T5iSfhfvlckXYZl6tTZkCEh4fj3NmYMtQ9vwpoexdYWwx5ylPT3rpByfBbO+foHgQ3JXk6Kyt2R9ULjghMU3/lEcsG4AuGU1XMomsTzrdigXY8=,iv:ls3nIFIwTM//tSvee/aHj6Qv2nn/gZMKgGF+aQWNxeg=,tag:l58uHLpvPfIkbUn9gl+lzg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-01-22T00:20:19Z"
|
||||
enc: |-
|
||||
|
@ -79,4 +80,4 @@ sops:
|
|||
-----END PGP MESSAGE-----
|
||||
fp: 28677f2e3584b39f528a779caf445ebb39c882b7
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.7.3
|
||||
version: 3.8.1
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2023 Simon Bruder <simon@sbruder.de>
|
||||
# SPDX-FileCopyrightText: 2023-2024 Simon Bruder <simon@sbruder.de>
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
|
@ -35,22 +35,22 @@ in
|
|||
vlan = {
|
||||
lan = {
|
||||
id = 10;
|
||||
subnet = mkSubnet "10.80.1.0/24" "fd00:80:1::/64";
|
||||
subnet = mkSubnet "10.80.1.0/24" "2001:470:73b9:1::/64";
|
||||
domain = "lan.shinonome-lab.de";
|
||||
};
|
||||
management = {
|
||||
id = 20;
|
||||
subnet = mkSubnet "10.80.2.0/24" "fd00:80:2::/64";
|
||||
subnet = mkSubnet "10.80.2.0/24" "2001:470:73b9:2::/64";
|
||||
domain = "management.shinonome-lab.de";
|
||||
};
|
||||
guest = {
|
||||
id = 30;
|
||||
subnet = mkSubnet "10.80.3.0/24" "fd00:80:3::/64";
|
||||
subnet = mkSubnet "10.80.3.0/24" "2001:470:73b9:3::/64";
|
||||
domain = "guest.shinonome-lab.de";
|
||||
};
|
||||
iot = {
|
||||
id = 40;
|
||||
subnet = mkSubnet "10.80.4.0/24" "fd00:80:4::/64";
|
||||
subnet = mkSubnet "10.80.4.0/24" "2001:470:73b9:4::/64";
|
||||
domain = "iot.shinonome-lab.de";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2023 Simon Bruder <simon@sbruder.de>
|
||||
# SPDX-FileCopyrightText: 2023-2024 Simon Bruder <simon@sbruder.de>
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
|
@ -36,6 +36,8 @@ in
|
|||
./tc.nix
|
||||
];
|
||||
|
||||
sbruder.wireguard.he.enable = true;
|
||||
|
||||
boot.kernel.sysctl = {
|
||||
"net.ipv4.conf.all.forwarding" = true;
|
||||
"net.ipv6.conf.all.forwarding" = true;
|
||||
|
@ -106,6 +108,7 @@ in
|
|||
# Only use RA
|
||||
DHCPv6Client = false;
|
||||
UseDNS = "no";
|
||||
UseGateway = false; # should not be used by default for routing (wg-he takes precendence)
|
||||
};
|
||||
};
|
||||
physical-lan = {
|
||||
|
@ -128,6 +131,13 @@ in
|
|||
name = "enp4s0";
|
||||
bridge = [ "br-lan" ];
|
||||
};
|
||||
# extended from common config
|
||||
wg-he = {
|
||||
address = lib.singleton "2001:470:73b9::1";
|
||||
routes = lib.singleton {
|
||||
routeConfig.Gateway = "::"; # on link
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
|
|
@ -54,6 +54,12 @@ in
|
|||
server = [
|
||||
"127.0.0.1#5053"
|
||||
];
|
||||
|
||||
# Authoritative zones for external reachability (only AAAA records)
|
||||
auth-server = "shinobu.shinonome-lab.de,2001:470:73b9::1";
|
||||
auth-zone = map
|
||||
(vlan: "${vlan.domain},${vlan.subnet.v6.cidr}")
|
||||
(lib.attrValues cfg.vlan);
|
||||
};
|
||||
};
|
||||
systemd.services.dnsmasq.after = [ "systemd-networkd.service" ];
|
||||
|
|
|
@ -4,34 +4,51 @@
|
|||
|
||||
define NAT_LAN_IFACES = { "br-lan", "br-guest" }
|
||||
define PHYSICAL_WAN = "enp1s0"
|
||||
# only includes interfaces that use NAT
|
||||
define NAT_WAN_IFACES = { $PHYSICAL_WAN }
|
||||
# also includes interfaces that do not use NAT
|
||||
define WAN_IFACES = { $NAT_WAN_IFACES, "wg-he" }
|
||||
|
||||
table inet filter {
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop
|
||||
|
||||
# Use MSS clamping to avoid too large packets not going through the tunnel.
|
||||
tcp flags syn / syn,rst tcp option maxseg size set rt mtu
|
||||
|
||||
# plastic router, might be vulnerable (FIXME v6 is still reachable)
|
||||
iifname "br-guest" ip daddr "192.168.0.1" drop
|
||||
|
||||
# allow traffic between selected VLANs and wan
|
||||
iifname $NAT_LAN_IFACES oifname $NAT_WAN_IFACES counter accept
|
||||
iifname $NAT_WAN_IFACES oifname $NAT_LAN_IFACES ct state established,related counter accept
|
||||
iifname $NAT_LAN_IFACES oifname $WAN_IFACES counter accept
|
||||
iifname $WAN_IFACES oifname $NAT_LAN_IFACES ct state established,related counter accept
|
||||
|
||||
# allow lan clients to be publicly reachable
|
||||
iifname "wg-he" oifname "br-lan" counter accept
|
||||
|
||||
# traffic from lan to all other vlans is allowed
|
||||
iifname "br-lan" oifname $VLAN_BRIDGES counter accept;
|
||||
iifname $VLAN_BRIDGES oifname "br-lan" ct state established,related counter accept
|
||||
|
||||
iifname $NAT_WAN_IFACES oifname "br-iot" ct state established,related counter accept
|
||||
iifname $WAN_IFACES oifname "br-iot" ct state established,related counter accept
|
||||
}
|
||||
}
|
||||
|
||||
table inet nat {
|
||||
table ip nat {
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority filter; policy accept
|
||||
oifname $NAT_WAN_IFACES masquerade
|
||||
}
|
||||
}
|
||||
|
||||
table ip6 public-access {
|
||||
chain input {
|
||||
type filter hook input priority filter; policy accept
|
||||
|
||||
iifname "wg-he" oifname "br-lan" counter accept
|
||||
}
|
||||
}
|
||||
|
||||
# Only allow select connections from and to (physical) wan,
|
||||
# overriding NixOS firewall in some cases.
|
||||
table inet restrict-wan {
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
sbruder = {
|
||||
nginx.hardening.enable = true;
|
||||
full = false;
|
||||
wireguard.home.enable = true;
|
||||
wireguard = {
|
||||
he.enable = true;
|
||||
home.enable = true;
|
||||
};
|
||||
infovhost.enable = true;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
wg-he-private-key: ENC[AES256_GCM,data:aTH+AUBgG2D1CUF0zp1OzTUBu5Td2J2fsq3EpYEUuPGQFA+EbAYS+4AEipg=,iv:vNkqtoixZ+I+C5L4Vbck3EhCYGKzzIvwHIjiNs5PPIQ=,tag:6SMQ9oqKd7FdLvQNt2SAYA==,type:str]
|
||||
wg-home-private-key: ENC[AES256_GCM,data:0ylkx9p62CBGqVg+T52eHbMwbLcZM/v3tg/wJukDq76heN1TtQqbbqgVZKc=,iv:/aUkqKhihnBWQFLIRjS7kHigBCBXX7L4KY5q+cO9Q00=,tag:jQSMVElMfIyrG5hs7HuxUQ==,type:str]
|
||||
li7y-environment: ENC[AES256_GCM,data:cm4+672JelbYsBm0rwrF/I9gS72XfAlj335v0+EfXmPSD1LCBJ3clR7jZC7SVH5D9ZSaSlrY8J/+7hgDmzsiR2kypNBvfMvN825AF5QFehnYeHhxUktU+uig7RzpRUeWSPM0r8j6lmpGNc7vd3S+L3TWn2ZfCJ8Kc28Ad2M9yFiZ7PPqB6qqLnsx2peQuafDhefuohLPOYA=,iv:84yL6l7zqeb7l3w3ARskJoQEvI1+HxoCCKrLhB0kx7E=,tag:GCetAOW7pvyjKEM26A9ZbA==,type:str]
|
||||
sops:
|
||||
|
@ -6,8 +7,8 @@ sops:
|
|||
azure_kv: []
|
||||
hc_vault: []
|
||||
age: []
|
||||
lastmodified: "2024-07-14T17:32:43Z"
|
||||
mac: ENC[AES256_GCM,data:7D9xHNpdhI6CgX94PAoJJIJqVZ403ZL7dXbdnod2do4M+Qf0yRrRDxi6hPipf0BX0vsSq1npdiXcnwP50PZHal8LW7IJRjfefW5WnO+BLD42sIxt5mikdNfZhpyg3dHB7j+8m1lE1+veK/Ho06V32sckibhBG4AFBfMZ/k1VIns=,iv:NS9CaSyEUdmJEKFejiaugtZ5Nf8norhoaCaOwPZsxow=,tag:Y2Nu92iYO0PSqtXMLc3D7g==,type:str]
|
||||
lastmodified: "2024-08-26T17:49:34Z"
|
||||
mac: ENC[AES256_GCM,data:tnjZq65XULfFeEa7fDwTbOFTgjyvZ+UHW+T7Hqny3kzUb5bgaX6D3Xj2Ij0CrTxgyEzRLpkBG/TpEDdY1//NaruGl6CDYmYHEb5yHAzDRzpbPoZhteGfyuiRKGblK3EvMWpj2x4ZTnO7Y13fGpOzA5o38maAZL3eYPUb2yueD58=,iv:70dlzD6/uteJZZMo2T5R+H7QvZH60AWDrwc8iljIEb4=,tag:ADWZObS6Aq/iwRLPLlqPjg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-01-22T00:20:20Z"
|
||||
enc: |-
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# SPDX-FileCopyrightText: 2020-2023 Simon Bruder <simon@sbruder.de>
|
||||
# SPDX-FileCopyrightText: 2020-2024 Simon Bruder <simon@sbruder.de>
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{
|
||||
imports = [
|
||||
./he.nix
|
||||
./home.nix
|
||||
./support.nix
|
||||
];
|
||||
|
|
120
modules/wireguard/he.nix
Normal file
120
modules/wireguard/he.nix
Normal file
|
@ -0,0 +1,120 @@
|
|||
# SPDX-FileCopyrightText: 2020-2024 Simon Bruder <simon@sbruder.de>
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{ lib, config, ... }:
|
||||
let
|
||||
serverHostName = "yuzuru";
|
||||
serverPort = 51820;
|
||||
peers = {
|
||||
yuzuru = {
|
||||
subnets = [ ];
|
||||
publicKey = "mWm92aZybisoLtd11g4XqwUZvQGVxMfPW9/za3/1/0Y=";
|
||||
};
|
||||
shinobu = {
|
||||
subnets = [ "2001:470:73b9::/56" ];
|
||||
publicKey = "c8lnzMWFeTzQmXwNV0DlD2ROJqBcDL0F9WN5u4lVeFQ=";
|
||||
};
|
||||
};
|
||||
|
||||
cfg = config.sbruder.wireguard.he;
|
||||
enableServer = config.networking.hostName == serverHostName;
|
||||
in
|
||||
{
|
||||
options.sbruder.wireguard.he.enable = lib.mkEnableOption "WireGuard tunnel wg-he";
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
sops.secrets.wg-he-private-key = {
|
||||
owner = config.users.users.systemd-network.name;
|
||||
sopsFile = ./../../machines + "/${config.networking.hostName}/secrets.yaml";
|
||||
};
|
||||
|
||||
systemd.network = {
|
||||
enable = true;
|
||||
netdevs = {
|
||||
wg-he = {
|
||||
netdevConfig = {
|
||||
Kind = "wireguard";
|
||||
Name = "wg-he";
|
||||
};
|
||||
wireguardConfig = {
|
||||
PrivateKeyFile = config.sops.secrets.wg-he-private-key.path;
|
||||
} // (lib.optionalAttrs enableServer {
|
||||
ListenPort = serverPort;
|
||||
});
|
||||
wireguardPeers =
|
||||
if enableServer
|
||||
then
|
||||
map
|
||||
({ publicKey, subnets }: {
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = publicKey;
|
||||
AllowedIPs = subnets;
|
||||
};
|
||||
})
|
||||
(lib.attrValues
|
||||
(lib.filterAttrs
|
||||
(n: v: n != config.networking.hostName)
|
||||
peers))
|
||||
else
|
||||
lib.singleton {
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = peers."${serverHostName}".publicKey;
|
||||
AllowedIPs = "::/0";
|
||||
Endpoint = "85.215.73.203:${toString serverPort}";
|
||||
PersistentKeepalive = 25;
|
||||
};
|
||||
};
|
||||
};
|
||||
} // (lib.optionalAttrs enableServer {
|
||||
he = {
|
||||
netdevConfig = {
|
||||
Name = "he";
|
||||
Kind = "sit";
|
||||
MTUBytes = "1480";
|
||||
};
|
||||
tunnelConfig = {
|
||||
Remote = "216.66.80.30"; # tserv1.fra1.he.net
|
||||
Local = "85.215.73.203";
|
||||
TTL = 255;
|
||||
};
|
||||
};
|
||||
});
|
||||
networks = {
|
||||
wg-he = {
|
||||
name = "wg-he";
|
||||
networkConfig = lib.optionalAttrs enableServer {
|
||||
IPForward = "ipv6";
|
||||
};
|
||||
routes = lib.singleton {
|
||||
routeConfig.Destination = "2001:470:73b9::/48";
|
||||
};
|
||||
};
|
||||
} // (lib.optionalAttrs enableServer {
|
||||
he = {
|
||||
name = "he";
|
||||
address = lib.singleton "2001:470:1f0a:5db::2/64";
|
||||
gateway = lib.singleton "2001:470:1f0a:5db::1";
|
||||
routingPolicyRules = lib.singleton {
|
||||
routingPolicyRuleConfig = {
|
||||
From = "2001:470:73b9::/48";
|
||||
Table = "0x73b9";
|
||||
};
|
||||
};
|
||||
routes = lib.singleton {
|
||||
routeConfig = {
|
||||
Gateway = "2001:470:1f0a:5db::1";
|
||||
Table = "0x73b9";
|
||||
};
|
||||
};
|
||||
};
|
||||
# FIXME interface name is hardcoded
|
||||
eth0 = {
|
||||
networkConfig.Tunnel = "he";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
networking.firewall.allowedUDPPorts = lib.optional enableServer serverPort;
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue