replace ospf with bgp

This commit is contained in:
Astro 2023-01-20 20:04:52 +01:00
parent dfd033af25
commit e618d0caff
15 changed files with 313 additions and 354 deletions

View File

@ -19,4 +19,6 @@ in
++ lib.filesystem.listFilesRecursive ./net; ++ lib.filesystem.listFilesRecursive ./net;
site.net-combined = concatMapAttrsRecursive (name: value: { inherit (value) hosts4 hosts6; }) config.site.net; site.net-combined = concatMapAttrsRecursive (name: value: { inherit (value) hosts4 hosts6; }) config.site.net;
site.bgp.asn = 4242421127;
} }

View File

@ -1,4 +1,5 @@
{ lib, ... }: { config, lib, ... }:
{ {
site.net.c3d2 = { site.net.c3d2 = {
dhcp = { dhcp = {
@ -110,28 +111,34 @@
c3d2.hwaddr = "0A:14:48:01:07:05"; c3d2.hwaddr = "0A:14:48:01:07:05";
core.hwaddr = "0A:14:48:01:07:04"; core.hwaddr = "0A:14:48:01:07:04";
}; };
ospf.allowedUpstreams = [ "anon1" "freifunk" ]; bgp.allowedUpstreams = [ "anon1" "freifunk" ];
}; };
c3d2-gw1 = makeGateway { c3d2-gw1 = makeGateway {
interfaces = { interfaces = {
c3d2.hwaddr = "0A:14:48:01:21:01"; c3d2.hwaddr = "0A:14:48:01:21:01";
core.hwaddr = "0A:14:48:01:21:00"; core.hwaddr = "0A:14:48:01:21:00";
}; };
ospf.allowedUpstreams = [ "flpk-gw" "freifunk" "upstream4" "upstream3" "anon1" ]; bgp.allowedUpstreams = [ "flpk-gw" "freifunk" "upstream4" "upstream3" "anon1" ];
}; };
c3d2-gw2 = makeGateway { c3d2-gw2 = makeGateway {
interfaces = { interfaces = {
c3d2.hwaddr = "0A:14:48:01:21:03"; c3d2.hwaddr = "0A:14:48:01:21:03";
core.hwaddr = "0A:14:48:01:21:02"; core.hwaddr = "0A:14:48:01:21:02";
}; };
ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; bgp.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ];
}; };
c3d2-gw3 = makeGateway { c3d2-gw3 = makeGateway {
interfaces = { interfaces = {
c3d2.hwaddr = "0A:14:48:01:21:05"; c3d2.hwaddr = "0A:14:48:01:21:05";
core.hwaddr = "0A:14:48:01:21:04"; core.hwaddr = "0A:14:48:01:21:04";
}; };
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; bgp = {
peers.${config.site.net.core.hosts6.dn42.bgp} = {
type = "rr_client";
name = "rr";
};
allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
};
}; };
}; };
} }

View File

@ -1,4 +1,4 @@
{ lib, ... }: { config, lib, ... }:
let let
cephMonServers = [ "server5" "server6" "server8" ]; cephMonServers = [ "server5" "server6" "server8" ];
in in
@ -158,7 +158,13 @@ in
type = "veth"; type = "veth";
}; };
}; };
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; bgp = {
peers.${config.site.net.core.hosts6.dn42.bgp} = {
type = "rr_client";
name = "rr";
};
allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
};
}; };
server3 = makeServer; server3 = makeServer;
server5 = makeServer; server5 = makeServer;

View File

