Added most of what will be needed to get this running
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# TODO: Dir creation and file permissions in nix
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.kirk.upnp;
|
||||
in {
|
||||
options.kirk.upnp = {
|
||||
enable = mkEnableOption "Enable port forwarding using UPNP.";
|
||||
|
||||
openTcpPorts = mkOption {
|
||||
type = with types; listOf port;
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
What TCP ports to open using UPNP.
|
||||
'';
|
||||
example = [ 46382 38473 ];
|
||||
};
|
||||
|
||||
openUdpPorts = mkOption {
|
||||
type = with types; listOf port;
|
||||
default = [];
|
||||
description = lib.mdDoc ''
|
||||
What UDP ports to open using UPNP.
|
||||
'';
|
||||
example = [ 46382 38473 ];
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# UPNPC firewall access, if not set, then upnpc will fail with "No IGD
|
||||
# UPnP Device found !"
|
||||
#
|
||||
# Alternatively, I also tried allowing all traffic from the router. But
|
||||
# I assume that the official way is cleaner/more secure:
|
||||
# ```nix
|
||||
# networking.firewall.extraCommands = ''
|
||||
# iptables -I INPUT -p udp -s 192.168.1.1 -j ACCEPT
|
||||
# iptables -I OUTPUT -p udp -d 192.168.1.1 -j ACCEPT
|
||||
# '';
|
||||
# ```
|
||||
#
|
||||
# See:
|
||||
# https://github.com/miniupnp/miniupnp/blob/8ced59d384de13689d3b1c32405bcb562030b241/miniupnpc/README
|
||||
#
|
||||
# TODO: Understand this properly
|
||||
networking.firewall.extraCommands = ''
|
||||
# Rules for IPv4:
|
||||
${pkgs.ipset}/bin/ipset -exist create upnp hash:ip,port timeout 3
|
||||
iptables -A OUTPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j SET --add-set upnp src,src --exist
|
||||
iptables -A INPUT -p udp -m set --match-set upnp dst,dst -j ACCEPT
|
||||
iptables -A INPUT -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT
|
||||
|
||||
# Rules for IPv6:
|
||||
${pkgs.ipset}/bin/ipset -exist create upnp6 hash:ip,port timeout 3 family inet6
|
||||
ip6tables -A OUTPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist
|
||||
ip6tables -A OUTPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j SET --add-set upnp6 src,src --exist
|
||||
ip6tables -A INPUT -p udp -m set --match-set upnp6 dst,dst -j ACCEPT
|
||||
ip6tables -A INPUT -d ff02::c/128 -p udp -m udp --dport 1900 -j ACCEPT
|
||||
ip6tables -A INPUT -d ff05::c/128 -p udp -m udp --dport 1900 -j ACCEPT
|
||||
'';
|
||||
|
||||
systemd = {
|
||||
services.upnpc = let
|
||||
upnp-ports = pkgs.writeShellApplication {
|
||||
name = "upnp-ports";
|
||||
|
||||
runtimeInputs = with pkgs; [miniupnpc];
|
||||
|
||||
text = (
|
||||
strings.concatMapStrings (x: "upnpc -r ${builtins.toString x} UDP" + "\n") cfg.openUpdPorts ++
|
||||
strings.concatMapStrings (x: "upnpc -r ${builtins.toString x} TCP" + "\n") cfg.openTcpPorts ++
|
||||
''echo "Successfully requested upnp ports to be opened".''
|
||||
);
|
||||
};
|
||||
in mkIf cfg.upnp.enable {
|
||||
enable = true;
|
||||
description = "Sets port on router";
|
||||
script = "${upnp-ports}/bin/upnp-ports";
|
||||
|
||||
serviceConfig = {
|
||||
User = "root";
|
||||
Type = "oneshot";
|
||||
};
|
||||
};
|
||||
|
||||
timers = {
|
||||
upnpc = mkIf cfg.upnp.enable {
|
||||
description = "Sets port on router";
|
||||
wantedBy = ["timers.target"];
|
||||
|
||||
timerConfig = {
|
||||
OnCalendar = "hourly";
|
||||
Persistent = "true"; # Run service immediately if last window was missed
|
||||
RandomizedDelaySec = "5m"; # Run service OnCalendar +- 1h
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user