diff --git a/modules/default.nix b/modules/default.nix index 4335222..3034f97 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -4,6 +4,7 @@ imports = [ ./yate ./forward-filter + ./policyrouting ./uplink-selector ./fieldpoc ]; diff --git a/modules/policyrouting/default.nix b/modules/policyrouting/default.nix new file mode 100644 index 0000000..6849dd8 --- /dev/null +++ b/modules/policyrouting/default.nix @@ -0,0 +1,116 @@ +{ 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"; + }; + }; + }; + +} diff --git a/modules/uplink-selector/default.nix b/modules/uplink-selector/default.nix index f917921..57b4082 100644 --- a/modules/uplink-selector/default.nix +++ b/modules/uplink-selector/default.nix @@ -6,35 +6,6 @@ let cfg = config.clerie.uplink-selector; - startScript = pkgs.writeScriptBin "uplink-selector-start" '' - #! ${pkgs.runtimeShell} -e - - ip46() { - ip "$@" - ip -6 "$@" - } - - ip46 rule flush || true - - # Route everything except default route first - ip46 rule add lookup main suppress_prefixlength 0 prio 10000 - - # Decide which uplink to use - ${concatStrings (mapAttrsToList (iface: ifacecfg: '' - ip46 rule add iif ${iface} lookup ${cfg.uplinks.${ifacecfg.uplink}.table} prio 20000 - '') cfg.interfaces)} - - # Fallback to the main default table - ip46 rule add lookup main prio 32000 - ''; - - stopScript = pkgs.writeScriptBin "uplink-selector-stop" '' - #! ${pkgs.runtimeShell} -e - - ip rule flush || true - ip -6 rule flush || true - ''; - in { @@ -90,25 +61,14 @@ in config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.iproute2 ]; + clerie.policyrouting.enable = true; - systemd.services.uplink-selector = { - description = "Uplink Selector"; - before = [ "network.target" ]; - wantedBy = [ "network.target" ]; - after = [ "network-pre.target" ]; + clerie.policyrouting.rules = [ + { rule = "lookup main suppress_prefixlength 0"; prio = 10000; } + ] ++ (mapAttrsToList (iface: ifacecfg: { + rule = "iif ${iface} lookup ${cfg.uplinks.${ifacecfg.uplink}.table}"; prio = 20000; + }) cfg.interfaces); - path = [ pkgs.iproute2 ]; - - unitConfig.ConditionCapability = "CAP_NET_ADMIN"; - - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = "@${startScript}/bin/uplink-selector-start uplink-selector-start"; - ExecStop = "@${stopScript}/bin/uplink-selector-stop uplink-selector-stop"; - }; - }; }; }