@ -1,3 +1,5 @@
{ config, lib, ... }:
{ {
site.net.core = { site.net.core = {
domainName = "core.zentralwerk.org"; domainName = "core.zentralwerk.org";
@ -132,6 +134,7 @@
upstream4 = "fd23:42:c3d2:581::b:3"; upstream4 = "fd23:42:c3d2:581::b:3";
yggdrasil = "fd23:42:c3d2:581:9000::1"; yggdrasil = "fd23:42:c3d2:581:9000::1";
vpn-gw = "fd23:42:c3d2:581:9001::1"; vpn-gw = "fd23:42:c3d2:581:9001::1";
flpk-gw = "fd23:42:c3d2:581:9002::1";
}; };
up4 = { up4 = {
anon1 = "2a00:8180:2c00:281::9:1"; anon1 = "2a00:8180:2c00:281::9:1";
@ -201,15 +204,33 @@
}; };
}; };
site.hosts = { site.hosts = lib.mkMerge ([ {
bgp = { bgp = {
bgp = { bgp = {
asn = 4242421127;
peers = { peers = {
"172.22.99.253" = { asn = 64699; }; "172.22.99.253" = {
"fe80::a800:42ff:fe7a:3246%c3d2" = { asn = 64699; }; 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";
};
}; };
# 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 = { interfaces = {
c3d2 = { c3d2 = {
hwaddr = "0A:14:48:01:22:01"; hwaddr = "0A:14:48:01:22:01";
@ -220,14 +241,21 @@
type = "veth"; type = "veth";
}; };
}; };
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" ];
};
role = "container";
}; };
}; } ] ++ 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";
};
};
# TODO: upstreams
} ]
# except "bgp" itself :)
else []
) (builtins.attrNames config.site.net.core.hosts6.dn42));
} }

View File

@ -1,3 +1,5 @@
{ config, ... }:
{ {
site.net.flpk = { site.net.flpk = {
domainName = "flpk.zentralwerk.org"; domainName = "flpk.zentralwerk.org";
@ -48,9 +50,13 @@
}; };
}; };
}; };
ospf = { bgp = {
allowedUpstreams = [ "upstream4" "upstream3" "freifunk" ]; allowedUpstreams = [ "upstream4" "upstream3" "freifunk" ];
upstreamInstance = 2; upstreamTable = "vpn_table";
peers.${config.site.net.core.subnets6.dn42} = {
type = "upstream";
name = "up";
};
}; };
role = "container"; role = "container";
}; };

View File

@ -192,10 +192,7 @@
type = "veth"; type = "veth";
}; };
}; };
ospf = { bgp.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
allowedUpstreams =
[ "upstream4" "upstream3" "anon1" "freifunk" ];
};
role = "container"; role = "container";
}; };
} }

View File

@ -38,7 +38,7 @@ lib.mkMerge (
core.type = "veth"; core.type = "veth";
"priv${toString n}".type = "veth"; "priv${toString n}".type = "veth";
}; };
ospf.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ]; bgp.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
}; };
} }
) (seq 1 privCount) ) (seq 1 privCount)
@ -540,7 +540,7 @@ lib.mkMerge (
hwaddr = "0A:14:47:02:2A:19"; hwaddr = "0A:14:47:02:2A:19";
}; };
}; };
ospf.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ]; bgp.allowedUpstreams = [ "upstream3" "upstream4" "anon1" "freifunk" ];
}; };
priv18-gw = { priv18-gw = {
interfaces = { interfaces = {

View File

@ -39,7 +39,7 @@
type = "veth"; type = "veth";
}; };
}; };
ospf = { bgp = {
allowedUpstreams = [ "anon1" "freifunk" ]; allowedUpstreams = [ "anon1" "freifunk" ];
allowedUpstreams6 = [ "flpk-gw" "anon1" "freifunk" ]; allowedUpstreams6 = [ "flpk-gw" "anon1" "freifunk" ];
}; };

View File

@ -206,7 +206,7 @@
gw6 = null; gw6 = null;
}; };
}; };
ospf.allowedUpstreams = bgp.allowedUpstreams =
[ "upstream4" "upstream3" "anon1" "freifunk" ]; [ "upstream4" "upstream3" "anon1" "freifunk" ];
}; };
stats = makeContainer { stats = makeContainer {

View File

@ -24,8 +24,12 @@ in
}; };
}; };
}; };
ospf.upstreamInstance = 7;
role = "container"; role = "container";
bgp.peers.${config.site.net.core.subnets6.dn42} = {
asn = config.site.hosts.upstream3.bgp.asn;
type = "upstream";
name = "up";
};
}; };
upstream4 = rec { upstream4 = rec {
@ -327,17 +331,19 @@ in
}; };
}; };
}; };
ospf = { bgp = {
upstreamInstance = 8; nets4 = [
stubNets4 = [
"${interfaces.up4-pppoe.upstream.staticIpv4Address}/32" "${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"; role = "container";
}; };
freifunk.ospf.upstreamInstance = 6;
anon1 = { anon1 = {
interfaces = { interfaces = {
core = { core = {
@ -352,9 +358,14 @@ in
}; };
}; };
}; };
ospf = { bgp = {
allowedUpstreams = [ "upstream3" "upstream4" "freifunk" ]; allowedUpstreams = [ "upstream3" "upstream4" "freifunk" ];
upstreamInstance = 5; upstreamTable = "vpn_table";
peers.${config.site.net.core.subnets6.dn42} = {
asn = config.site.hosts.upstream3.bgp.asn;
type = "upstream";
name = "up";
};
}; };
role = "container"; role = "container";
}; };

