infrastructure/modules/nixos/access/local.nix

166 lines
5 KiB
Nix

{
pkgs,
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkMerge mkBefore mkAfter;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.strings) optionalString;
inherit (config) networking;
cfg = config.networking.access.localaddrs;
in {
options.networking.access.localaddrs = with lib.types; {
enable =
mkEnableOption "localaddrs"
// {
default = networking.firewall.interfaces.local.nftables.enable;
};
stateDir = mkOption {
type = path;
default = "/var/lib/localaddrs";
};
reloadScript = mkOption {
type = path;
readOnly = true;
};
nftablesInclude = mkOption {
type = lines;
readOnly = true;
};
};
config.networking.access = {
localaddrs = {
nftablesInclude = mkBefore (''
define localrange6 = 2001:568::/29
''
+ optionalString cfg.enable ''
include "${cfg.stateDir}/*.nft"
'');
reloadScript = let
localaddrs-reload = pkgs.writeShellScript "localaddrs-reload" ''
${config.systemd.package}/bin/systemctl reload localaddrs 2>/dev/null ||
${config.systemd.package}/bin/systemctl restart localaddrs ||
true
'';
in "${localaddrs-reload}";
};
moduleArgAttrs = {
inherit (cfg) localaddrs;
};
};
config.networking = {
nftables.ruleset = mkIf cfg.enable (mkBefore cfg.nftablesInclude);
firewall = {
interfaces.local = {
nftables.conditions = mkIf (cfg.enable && networking.enableIPv6) [ "ip6 saddr $localrange6" ];
};
};
};
config.systemd.services = let
localaddrs = pkgs.writeShellScript "localaddrs" ''
set -eu
getaddrs() {
local PREFIX=$1 PATTERN=$2 IPADDRS
IPADDRS=$(${pkgs.iproute2}/bin/ip -o addr show to "$PREFIX") || return $?
IPADDRS=$(printf '%s\n' "$IPADDRS" | ${pkgs.gnugrep}/bin/grep -o "$PATTERN") || return $?
if [[ -z $IPADDRS ]]; then
return 1
fi
printf '%s\n' "$IPADDRS"
}
getaddrs4() {
getaddrs 10.1.1.0/24 '[0-9]*\.[0-9.]*/[0-9]*'
}
getaddrs6() {
getaddrs 2001:568::/29 '[0-9a-f:]*:[0-9a-f:]*/[0-9]*'
}
stripcidr() {
local IPADDR
while read -r IPADDR; do
if [[ $IPADDR = ?*:?*:?*:?*:?*:?*:?*:?*/64 ]]; then
echo ''${IPADDR%:?*:?*:?*:?*/64}::/64
elif [[ $IPADDR = ?*:?*:?*:?*::*/64 ]] || [[ $IPADDR = ?*::?*:?*:?*:?*/64 ]]; then
echo ''${IPADDR%::*/64}::/64
elif [[ $IPADDR = *.*.*.*/24 ]]; then
echo "''${IPADDR%.*/24}.0/24"
else
echo "WARNING: localaddrs failed to parse CIDR: $IPADDR" >&2
echo "$IPADDR"
fi
done
}
mkdir -p $STATE_DIRECTORY
if LOCALADDRS4=$(getaddrs4); then
printf '%s\n' "$LOCALADDRS4" > $STATE_DIRECTORY/localaddrs4
stripcidr <<<"$LOCALADDRS4" > $STATE_DIRECTORY/localcidrs4
else
echo WARNING: localaddr4 not found >&2
fi
if LOCALADDRS6=$(getaddrs6); then
echo "$LOCALADDRS6" > $STATE_DIRECTORY/localaddrs6
stripcidr <<<"$LOCALADDRS6" > $STATE_DIRECTORY/localcidrs6
else
echo WARNING: localaddr6 not found >&2
fi
'';
localaddrs-nftables = pkgs.writeShellScript "localaddrs-nftables" ''
set -eu
LOCALADDR6=$(head -n1 "${cfg.stateDir}/localcidrs6" || true)
if [[ -n $LOCALADDR6 ]]; then
printf 'redefine localrange6 = %s\n' "$LOCALADDR6" > ${cfg.stateDir}/ranges.nft
fi
'';
localaddrs-nginx = pkgs.writeShellScript "localaddrs-nginx" ''
set -eu
LOCALADDR6=$(head -n1 "${cfg.stateDir}/localcidrs6" || true)
if [[ -n $LOCALADDR6 ]]; then
printf 'allow %s;\n' "$LOCALADDR6" > ${cfg.stateDir}/allow.nginx.conf
fi
LOCALADDR4=$(head -n1 "${cfg.stateDir}/localcidrs4" || true)
if [[ -n $LOCALADDR4 ]]; then
printf 'allow %s;\n' "$LOCALADDR4" >> ${cfg.stateDir}/allow.nginx.conf
fi
'';
in {
localaddrs = mkIf cfg.enable {
unitConfig = {
After = ["network-online.target"];
};
serviceConfig = rec {
StateDirectory = "localaddrs";
ExecStart = mkMerge [
["${localaddrs}"]
(mkIf networking.nftables.enable (mkAfter [
"${localaddrs-nftables}"
]))
(mkIf config.services.nginx.enable (mkAfter [
"${localaddrs-nginx}"
]))
];
ExecReload = ExecStart;
Type = "oneshot";
RemainAfterExit = true;
};
};
nftables = mkIf (networking.nftables.enable && cfg.enable) {
wants = ["localaddrs.service"];
serviceConfig = {
ExecReload = mkBefore [
"+${cfg.reloadScript}"
];
};
};
nginx = mkIf (config.services.nginx.enable && cfg.enable) rec {
wants = ["localaddrs.service"];
after = wants;
serviceConfig = {
ExecReload = mkBefore [
"+${cfg.reloadScript}"
];
};
};
};
}