diff --git a/default.nix b/default.nix index de10968..5394efb 100644 --- a/default.nix +++ b/default.nix @@ -4,7 +4,6 @@ with lib; let cfg = config.ffnix; - activeDomains = attrsets.filterAttrs (n: v: v.enable) cfg.domains; in { options.ffnix = { @@ -52,6 +51,13 @@ in routingTable = mkOption { type = types.int; }; + defaultNullRoute = mkOption { + type = types.bool; + default = true; + description = '' + Create a Null-Route in the routing-table to allow traffic leaks on the gateways default route when uplink is down. + ''; + }; mtu = mkOption { type = types.int; }; @@ -71,6 +77,10 @@ in default = []; type = types.listOf types.str; }; + batmanAlgorithm = mkOption { + default = "batman-iv"; + type = types.str; + }; tunnels = mkOption { default = {}; type = (pkgs.formats.json {}).type; @@ -85,10 +95,10 @@ in programs.mtr.enable = true; - environment.etc."ffnix.json".source = pkgs.writeText "ffnix.json" (generators.toJSON {} activeDomains); }; imports = [ + ./modules ./modules/batman.nix ./modules/fastd.nix ./modules/bird diff --git a/modules/bird/default.nix b/modules/bird/default.nix index e17b80c..72ec071 100644 --- a/modules/bird/default.nix +++ b/modules/bird/default.nix @@ -1,7 +1,5 @@ { config, lib, pkgs, ... }: -with import ../common-vars.nix { inherit lib config; }; - let cfg = config.ffnix.bird; in { diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..5ead52f --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,95 @@ +{ pkgs, config, lib, ... }: + +with lib; + +let + cfg = config.ffnix; + activeDomains = attrsets.filterAttrs (n: v: v.enable) cfg.domains; + + mkDomain = name: domCfg: + let + mkIfName = type: + if type == "bridge" then "br-${name}" else + if type == "batman" then "bat-${name}" else + throw "unknown interface type ${type}, coud not generate name"; + in { + networks."10-lo" = { + routes = if !domCfg.defaultNullRoute then [] else [ + { + routeConfig = { + Destination = "0.0.0.0/0"; + Metric = 200; + Type = "unreachable"; + Table = domCfg.routingTable; + }; + } + { + routeConfig = { + Destination = "::/0"; + Metric = 200; + Type = "unreachable"; + Table = domCfg.routingTable; + }; + } + ]; + }; + + netdevs."30-${mkIfName "bridge"}".netdevConfig = { + Name = mkIfName "bridge"; + Kind = "bridge"; + }; + networks."30-${mkIfName "bridge"}" = { + matchConfig.Name = mkIfName "bridge"; + linkConfig.RequiredForOnline = "no"; + address = domCfg.addresses; + routes = map (prefix: { + routeConfig = { + Destination = prefix; + Scope = "link"; + Table = domCfg.routingTable; + }; + }) (domCfg.ipv6Prefixes ++ [ domCfg.ipv4Prefix ]); + routingPolicyRules = [ + { + routingPolicyRuleConfig = { + IncomingInterface = mkIfName "bridge"; + Table = domCfg.routingTable; + Family = "both"; + }; + } + ] ++ map (prefix: { + routingPolicyRuleConfig = { + From = prefix; + Table = domCfg.routingTable; + }; + }) (domCfg.ipv6Prefixes ++ [ domCfg.ipv4Prefix ]); + }; + + netdevs."30-${mkIfName "batman"}" = mkIf (!cfg.batmanLegacy) { + netdevConfig = { + Kind = "batadv"; + Name = mkIfName "batman"; + }; + batmanAdvancedConfig = { + GatewayMode = "server"; + RoutingAlgorithm = domCfg.batmanAlgorithm; + OriginatorIntervalSec = 5; + }; + }; + networks."30-${mkIfName "batman"}" = { + matchConfig.Name = mkIfName "batman"; + bridge = [ "${mkIfName "bridge"}" ]; + }; + }; + + domConfigs = map (key: getAttr key (mapAttrs mkDomain activeDomains)) (attrNames activeDomains); + mergedConfigs = mapAttrs (name: value: mkMerge value) (attrsets.zipAttrs (map (x: removeAttrs x [ "foo" ]) domConfigs)); + +in +{ + config = mkIf cfg.enable { + environment.etc."ffnix.json".source = pkgs.writeText "ffnix.json" (generators.toJSON {} activeDomains); + systemd.network.netdevs = mergedConfigs.netdevs; + systemd.network.networks = mergedConfigs.networks; + }; +}