146 lines
5.5 KiB
Nix
146 lines
5.5 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
externalInterface = config.my.interfaces.${config.networking.hostName};
|
|
wgInterface = "wg0";
|
|
ips = {
|
|
homeServer = config.my.ips.wg-server;
|
|
wgWorkstation = config.my.ips.wg-workstation;
|
|
wgFriend1 = config.my.ips.wg-friend1;
|
|
wgFriend6 = config.my.ips.wg-friend6;
|
|
};
|
|
subnets = {
|
|
wgFriends = config.my.subnets.wg-friends;
|
|
wgGuests = config.my.subnets.wg-guests;
|
|
wgHomelab = config.my.subnets.wg-homelab;
|
|
};
|
|
ports = {
|
|
inherit (config.my.ports)
|
|
giteaSsh
|
|
qbittorrent
|
|
ssh
|
|
wg
|
|
;
|
|
web = [
|
|
80
|
|
443
|
|
];
|
|
syncthing = config.my.ports.syncthingRelay;
|
|
synapseFederation = config.my.ports.synapseSsl;
|
|
};
|
|
portsStr = {
|
|
syncthing = toString config.my.ports.syncthingRelay;
|
|
synapseFederation = toString config.my.ports.synapseSsl;
|
|
synapseClient = toString config.my.servers.synapse.port;
|
|
syncplay = toString config.my.servers.syncplay.port;
|
|
synctube = toString config.my.servers.synctube.port;
|
|
stash = toString config.my.servers.stash.port;
|
|
jellyfin = toString config.my.servers.jellyfin.port;
|
|
audiobookshelf = toString config.my.servers.audiobookshelf.port;
|
|
kavita = toString config.my.servers.kavita.port;
|
|
openWebui = toString config.my.ports.openWebui;
|
|
sillytavern = toString config.my.ports.sillytavern;
|
|
ollama = toString config.my.ports.ollama;
|
|
comfyui = toString config.my.ports.comfyui;
|
|
};
|
|
forwardedPorts = [
|
|
{
|
|
comment = "snat ssh forward";
|
|
port = ports.giteaSsh;
|
|
proto = "tcp";
|
|
}
|
|
{
|
|
comment = "snat qbittorrent tcp forward";
|
|
port = ports.qbittorrent;
|
|
proto = "tcp";
|
|
}
|
|
{
|
|
comment = "snat qbittorrent udp forward";
|
|
port = ports.qbittorrent;
|
|
proto = "udp";
|
|
}
|
|
];
|
|
mkForwardPort =
|
|
{ port, proto, ... }:
|
|
{
|
|
sourcePort = port;
|
|
inherit proto;
|
|
destination = "${ips.homeServer}:${toString port}";
|
|
};
|
|
mkSnatRule =
|
|
{
|
|
comment,
|
|
port,
|
|
proto,
|
|
...
|
|
}:
|
|
''iifname "${externalInterface}" oifname "${wgInterface}" ip daddr ${ips.homeServer}/32 ${proto} dport ${toString port} masquerade comment "${comment}"'';
|
|
in
|
|
{
|
|
networking = {
|
|
nat = {
|
|
inherit externalInterface;
|
|
enable = true;
|
|
internalInterfaces = [ wgInterface ];
|
|
forwardPorts = map mkForwardPort forwardedPorts;
|
|
};
|
|
nftables = {
|
|
enable = true;
|
|
tables.vps-snat = {
|
|
family = "ip";
|
|
content = ''
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat;
|
|
iifname "${wgInterface}" oifname "${externalInterface}" ip saddr ${subnets.wgHomelab} masquerade comment "snat homelab egress"
|
|
${lib.concatStringsSep "\n " (map mkSnatRule forwardedPorts)}
|
|
}
|
|
'';
|
|
};
|
|
};
|
|
firewall = {
|
|
enable = true;
|
|
filterForward = true;
|
|
checkReversePath = "loose";
|
|
allowedTCPPorts = [
|
|
ports.ssh
|
|
ports.qbittorrent
|
|
]
|
|
++ ports.web;
|
|
allowedUDPPorts = [
|
|
ports.wg
|
|
ports.qbittorrent
|
|
];
|
|
extraForwardRules = ''
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.syncthing} accept
|
|
iifname "${wgInterface}" ip saddr ${ips.homeServer}/32 ip daddr ${subnets.wgFriends} tcp dport ${portsStr.syncthing} accept
|
|
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 tcp dport { ${portsStr.synapseClient}, ${portsStr.synapseFederation}, ${portsStr.syncplay}, ${portsStr.synctube} } accept
|
|
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} ip daddr ${ips.homeServer}/32 icmp type echo-request accept
|
|
iifname "${wgInterface}" ip saddr ${ips.wgFriend1}/32 ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.stash} accept
|
|
iifname "${wgInterface}" ip saddr ${ips.wgFriend6}/32 ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.stash} accept
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} ip daddr ${ips.homeServer}/32 tcp dport { ${portsStr.stash}, ${portsStr.jellyfin}, ${portsStr.audiobookshelf}, ${portsStr.kavita} } accept
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} ip daddr ${ips.homeServer}/32 icmp type echo-request accept
|
|
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} ip daddr ${ips.homeServer}/32 accept
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} ip daddr ${ips.wgWorkstation}/32 tcp dport { ${portsStr.openWebui}, ${portsStr.sillytavern}, ${portsStr.ollama}, ${portsStr.comfyui} } accept
|
|
iifname "${wgInterface}" ip saddr ${ips.wgWorkstation}/32 ip daddr ${subnets.wgHomelab} tcp sport { ${portsStr.openWebui}, ${portsStr.sillytavern}, ${portsStr.ollama}, ${portsStr.comfyui} } accept
|
|
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgHomelab} oifname "${externalInterface}" accept
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgFriends} oifname "${externalInterface}" accept
|
|
iifname "${wgInterface}" ip saddr ${subnets.wgGuests} oifname "${externalInterface}" accept
|
|
|
|
ip saddr ${subnets.wgFriends} ip daddr ${subnets.wgHomelab} drop
|
|
ip saddr ${subnets.wgHomelab} ip daddr ${subnets.wgFriends} drop
|
|
ip saddr ${subnets.wgGuests} ip daddr ${subnets.wgHomelab} drop
|
|
ip saddr ${subnets.wgHomelab} ip daddr ${subnets.wgGuests} drop
|
|
ip saddr ${subnets.wgGuests} ip daddr ${subnets.wgFriends} drop
|
|
ip saddr ${subnets.wgFriends} ip daddr ${subnets.wgGuests} drop
|
|
'';
|
|
};
|
|
};
|
|
}
|