nixformat + firewall rules to port forward qbittorrent
This commit is contained in:
@@ -7,6 +7,9 @@
|
||||
}:
|
||||
let
|
||||
lidarrMbGapId = 968;
|
||||
qbittorrentRouteTable = 200;
|
||||
serverInterface = config.my.interfaces.server;
|
||||
jawzUid = config.users.users.jawz.uid;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
@@ -70,7 +73,11 @@ in
|
||||
};
|
||||
networking = {
|
||||
hostName = "server";
|
||||
iproute2.rttablesExtraConfig = ''
|
||||
${toString qbittorrentRouteTable} qbittorrent
|
||||
'';
|
||||
wireguard.interfaces.wg0 = lib.mkIf config.my.secureHost {
|
||||
allowedIPsAsRoutes = false;
|
||||
ips = [ "${config.my.ips.wg-server}/32" ];
|
||||
privateKeyFile = config.sops.secrets."server/private".path;
|
||||
peers = [
|
||||
@@ -78,6 +85,7 @@ in
|
||||
publicKey = "dFbiSekBwnZomarcS31o5+w6imHjMPNCipkfc2fZ3GY=";
|
||||
endpoint = "${config.my.ips.vps}:51820";
|
||||
allowedIPs = [
|
||||
"0.0.0.0/0"
|
||||
"${config.my.ips.wg-vps}/32"
|
||||
config.my.subnets.wg-homelab
|
||||
config.my.subnets.wg-friends
|
||||
@@ -92,6 +100,71 @@ in
|
||||
interfaces.wg0.allowedTCPPorts = [ config.my.servers.nextcloud.port ];
|
||||
};
|
||||
};
|
||||
systemd.services.qbittorrent-vpn-routing = lib.mkIf config.my.secureHost {
|
||||
description = "Route qBittorrent user traffic through the VPS WireGuard tunnel";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
path = with pkgs; [
|
||||
coreutils
|
||||
gnugrep
|
||||
iproute2
|
||||
];
|
||||
script = ''
|
||||
for _ in $(seq 1 30); do
|
||||
if ip -4 addr show dev wg0 >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if ! ip -4 addr show dev wg0 >/dev/null 2>&1; then
|
||||
echo "wg0 is not available"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ip -4 route replace ${config.my.subnets.wg-homelab} dev wg0 src ${config.my.ips.wg-server}
|
||||
ip -4 route replace ${config.my.subnets.wg-friends} dev wg0 src ${config.my.ips.wg-server}
|
||||
ip -4 route replace ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server}
|
||||
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-homelab} dev wg0 src ${config.my.ips.wg-server}
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-friends} dev wg0 src ${config.my.ips.wg-server}
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.subnets.wg-guests} dev wg0 src ${config.my.ips.wg-server}
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} 10.88.0.0/16 dev podman0 src 10.88.0.1
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} 192.168.100.0/24 dev ${serverInterface} src ${config.my.ips.server}
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} ${config.my.ips.vps}/32 via ${config.my.ips.router} dev ${serverInterface} src ${config.my.ips.server}
|
||||
ip -4 route replace table ${toString qbittorrentRouteTable} default via ${config.my.ips.wg-vps} dev wg0 src ${config.my.ips.wg-server}
|
||||
|
||||
while ip -4 rule show | grep -q 'uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}'; do
|
||||
ip -4 rule del uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}
|
||||
done
|
||||
|
||||
while ip -4 rule show | grep -q 'from ${config.my.ips.wg-server} lookup ${toString qbittorrentRouteTable}'; do
|
||||
ip -4 rule del from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable}
|
||||
done
|
||||
|
||||
ip -4 rule add from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} priority 9999
|
||||
ip -4 rule add uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} priority 10000
|
||||
'';
|
||||
preStop = ''
|
||||
while ip -4 rule show | grep -q 'from ${config.my.ips.wg-server} lookup ${toString qbittorrentRouteTable}'; do
|
||||
ip -4 rule del from ${config.my.ips.wg-server}/32 lookup ${toString qbittorrentRouteTable} || true
|
||||
done
|
||||
|
||||
while ip -4 rule show | grep -q 'uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable}'; do
|
||||
ip -4 rule del uidrange ${toString jawzUid}-${toString jawzUid} lookup ${toString qbittorrentRouteTable} || true
|
||||
done
|
||||
|
||||
ip -4 route del ${config.my.subnets.wg-homelab} dev wg0 || true
|
||||
ip -4 route del ${config.my.subnets.wg-friends} dev wg0 || true
|
||||
ip -4 route del ${config.my.subnets.wg-guests} dev wg0 || true
|
||||
ip -4 route flush table ${toString qbittorrentRouteTable} || true
|
||||
'';
|
||||
serviceConfig = {
|
||||
RemainAfterExit = true;
|
||||
Type = "oneshot";
|
||||
};
|
||||
};
|
||||
users.users.jawz.packages = builtins.attrValues {
|
||||
inherit (pkgs) podman-compose attic-client;
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ let
|
||||
};
|
||||
ports = {
|
||||
inherit (config.my.ports) giteaSsh;
|
||||
inherit (config.my.ports) qbittorrent;
|
||||
inherit (config.my.ports) ssh;
|
||||
web = [
|
||||
80
|
||||
@@ -33,7 +34,6 @@ let
|
||||
synapseFederation = config.my.ports.synapseSsl;
|
||||
};
|
||||
portsStr = {
|
||||
giteaSsh = toString ports.giteaSsh;
|
||||
syncthing = toString ports.syncthing;
|
||||
synapseFederation = toString ports.synapseFederation;
|
||||
synapseClient = toString config.my.servers.synapse.port;
|
||||
@@ -48,6 +48,38 @@ let
|
||||
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
|
||||
{
|
||||
imports = [
|
||||
@@ -99,14 +131,8 @@ in
|
||||
nat = {
|
||||
inherit externalInterface;
|
||||
enable = true;
|
||||
internalInterfaces = [ "wg0" ];
|
||||
forwardPorts = [
|
||||
{
|
||||
sourcePort = ports.giteaSsh;
|
||||
proto = "tcp";
|
||||
destination = "${ips.homeServer}:${portsStr.giteaSsh}";
|
||||
}
|
||||
];
|
||||
internalInterfaces = [ wgInterface ];
|
||||
forwardPorts = map mkForwardPort forwardedPorts;
|
||||
};
|
||||
nftables = {
|
||||
enable = true;
|
||||
@@ -115,7 +141,8 @@ in
|
||||
content = ''
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat;
|
||||
iifname "${externalInterface}" oifname "${wgInterface}" ip daddr ${ips.homeServer}/32 tcp dport ${portsStr.giteaSsh} masquerade comment "snat ssh forward"
|
||||
iifname "${wgInterface}" oifname "${externalInterface}" ip saddr ${subnets.wgHomelab} masquerade comment "snat homelab egress"
|
||||
${lib.concatStringsSep "\n " (map mkSnatRule forwardedPorts)}
|
||||
}
|
||||
'';
|
||||
};
|
||||
@@ -124,8 +151,15 @@ in
|
||||
enable = true;
|
||||
filterForward = true;
|
||||
checkReversePath = "loose";
|
||||
allowedTCPPorts = [ ports.ssh ] ++ ports.web;
|
||||
allowedUDPPorts = [ ports.wg ];
|
||||
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
|
||||
@@ -142,6 +176,7 @@ in
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user