nixos-module/container/bird: revert bgp experiments for now
parent
f2bb5a2735
commit
ae6de7754c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -192,7 +192,10 @@
|
|||
type = "veth";
|
||||
};
|
||||
};
|
||||
bgp.allowedUpstreams = [ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
ospf = {
|
||||
allowedUpstreams =
|
||||
[ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
role = "container";
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
type = "veth";
|
||||
};
|
||||
};
|
||||
bgp = {
|
||||
ospf = {
|
||||
allowedUpstreams = [ "anon1" "freifunk" ];
|
||||
allowedUpstreams6 = [ "flpk-gw" "anon1" "freifunk" ];
|
||||
};
|
||||
|
|
|
@ -206,7 +206,7 @@
|
|||
gw6 = null;
|
||||
};
|
||||
};
|
||||
bgp.allowedUpstreams =
|
||||
ospf.allowedUpstreams =
|
||||
[ "upstream4" "upstream3" "anon1" "freifunk" ];
|
||||
};
|
||||
stats = makeContainer {
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
type = "wireguard";
|
||||
};
|
||||
};
|
||||
bgp.allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ];
|
||||
ospf = {
|
||||
allowedUpstreams = [ "flpk-gw" "anon1" "freifunk" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
# Dummy secrets for testing
|
||||
{
|
||||
site.net = {
|
||||
core.ospf.secret = "encrypted";
|
||||
};
|
||||
|
||||
site.hosts = {
|
||||
ap1.password = "encrypted";
|
||||
ap2.password = "encrypted";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue