{ config, lib, pkgs, ... }: with lib; let cfg = config.clerie.policyrouting; startScript = pkgs.writeScriptBin "policyrouting-start" '' #! ${pkgs.runtimeShell} -e ip -6 rule flush 2> /dev/null || true ip rule flush 2> /dev/null || true ${concatMapStrings (rule: '' ip -6 rule add ${rule.rule} prio ${toString rule.prio} '') (cfg.rules ++ cfg.rules6)} ${concatMapStrings (rule: '' ip rule add ${rule.rule} prio ${toString rule.prio} '') (cfg.rules ++ cfg.rules4)} ''; stopScript = pkgs.writeScriptBin "policyrouting-stop" '' #! ${pkgs.runtimeShell} -e ip -6 rule flush 2> /dev/null || true ip rule flush 2> /dev/null || true # Loading default settings ip -6 rule add from all lookup main prio 32766 ip rule add from all lookup main prio 32766 ip -6 rule add from all lookup default prio 32767 ip rule add from all lookup default prio 32767 ''; ruleOpts = { ... }: { options = { prio = mkOption { type = types.int; example = 20000; }; rule = mkOption { type = types.str; example = "from fd00:23:42::/64 lookup 20101"; }; }; }; in { options = { clerie.policyrouting = { enable = mkOption { type = types.bool; default = false; description = '' Enable policy routing ''; }; rules = mkOption { type = with types; listOf (submodule ruleOpts); default = []; description = "Rules applied both, to IPv6 and IPv4"; }; rules6 = mkOption { type = with types; listOf (submodule ruleOpts); default = []; description = "Rules applied to IPv6"; }; rules4 = mkOption { type = with types; listOf (submodule ruleOpts); default = []; description = "Rules applied to IPv4"; }; }; }; config = mkIf cfg.enable { # always use main routing table as a fallback clerie.policyrouting.rules = [ { rule = "lookup main"; prio = 32766; } { rule = "lookup default"; prio = 32767; } ]; environment.systemPackages = [ pkgs.iproute2 ]; systemd.services.policyrouting = { description = "Policyrouting"; before = [ "network.target" ]; wantedBy = [ "network.target" ]; after = [ "network-pre.target" ]; path = [ pkgs.iproute2 ]; unitConfig.ConditionCapability = "CAP_NET_ADMIN"; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStart = "@${startScript}/bin/policyrouting-start policyrouting-start"; ExecStop = "@${stopScript}/bin/policyrouting-stop policyrouting-stop"; }; }; }; }