View File

@ -33,8 +33,6 @@
type = "wireguard"; type = "wireguard";
}; };
}; };
ospf = { bgp.allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ];
allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ];
};
}; };
} }

View File

@ -7,10 +7,10 @@
type = "veth"; type = "veth";
}; };
}; };
ospf = { bgp = {
allowedUpstreams = allowedUpstreams =
[ "upstream4" "upstream3" "anon1" "freifunk" ]; [ "upstream4" "upstream3" "anon1" "freifunk" ];
stubNets6 = [ "200::/7" ]; nets6 = [ "200::/7" ];
}; };
services.yggdrasil.enable = true; services.yggdrasil.enable = true;

View File

@ -1,9 +1,5 @@
# Dummy secrets for testing # Dummy secrets for testing
{ {
site.net = {
core.ospf.secret = "encrypted";
};
site.hosts = { site.hosts = {
ap1.password = "encrypted"; ap1.password = "encrypted";
ap2.password = "encrypted"; ap2.password = "encrypted";

View File

@ -148,12 +148,6 @@ let
type = with types; attrsOf (attrsOf str); type = with types; attrsOf (attrsOf str);
default = {}; default = {};
}; };
ospf = {
secret = mkOption {
type = with types; nullOr str;
default = null;
};
};
dhcp = mkOption { dhcp = mkOption {
type = with types; nullOr (submodule { options = dhcpOpts; }); type = with types; nullOr (submodule { options = dhcpOpts; });
default = null; default = null;
@ -390,35 +384,10 @@ let
}; }); }; });
default = []; 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 { bgp = mkOption {
default = null; default = null;
type = with types; nullOr (submodule { type = with types; nullOr (submodule {
options = bgpOpts; options = bgpOpts name;
}); });
}; };
services.dns = { services.dns = {
@ -499,20 +468,52 @@ let
}; };
}; };
bgpOpts = { bgpOpts = hostName: {
asn = mkOption { asn = mkOption {
type = types.int; type = types.int;
default = config.site.bgp.asn;
}; };
peers = mkOption { peers = mkOption {
type = with types; attrsOf (submodule ({ ... }: { type = with types; attrsOf (submodule (submoduleArg: {
options = { options = {
asn = mkOption { asn = mkOption {
type = types.int; 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 = {}; 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, ... }: { linkOpts = hostName: { name, ... }: {
@ -623,6 +624,12 @@ in
default = "secret"; default = "secret";
}; };
}; };
bgp = {
asn = mkOption {
type = types.int;
};
};
}; };
config.warnings = config.warnings =
@ -643,16 +650,16 @@ in
reportCollisions = name: getter: xs: reportCollisions = name: getter: xs:
map (k: "Duplicate ${name}: ${k}") (findCollisions getter xs); map (k: "Duplicate ${name}: ${k}") (findCollisions getter xs);
ospfUpstreamXorGw = bgpUpstreamXorGw =
builtins.concatMap (hostName: builtins.concatMap (hostName:
let let
hostConf = config.site.hosts.${hostName}; hostConf = config.site.hosts.${hostName};
gwNets = builtins.filter (netName: gwNets = builtins.filter (netName:
hostConf.interfaces.${netName}.gw4 != null hostConf.interfaces.${netName}.gw4 != null
) (builtins.attrNames hostConf.interfaces); ) (builtins.attrNames hostConf.interfaces);
in if gwNets != [] && hostConf.ospf.allowedUpstreams != [] in if gwNets != [] && hostConf.bgp.allowedUpstreams or [] != []
then [ '' then [ ''
Host ${hostName} has gateway on ${builtins.head gwNets} but accepts default routes from OSPF Host ${hostName} has gateway on ${builtins.head gwNets} but accepts default routes from BGP
'' ] '' ]
else [] else []
) (builtins.attrNames config.site.hosts); ) (builtins.attrNames config.site.hosts);
@ -660,7 +667,7 @@ in
(reportCollisions "VLAN tag" (x: lib.optional (x.vlan != null) x.vlan) config.site.net) ++ (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 "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) ++ (reportCollisions "IPv6 subnet" (x: builtins.attrValues x.subnets6) config.site.net) ++
ospfUpstreamXorGw; bgpUpstreamXorGw;
config.assertions = config.assertions =
# Duplicate host/net name check # Duplicate host/net name check

View File

@ -25,6 +25,42 @@ let
n = n; n = n;
x = builtins.head list; x = builtins.head list;
} ] ++ (enumerate (n + 1) (builtins.tail 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 in
{ {
services.bird2 = { services.bird2 = {
@ -35,31 +71,13 @@ in
protocol kernel K4 { protocol kernel K4 {
learn; learn;
ipv4 { ipv4 {
${if isUpstream export all;
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 { protocol kernel K6 {
learn; learn;
ipv6 { ipv6 {
${if isUpstream export all;
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 { protocol device {
@ -84,10 +102,7 @@ in
check link yes; check link yes;
} }
${lib.optionalString ( ${lib.optionalString (hostConf.bgp.upstreamTable != null) ''
builtins.match "anon.*" hostName != null ||
hostName == "flpk-gw"
) ''
# BIRD routing table for Wireguard transport # BIRD routing table for Wireguard transport
ipv4 table vpn_table; ipv4 table vpn_table;
@ -128,235 +143,6 @@ 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 # Zentralwerk DN42
protocol static { protocol static {
ipv4; ipv4;
@ -370,31 +156,146 @@ in
} }
${lib.optionalString (hostConf.bgp != null) '' ${lib.optionalString (hostConf.bgp != null) ''
template bgp bgppeer { # zentralwerk-network
template bgp bgp_rr_server {
local as ${toString hostConf.bgp.asn}; local as ${toString hostConf.bgp.asn};
direct;
ipv4 { ipv4 {
import all; import filter {
export where source=RTS_STATIC; preference = preference + 200;
accept;
};
${lib.optionalString (nets4 != []) ''
export where net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}") nets4} ];
''}
}; };
ipv6 { ipv6 {
import filter {
preference = preference + 200;
accept;
};
${lib.optionalString (nets6 != []) ''
export where net ~ [ ${lib.concatMapStringsSep ", " (n: "${n}") nets6} ];
''}
};
}
template bgp bgp_rr_client {
local as ${toString hostConf.bgp.asn};
direct;
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; import all;
export where source=RTS_STATIC; 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;
}; };
} }
${builtins.concatStringsSep "\n" ( ${lib.concatMapStrings (peer:
map ({ n, x }: let
let peerConf = hostConf.bgp.peers.${peer};
peer = x; isRange = lib.hasInfix "/" peer;
peerConf = hostConf.bgp.peers.${peer}; in ''
in '' protocol bgp bgp_${peerConf.name} from bgp_${peerConf.type} {
protocol bgp bgp_${toString n} from bgppeer { neighbor ${lib.optionalString isRange "range"} ${peer} as ${toString peerConf.asn};
neighbor ${peer} as ${toString peerConf.asn}; ${lib.optionalString isRange ''
} dynamic name "bgp_${peerConf.name}";
'' ''}
) (enumerate 1 (builtins.attrNames hostConf.bgp.peers)) ${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_${upstream} {
local as ${toString hostConf.bgp.asn};
neighbor ${config.site.net.core.hosts6.dn42.${upstream}} as ${toString hostConf.bgp.asn};
direct;
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)}
''} ''}
''; '';
}; };