diff --git a/config/default.nix b/config/default.nix index 9fecd61..691912d 100644 --- a/config/default.nix +++ b/config/default.nix @@ -19,6 +19,4 @@ in ++ lib.filesystem.listFilesRecursive ./net; site.net-combined = concatMapAttrsRecursive (name: value: { inherit (value) hosts4 hosts6; }) config.site.net; - - site.bgp.asn = 4242421127; } diff --git a/config/net/c3d2.nix b/config/net/c3d2.nix index 851e747..ee366ef 100644 --- a/config/net/c3d2.nix +++ b/config/net/c3d2.nix @@ -1,5 +1,4 @@ -{ config, lib, ... }: - +{ lib, ... }: { site.net.c3d2 = { dhcp = { @@ -109,34 +108,28 @@ c3d2.hwaddr = "0A:14:48:01:07:05"; core.hwaddr = "0A:14:48:01:07:04"; }; - bgp.allowedUpstreams = [ "anon1" "freifunk" ]; + ospf.allowedUpstreams = [ "anon1" "freifunk" ]; }; c3d2-gw1 = makeGateway { interfaces = { c3d2.hwaddr = "0A:14:48:01:21:01"; core.hwaddr = "0A:14:48:01:21:00"; }; - bgp.allowedUpstreams = [ "flpk-gw" "freifunk" "upstream4" "upstream3" "anon1" ]; + ospf.allowedUpstreams = [ "flpk-gw" "freifunk" "upstream4" "upstream3" "anon1" ]; }; c3d2-gw2 = makeGateway { interfaces = { c3d2.hwaddr = "0A:14:48:01:21:03"; core.hwaddr = "0A:14:48:01:21:02"; }; - bgp.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; + ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; }; c3d2-gw3 = makeGateway { interfaces = { c3d2.hwaddr = "0A:14:48:01:21:05"; core.hwaddr = "0A:14:48:01:21:04"; }; - bgp = { - peers.${config.site.net.core.hosts6.dn42.bgp} = { - type = "rr_client"; - name = "rr"; - }; - allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; - }; + ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; }; }; } diff --git a/config/net/cluster.nix b/config/net/cluster.nix index 983bc4b..d8550b8 100644 --- a/config/net/cluster.nix +++ b/config/net/cluster.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ lib, ... }: let cephMonServers = [ "server5" "server6" "server8" ]; in @@ -158,13 +158,7 @@ in type = "veth"; }; }; - bgp = { - peers.${config.site.net.core.hosts6.dn42.bgp} = { - type = "rr_client"; - name = "rr"; - }; - allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; - }; + ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; }; server3 = makeServer; server5 = makeServer; diff --git a/config/net/core.nix b/config/net/core.nix index 581a1ea..23c6e33 100644 --- a/config/net/core.nix +++ b/config/net/core.nix @@ -1,5 +1,3 @@ -{ config, lib, ... }: - { site.net.core = { domainName = "core.zentralwerk.org"; @@ -133,7 +131,6 @@ upstream3 = "fd23:42:c3d2:581::b:2"; upstream4 = "fd23:42:c3d2:581::b:3"; vpn-gw = "fd23:42:c3d2:581:9001::1"; - flpk-gw = "fd23:42:c3d2:581:9002::1"; }; up4 = { anon1 = "2a00:8180:2c00:281::9:1"; @@ -202,33 +199,15 @@ }; }; - site.hosts = lib.mkMerge ([ { + site.hosts = { bgp = { bgp = { + asn = 4242421127; peers = { - "172.22.99.253" = { - asn = 64699; - type = "external"; - name = "dn42_4"; - }; - "fe80::a800:42ff:fe7a:3246%c3d2" = { - asn = 64699; - type = "external"; - name = "dn42_6"; - }; - # ${config.site.net.core.subnet4} = {}; - ${config.site.net.core.subnets6.dn42} = { - type = "rr_server"; - name = "rr"; - }; + "172.22.99.253" = { asn = 64699; }; + "fe80::a800:42ff:fe7a:3246%c3d2" = { asn = 64699; }; }; - # allowedUpstreams = - # [ "upstream4" "upstream3" "anon1" "freifunk" ]; - nets4 = [ "172.20.0.0/14" "10.0.0.0/8" ]; - nets6 = - [ "fd00::/8" "2a00:8180:2c00:200::/56" ]; }; - role = "container"; interfaces = { c3d2 = { hwaddr = "0A:14:48:01:22:01"; @@ -239,21 +218,14 @@ type = "veth"; }; }; - }; - } ] ++ builtins.concatMap (hostName: - if hostName != "bgp" - # everyone in core peers with router "bgp" - then [ { - ${hostName}.bgp = { - # peers.${config.site.net.core.hosts4.bgp} = {}; - peers.${config.site.net.core.hosts6.dn42.bgp} = { - type = "rr_client"; - name = "rr"; - }; + ospf = { + allowedUpstreams = + [ "upstream4" "upstream3" "anon1" "freifunk" ]; + stubNets4 = [ "172.20.0.0/14" "10.0.0.0/8" ]; + stubNets6 = + [ "fd00::/8" "2a00:8180:2c00:200::/56" ]; }; - # TODO: upstreams - } ] - # except "bgp" itself :) - else [] - ) (builtins.attrNames config.site.net.core.hosts6.dn42)); + role = "container"; + }; + }; } diff --git a/config/net/flpk.nix b/config/net/flpk.nix index c6a5117..6828499 100644 --- a/config/net/flpk.nix +++ b/config/net/flpk.nix @@ -1,5 +1,3 @@ -{ config, ... }: - { site.net.flpk = { domainName = "flpk.zentralwerk.org"; @@ -50,15 +48,9 @@ }; }; }; - bgp = { - upstreamTable = "vpn_table"; + ospf = { allowedUpstreams = [ "upstream4" "upstream3" "freifunk" ]; - # IPv6 ::/0 via wireguard tunnel - allowedUpstreams6 = []; - peers.${config.site.net.core.subnets6.dn42} = { - type = "upstream"; - name = "up"; - }; + upstreamInstance = 2; }; role = "container"; }; diff --git a/config/net/mgmt.nix b/config/net/mgmt.nix index 7cbedec..b61f801 100644 --- a/config/net/mgmt.nix +++ b/config/net/mgmt.nix @@ -192,7 +192,10 @@ type = "veth"; }; }; - bgp.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; + ospf = { + allowedUpstreams = + [ "upstream4" "upstream3" "anon1" "freifunk" ]; + }; role = "container"; }; } diff --git a/config/net/priv.nix b/config/net/priv.nix index ff95957..af49442 100644 --- a/config/net/priv.nix +++ b/config/net/priv.nix @@ -38,7 +38,7 @@ lib.mkMerge ( core.type = "veth"; "priv${toString n}".type = "veth"; }; - bgp.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; + ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; }; } ) (seq 1 privCount) @@ -540,7 +540,7 @@ lib.mkMerge ( hwaddr = "0A:14:47:02:2A:19"; }; }; - bgp.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; + ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; }; priv18-gw = { interfaces = { diff --git a/config/net/pub.nix b/config/net/pub.nix index 049c29a..3d54c0e 100644 --- a/config/net/pub.nix +++ b/config/net/pub.nix @@ -39,7 +39,7 @@ type = "veth"; }; }; - bgp = { + ospf = { allowedUpstreams = [ "anon1" "freifunk" ]; allowedUpstreams6 = [ "flpk-gw" "anon1" "freifunk" ]; }; diff --git a/config/net/serv.nix b/config/net/serv.nix index 9de6d8b..f95ff19 100644 --- a/config/net/serv.nix +++ b/config/net/serv.nix @@ -206,7 +206,7 @@ gw6 = null; }; }; - bgp.allowedUpstreams = + ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; }; stats = makeContainer { diff --git a/config/net/upstream.nix b/config/net/upstream.nix index 7c31eb1..285f600 100644 --- a/config/net/upstream.nix +++ b/config/net/upstream.nix @@ -24,12 +24,8 @@ in }; }; }; + ospf.upstreamInstance = 7; role = "container"; - bgp.peers.${config.site.net.core.subnets6.dn42} = { - asn = config.site.hosts.upstream3.bgp.asn; - type = "upstream"; - name = "up"; - }; }; upstream4 = rec { @@ -325,19 +321,17 @@ in }; }; }; - bgp = { - nets4 = [ + ospf = { + upstreamInstance = 8; + stubNets4 = [ "${interfaces.up4-pppoe.upstream.staticIpv4Address}/32" ]; - peers.${config.site.net.core.subnets6.dn42} = { - asn = config.site.hosts.upstream4.bgp.asn; - type = "upstream"; - name = "up"; - }; }; role = "container"; }; + freifunk.ospf.upstreamInstance = 6; + anon1 = { interfaces = { core = { @@ -352,16 +346,9 @@ in }; }; }; - bgp = { - upstreamTable = "vpn_table"; + ospf = { allowedUpstreams = [ "upstream3" "upstream4" "freifunk" ]; - # IPv6 ::/0 via wireguard tunnel - allowedUpstreams6 = []; - peers.${config.site.net.core.subnets6.dn42} = { - asn = config.site.hosts.upstream3.bgp.asn; - type = "upstream"; - name = "up"; - }; + upstreamInstance = 5; }; role = "container"; }; diff --git a/config/net/vpn.nix b/config/net/vpn.nix index fb43cc8..378d444 100644 --- a/config/net/vpn.nix +++ b/config/net/vpn.nix @@ -33,6 +33,8 @@ type = "wireguard"; }; }; - bgp.allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ]; + ospf = { + allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ]; + }; }; } diff --git a/config/secrets.nix b/config/secrets.nix index 3ebb3d4..d1fc3fc 100644 --- a/config/secrets.nix +++ b/config/secrets.nix @@ -1,5 +1,9 @@ # Dummy secrets for testing { + site.net = { + core.ospf.secret = "encrypted"; + }; + site.hosts = { ap1.password = "encrypted"; ap2.password = "encrypted"; diff --git a/nix/lib/config/options.nix b/nix/lib/config/options.nix index 06105bf..14fa191 100644 --- a/nix/lib/config/options.nix +++ b/nix/lib/config/options.nix @@ -148,6 +148,12 @@ let type = with types; attrsOf (attrsOf str); default = {}; }; + ospf = { + secret = mkOption { + type = with types; nullOr str; + default = null; + }; + }; dhcp = mkOption { type = with types; nullOr (submodule { options = dhcpOpts; }); default = null; @@ -384,10 +390,35 @@ let }; }); default = []; }; + ospf.stubNets4 = mkOption { + type = with types; listOf str; + default = []; + description = "Additional IPv4 networks to announce"; + }; + ospf.stubNets6 = mkOption { + type = with types; listOf str; + default = []; + description = "Additional IPv6 networks to announce"; + }; + ospf.allowedUpstreams = mkOption { + type = with types; listOf str; + default = []; + description = "Accept default routes from these OSPF routers, in order of preference"; + }; + ospf.allowedUpstreams6 = mkOption { + type = with types; listOf str; + default = config.site.hosts.${name}.ospf.allowedUpstreams; + description = "Accept IPv6 default routes from these OSPF3 routers, in order of preference"; + }; + ospf.upstreamInstance = mkOption { + type = with types; nullOr int; + default = null; + description = "OSPF instance for advertising the default route"; + }; bgp = mkOption { default = null; type = with types; nullOr (submodule { - options = bgpOpts name; + options = bgpOpts; }); }; services.dns = { @@ -458,52 +489,20 @@ let }; }; - bgpOpts = hostName: { + bgpOpts = { asn = mkOption { type = types.int; - default = config.site.bgp.asn; }; peers = mkOption { - type = with types; attrsOf (submodule (submoduleArg: { + type = with types; attrsOf (submodule ({ ... }: { options = { asn = mkOption { type = types.int; - default = config.site.bgp.asn; - }; - name = mkOption { - type = types.str; - }; - type = mkOption { - type = types.enum [ "external" "rr_server" "rr_client" "upstream" ]; }; }; })); default = {}; }; - nets4 = mkOption { - type = with types; listOf str; - default = []; - description = "Additional IPv4 networks to announce"; - }; - nets6 = mkOption { - type = with types; listOf str; - default = []; - description = "Additional IPv6 networks to announce"; - }; - allowedUpstreams = mkOption { - type = with types; listOf str; - default = []; - description = "Accept default routes from these BGP routers, in order of preference"; - }; - allowedUpstreams6 = mkOption { - type = with types; listOf str; - default = config.site.hosts.${hostName}.bgp.allowedUpstreams; - description = "Accept IPv6 default routes from these BGP routers, in order of preference"; - }; - upstreamTable = mkOption { - type = with types; nullOr str; - default = null; - }; }; linkOpts = hostName: { name, ... }: { @@ -614,12 +613,6 @@ in default = "secret"; }; }; - - bgp = { - asn = mkOption { - type = types.int; - }; - }; }; config.warnings = @@ -640,16 +633,16 @@ in reportCollisions = name: getter: xs: map (k: "Duplicate ${name}: ${k}") (findCollisions getter xs); - bgpUpstreamXorGw = + ospfUpstreamXorGw = builtins.concatMap (hostName: let hostConf = config.site.hosts.${hostName}; gwNets = builtins.filter (netName: hostConf.interfaces.${netName}.gw4 != null ) (builtins.attrNames hostConf.interfaces); - in if gwNets != [] && hostConf.bgp.allowedUpstreams or [] != [] + in if gwNets != [] && hostConf.ospf.allowedUpstreams != [] then [ '' - Host ${hostName} has gateway on ${builtins.head gwNets} but accepts default routes from BGP + Host ${hostName} has gateway on ${builtins.head gwNets} but accepts default routes from OSPF '' ] else [] ) (builtins.attrNames config.site.hosts); @@ -657,7 +650,7 @@ in (reportCollisions "VLAN tag" (x: lib.optional (x.vlan != null) x.vlan) config.site.net) ++ (reportCollisions "IPv4 subnet" (x: if x.subnet4 == null then [] else [x.subnet4]) config.site.net) ++ (reportCollisions "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net) ++ - bgpUpstreamXorGw; + ospfUpstreamXorGw; config.assertions = # Duplicate host/net name check diff --git a/nix/nixos-module/container/bird.nix b/nix/nixos-module/container/bird.nix index d27858d..47f972a 100644 --- a/nix/nixos-module/container/bird.nix +++ b/nix/nixos-module/container/bird.nix @@ -25,42 +25,6 @@ let n = n; x = builtins.head list; } ] ++ (enumerate (n + 1) (builtins.tail list)); - - nets4 = - hostConf.bgp.nets4 - ++ - builtins.concatMap (net: - if net != "core" - then - let - subnet4 = config.site.net.${net}.subnet4 or null; - in lib.optional (subnet4 != null) subnet4 - else - [] - ) (builtins.attrNames hostConf.interfaces); - - nets6 = - hostConf.bgp.nets6 - ++ - builtins.concatMap (net: - if net != "core" - then - builtins.attrValues config.site.net.${net}.subnets6 or {} - else - [] - ) (builtins.attrNames hostConf.interfaces); - - upstreamsToOrder = upstreams: - builtins.foldl' (order: { n, x }: - order // { - ${x} = n; - } - ) {} (enumerate 1 upstreams); - upstream4Order = upstreamsToOrder hostConf.bgp.allowedUpstreams; - upstream6Order = upstreamsToOrder hostConf.bgp.allowedUpstreams6; - allowedUpstreams = lib.unique ( - hostConf.bgp.allowedUpstreams ++ hostConf.bgp.allowedUpstreams6 - ); in { services.bird2 = { @@ -71,13 +35,31 @@ in protocol kernel K4 { learn; ipv4 { - export all; + ${if isUpstream + then '' + # Install all routes but the default route on upstreams + export where net != 0.0.0.0/0; + # Learn the upstream default route + import where net = 0.0.0.0/0; + '' + else '' + export all; + ''} }; } protocol kernel K6 { learn; ipv6 { - export all; + ${if isUpstream + then '' + # Install all routes but the default route on upstreams + export where net != ::/0; + # Learn the upstream default route + import where net = ::/0; + '' + else '' + export all; + ''} }; } protocol device { @@ -102,7 +84,10 @@ in check link yes; } - ${lib.optionalString (hostConf.bgp.upstreamTable != null) '' + ${lib.optionalString ( + builtins.match "anon.*" hostName != null || + hostName == "flpk-gw" + ) '' # BIRD routing table for Wireguard transport ipv4 table vpn_table; @@ -143,6 +128,235 @@ in } ''} + # OSPFv2 for site-local IPv4 + protocol ospf v2 ZW4 { + ipv4 { + import all; + # OSPF is self-contained + export none; + }; + area 0 { + ${builtins.concatStringsSep "\n" ( + builtins.attrValues ( + builtins.mapAttrs (net: _: + # Enable OSPF only on networks with a secret. + if config.site.net ? "${net}" && config.site.net.${net}.ospf.secret != null + then '' + interface "${net}" { + hello 10; + wait 20; + + authentication cryptographic; + password "${config.site.net.${net}.ospf.secret}"; + }; + '' + else '' + interface "${net}" { + stub yes; + cost 10; + }; + '' + ) hostConf.interfaces + ) + )} + ${builtins.concatStringsSep "\n" ( + map (stubnet4: '' + # Advertise additional route + stubnet ${stubnet4} {}; + '') hostConf.ospf.stubNets4 + )} + }; + } + + ${lib.optionalString isUpstream '' + # OSPFv2 to advertise my default route + protocol ospf v2 ZW4_${hostNameEscaped} { + ipv4 { + export where net = 0.0.0.0/0; + }; + area 0 { + ${builtins.concatStringsSep "\n" ( + builtins.attrValues ( + builtins.mapAttrs (net: _: + # Enable OSPF only on interfaces with a secret. + lib.optionalString (config.site.net.${net}.ospf.secret != null) '' + interface "${net}" instance ${toString hostConf.ospf.upstreamInstance} { + # Become the designated router + priority 10; + hello 10; + wait 20; + + authentication cryptographic; + password "${config.site.net.${net}.ospf.secret}"; + }; + '' + ) hostConf.physicalInterfaces + ) + )} + }; + } + ''} + + ${( + builtins.foldl' ({ text, n }: upstream: { + text = '' + ${text} + + # OSPFv2 to receive a default route from ${upstream} + protocol ospf v2 ZW4_${ + builtins.replaceStrings [ "-" ] [ "_" ] upstream + } { + ipv4 { + import filter { + preference = preference + ${toString (100 - n)}; + accept; + }; + ${lib.optionalString ( + builtins.match "anon.*" hostName != null || + hostName == "flpk-gw" + ) '' + table vpn_table; + ''} + }; + area 0 { + ${builtins.concatStringsSep "\n" ( + builtins.attrValues ( + builtins.mapAttrs (net: _: + # Enable OSPF only on interfaces with a secret. + lib.optionalString (config.site.net.${net}.ospf.secret != null) '' + interface "${net}" instance ${ + builtins.replaceStrings [ "-" ] [ "_" ] ( + toString config.site.hosts.${upstream}.ospf.upstreamInstance + ) + } { + hello 10; + wait 20; + authentication cryptographic; + password "${config.site.net.${net}.ospf.secret}"; + }; + '' + ) hostConf.physicalInterfaces + ) + )} + }; + } + ''; + n = n + 1; + }) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams + ).text} + + # OSPFv3 for site-local IPv6 + protocol ospf v3 ZW6 { + ipv6 { + import all; + # OSPF is self-contained + export none; + }; + area 0 { + ${builtins.concatStringsSep "\n" ( + builtins.attrValues ( + builtins.mapAttrs (net: _: + # Enable OSPF only on networks with a secret. + if config.site.net.${net}.ospf.secret != null + then '' + interface "${net}" { + hello 10; + wait 20; + + authentication cryptographic; + password "${config.site.net.${net}.ospf.secret}"; + }; + '' + else '' + interface "${net}" { + stub yes; + cost 10; + }; + '' + ) hostConf.physicalInterfaces + ) + )} + ${builtins.concatStringsSep "\n" ( + map (stubnet6: '' + # Advertise additional route + stubnet ${stubnet6} {}; + '') + hostConf.ospf.stubNets6 + )} + }; + } + + ${lib.optionalString isUpstream '' + # OSPFv3 to advertise my default route + protocol ospf v3 ZW6_${hostNameEscaped} { + ipv6 { + export where net = ::/0; + }; + area 0 { + ${builtins.concatStringsSep "\n" ( + builtins.attrValues ( + builtins.mapAttrs (net: _: + # Enable OSPF only on interfaces with a secret. + lib.optionalString (config.site.net.${net}.ospf.secret != null) '' + interface "${net}" instance ${toString hostConf.ospf.upstreamInstance} { + # Become the designated router + priority 10; + hello 10; + wait 20; + + authentication cryptographic; + password "${config.site.net.${net}.ospf.secret}"; + }; + '' + ) hostConf.physicalInterfaces + ) + )} + }; + } + ''} + + ${lib.optionalString (builtins.match "anon.*" hostName == null) ( + builtins.foldl' ({ text, n }: upstream: { + text = '' + ${text} + + # OSPFv3 to receive a default route from ${upstream} + protocol ospf v3 ZW6_${ + builtins.replaceStrings [ "-" ] [ "_" ] upstream + } { + ipv6 { + import filter { + preference = preference + ${toString (100 - n)}; + accept; + }; + }; + area 0 { + ${builtins.concatStringsSep "\n" ( + builtins.attrValues ( + builtins.mapAttrs (net: _: + # Enable OSPF only on interfaces with a secret. + lib.optionalString (config.site.net.${net}.ospf.secret != null) '' + interface "${net}" instance ${ + builtins.replaceStrings [ "-" ] [ "_" ] ( + toString config.site.hosts.${upstream}.ospf.upstreamInstance + ) + } { + hello 10; + wait 20; + authentication cryptographic; + password "${config.site.net.${net}.ospf.secret}"; + }; + '' + ) hostConf.physicalInterfaces + ) + )} + }; + } + ''; + n = n + 1; + }) { text = ""; n = 0; } hostConf.ospf.allowedUpstreams6 + ).text} + # Zentralwerk DN42 protocol static { ipv4; @@ -156,170 +370,31 @@ in } ${lib.optionalString (hostConf.bgp != null) '' - # zentralwerk-network - template bgp bgp_rr_server { + template bgp bgppeer { local as ${toString hostConf.bgp.asn}; - direct; ipv4 { - import filter { - preference = preference + 200; - accept; - }; - export filter { - if net ~ [ ${config.site.net.core.subnet4} ] then { - reject; + import all; + export where source=RTS_STATIC; + }; + ipv6 { + import all; + export where source=RTS_STATIC; + }; + } + + ${builtins.concatStringsSep "\n" ( + map ({ n, x }: + let + peer = x; + peerConf = hostConf.bgp.peers.${peer}; + in '' + protocol bgp bgp_${toString n} from bgppeer { + neighbor ${peer} as ${toString peerConf.asn}; } - ${lib.optionalString (nets4 != []) '' - if net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}+") nets4} ] then { - accept; - } - ''} - reject; - }; - }; - ipv6 { - import filter { - preference = preference + 200; - accept; - }; - export filter { - if net ~ [ ${lib.concatStringsSep ", " (builtins.attrValues config.site.net.core.subnets6)} ] then { - reject; - } - ${lib.optionalString (nets6 != []) '' - if net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}+") nets6} ] then { - accept; - } - ''} - reject; - }; - }; - } - template bgp bgp_rr_client { - local as ${toString hostConf.bgp.asn}; - direct; - connect delay time 1; - connect retry time 3; - error wait time 1 5; - error forget time 5; - - ipv4 { - next hop self on; - import filter { - preference = preference + 200; - accept; - }; - ${lib.optionalString (nets4 != []) '' - export where net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}") nets4} ]; - ''} - }; - ipv6 { - next hop self on; - import filter { - preference = preference + 200; - accept; - }; - ${lib.optionalString (nets6 != []) '' - export where net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}") nets6} ]; - ''} - }; - } - # dn42 - template bgp bgp_external { - local as ${toString hostConf.bgp.asn}; - direct; - - ipv4 { - next hop self on; - import all; - export where source = RTS_STATIC; - }; - ipv6 { - next hop self on; - import all; - export where source = RTS_STATIC; - }; - } - # emitting default routes - template bgp bgp_upstream { - local as ${toString hostConf.bgp.asn}; - direct; - - ipv4 { - next hop self on; - import all; - export where net = 0.0.0.0/0; - }; - ipv6 { - next hop self on; - import all; - export where net = ::/0; - }; - } - - ${lib.concatMapStrings (peer: - let - peerConf = hostConf.bgp.peers.${peer}; - isRange = lib.hasInfix "/" peer; - in '' - protocol bgp bgp_${peerConf.name} from bgp_${peerConf.type} { - neighbor ${lib.optionalString isRange "range"} ${peer} as ${toString peerConf.asn}; - ${lib.optionalString isRange '' - dynamic name "bgp_${peerConf.name}"; - ''} - ${lib.optionalString (peerConf.type == "rr") '' - rr client; - ''} - } - '') (builtins.attrNames hostConf.bgp.peers)} - - ${lib.concatMapStrings ({ n, x }: let upstream = x; in '' - # upstream client instance #${toString n} - protocol bgp bgp_up_${builtins.replaceStrings ["-"] ["_"] upstream} { - local as ${toString hostConf.bgp.asn}; - neighbor ${config.site.net.core.hosts6.dn42.${upstream}} as ${toString hostConf.bgp.asn}; - direct; - connect delay time 1; - connect retry time 3; - error wait time 1 5; - error forget time 5; - - ipv4 { - ${if (upstream4Order ? ${upstream}) - then '' - import filter { - preference = preference + ${toString (100 - upstream4Order.${upstream})}; - accept; - }; - '' - else '' - import none; - ''} - ${lib.optionalString (nets4 != []) '' - export where net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}") nets4} ]; - ''} - ${lib.optionalString (hostConf.bgp.upstreamTable != null) '' - table ${hostConf.bgp.upstreamTable}; - ''} - }; - ipv6 { - ${if (upstream4Order ? ${upstream}) - then '' - import filter { - preference = preference + ${toString (100 - upstream4Order.${upstream})}; - accept; - }; - '' - else '' - import none; - ''} - ${lib.optionalString (nets6 != []) '' - export where net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}") nets6} ]; - ''} - }; - } - '') (enumerate 1 allowedUpstreams)} + '' + ) (enumerate 1 (builtins.attrNames hostConf.bgp.peers)) + )} ''} ''; }; @@ -353,7 +428,8 @@ in ]; }; instance = { - ipv4 = "bgp_up"; + ipv4 = "ZW4_${hostNameEscaped}"; + ipv6 = "ZW6_${hostNameEscaped}"; }; checkService = addressFamily: { description = "Check connectivity for ${addressFamily}"; @@ -392,6 +468,6 @@ in }; in lib.mkIf isUpstream { check-upstream-ipv4 = checkService "ipv4"; - #check-upstream-ipv6 = checkService "ipv6"; + check-upstream-ipv6 = checkService "ipv6"; }; }