cofractal-ams01: bgp-over-ipv4
This commit is contained in:
parent
756c1a3dd2
commit
9213875d8b
2 changed files with 65 additions and 19 deletions
|
@ -6,6 +6,7 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../lib/zfs.nix
|
../lib/zfs.nix
|
||||||
|
../lib/bgp.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Otherwise _this_ machine won't enumerate things properly.
|
# Otherwise _this_ machine won't enumerate things properly.
|
||||||
|
@ -136,5 +137,31 @@
|
||||||
(bindMountSvc "/var/lib/tailscale" "tailscaled.service")
|
(bindMountSvc "/var/lib/tailscale" "tailscaled.service")
|
||||||
];
|
];
|
||||||
|
|
||||||
|
services.lukegbgp = let
|
||||||
|
local.asn = 205479;
|
||||||
|
in {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
local = {
|
||||||
|
routerID = "199.19.152.160";
|
||||||
|
};
|
||||||
|
export.v4 = [ ];
|
||||||
|
peering.cofractal = {
|
||||||
|
local = local // {
|
||||||
|
v6 = "2a09:a446:1337:ffff::10";
|
||||||
|
};
|
||||||
|
remote = {
|
||||||
|
asn = 26073;
|
||||||
|
export_community = 6000;
|
||||||
|
routers = [{
|
||||||
|
v6 = "2a09:a446:1337:ffff::2";
|
||||||
|
} {
|
||||||
|
v6 = "2a09:a446:1337:ffff::3";
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
system.stateVersion = "23.05";
|
system.stateVersion = "23.05";
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
let
|
let
|
||||||
generateSnippet = base: args: lib.concatStringsSep "\n" (lib.mapAttrsToList ( ixName: ix: generateSnippetForIX (args // { ixName = ixName; ix = ix; }) ) base );
|
generateSnippet = base: args: lib.concatStringsSep "\n" (lib.mapAttrsToList ( ixName: ix: generateSnippetForIX (args // { ixName = ixName; ix = ix; }) ) base );
|
||||||
generateSnippetForIX = { ixName, ix, ... }@args: ''
|
generateSnippetForIX = { ixName, ix, ... }@args: ''
|
||||||
|
${lib.optionalString (doesIPv4 ix) ''
|
||||||
ipv4 table ${ixName}4;
|
ipv4 table ${ixName}4;
|
||||||
ipv6 table ${ixName}6;
|
|
||||||
filter bgp_in_${ixName}4
|
filter bgp_in_${ixName}4
|
||||||
prefix set allnet;
|
prefix set allnet;
|
||||||
int set allas;
|
int set allas;
|
||||||
|
@ -19,35 +19,38 @@ let
|
||||||
bgp_local_pref = ${toString ix.remote.bgp_local_pref};
|
bgp_local_pref = ${toString ix.remote.bgp_local_pref};
|
||||||
accept;
|
accept;
|
||||||
}
|
}
|
||||||
filter bgp_in_${ixName}6
|
|
||||||
prefix set allnet;
|
|
||||||
int set allas;
|
|
||||||
{
|
|
||||||
if ! (avoid_martians6()) then reject;
|
|
||||||
${if ix.remote.must_be_next_hop then "if (bgp_path.first != ${toString ix.remote.asn}) then reject;" else "# no next-hop requirement"}
|
|
||||||
${lib.concatMapStringsSep "\n" (asn: "if (bgp_path ~ [= * ${toString asn} * =]) then reject;") ix.remote.drop_asns}
|
|
||||||
if (bgp_path ~ [= * 16276 * =] && gw = 2001:7f8:4::3f94:2) then gw = 2001:7f8:4::3f94:1; # OVH must go via router 1; router 2 is bork.
|
|
||||||
bgp_local_pref = ${toString ix.remote.bgp_local_pref};
|
|
||||||
accept;
|
|
||||||
}
|
|
||||||
filter bgp_export_${ixName}4
|
filter bgp_export_${ixName}4
|
||||||
{
|
{
|
||||||
if ! ((ro, ${toString ix.local.asn}, 1000) ~ bgp_ext_community) then reject;
|
if ! ((ro, ${toString ix.local.asn}, 1000) ~ bgp_ext_community) then reject;
|
||||||
bgp_ext_community.delete([(ro, ${toString ix.local.asn}, *)]);
|
bgp_ext_community.delete([(ro, ${toString ix.local.asn}, *)]);
|
||||||
accept;
|
accept;
|
||||||
}
|
}
|
||||||
filter bgp_export_${ixName}6
|
|
||||||
{
|
|
||||||
if ! ((ro, ${toString ix.local.asn}, 1000) ~ bgp_ext_community) then reject;
|
|
||||||
bgp_ext_community.delete([(ro, ${toString ix.local.asn}, *)]);
|
|
||||||
accept;
|
|
||||||
}
|
|
||||||
protocol pipe ${ixName}pipe_4 {
|
protocol pipe ${ixName}pipe_4 {
|
||||||
table ${ixName}4;
|
table ${ixName}4;
|
||||||
peer table master4;
|
peer table master4;
|
||||||
import ${if ix.remote.is_route_collector then "all" else "where ((ro, ${toString ix.local.asn}, ${toString ix.remote.export_community}) ~ bgp_ext_community)"};
|
import ${if ix.remote.is_route_collector then "all" else "where ((ro, ${toString ix.local.asn}, ${toString ix.remote.export_community}) ~ bgp_ext_community)"};
|
||||||
export filter bgp_in_${ixName}4;
|
export filter bgp_in_${ixName}4;
|
||||||
};
|
};
|
||||||
|
''}
|
||||||
|
|
||||||
|
ipv6 table ${ixName}6;
|
||||||
|
filter bgp_in_${ixName}6
|
||||||
|
prefix set allnet;
|
||||||
|
int set allas;
|
||||||
|
{
|
||||||
|
if ! (avoid_martians6()) then reject;
|
||||||
|
${if ix.remote.must_be_next_hop then "if (bgp_path.first != ${toString ix.remote.asn}) then reject;" else "# no next-hop requirement"}
|
||||||
|
${lib.concatMapStringsSep "\n" (asn: "if (bgp_path ~ [= * ${toString asn} * =]) then reject;") ix.remote.drop_asns}
|
||||||
|
if (bgp_path ~ [= * 16276 * =] && gw = 2001:7f8:4::3f94:2) then gw = 2001:7f8:4::3f94:1; # OVH must go via router 1; router 2 is bork.
|
||||||
|
bgp_local_pref = ${toString ix.remote.bgp_local_pref};
|
||||||
|
accept;
|
||||||
|
}
|
||||||
|
filter bgp_export_${ixName}6
|
||||||
|
{
|
||||||
|
if ! ((ro, ${toString ix.local.asn}, 1000) ~ bgp_ext_community) then reject;
|
||||||
|
bgp_ext_community.delete([(ro, ${toString ix.local.asn}, *)]);
|
||||||
|
accept;
|
||||||
|
}
|
||||||
protocol pipe ${ixName}pipe_6 {
|
protocol pipe ${ixName}pipe_6 {
|
||||||
table ${ixName}6;
|
table ${ixName}6;
|
||||||
peer table master6;
|
peer table master6;
|
||||||
|
@ -55,12 +58,14 @@ let
|
||||||
export filter bgp_in_${ixName}6;
|
export filter bgp_in_${ixName}6;
|
||||||
};
|
};
|
||||||
'' + lib.concatImapStringsSep "\n" ( i: v: generateSnippetForRouter (args // { routerNum = i; router = v; }) ) ix.remote.routers;
|
'' + lib.concatImapStringsSep "\n" ( i: v: generateSnippetForRouter (args // { routerNum = i; router = v; }) ) ix.remote.routers;
|
||||||
|
doesIPv4 = ix: (ix.local.v4 != null) || ix.v4onv6;
|
||||||
enabledSnippet = { enabled ? true, ... }: "disabled ${if enabled then "off" else "on"};";
|
enabledSnippet = { enabled ? true, ... }: "disabled ${if enabled then "off" else "on"};";
|
||||||
passwordSnippet = { password ? null, ... }: if password == null then "# no password" else "password \"${password}\";";
|
passwordSnippet = { password ? null, ... }: if password == null then "# no password" else "password \"${password}\";";
|
||||||
multihopSnippet = { multihop ? null, ... }: if multihop == null then "# not multihop" else "multihop ${toString multihop};";
|
multihopSnippet = { multihop ? null, ... }: if multihop == null then "# not multihop" else "multihop ${toString multihop};";
|
||||||
passiveSnippet = { passive, ... }: "passive ${if passive then "on" else "off"};";
|
passiveSnippet = { passive, ... }: "passive ${if passive then "on" else "off"};";
|
||||||
prefixLimitSnippet = limit: if limit == null then "# no import limit" else "import limit ${toString limit} action restart;";
|
prefixLimitSnippet = limit: if limit == null then "# no import limit" else "import limit ${toString limit} action restart;";
|
||||||
generateSnippetForRouter = { ixName, ix, routerNum, router, ... }: ''
|
generateSnippetForRouter = { ixName, ix, routerNum, router, ... }: ''
|
||||||
|
${lib.optionalString (ix.local.v4 != null) ''
|
||||||
protocol bgp ${ixName}${toString routerNum}_4 {
|
protocol bgp ${ixName}${toString routerNum}_4 {
|
||||||
${enabledSnippet router}
|
${enabledSnippet router}
|
||||||
${passwordSnippet router}
|
${passwordSnippet router}
|
||||||
|
@ -77,6 +82,7 @@ let
|
||||||
${prefixLimitSnippet ix.remote.prefix_limit.v4}
|
${prefixLimitSnippet ix.remote.prefix_limit.v4}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
''}
|
||||||
protocol bgp ${ixName}${toString routerNum}_6 {
|
protocol bgp ${ixName}${toString routerNum}_6 {
|
||||||
${enabledSnippet router}
|
${enabledSnippet router}
|
||||||
${passwordSnippet router}
|
${passwordSnippet router}
|
||||||
|
@ -86,6 +92,14 @@ let
|
||||||
neighbor ${router.v6} as ${toString ix.remote.asn};
|
neighbor ${router.v6} as ${toString ix.remote.asn};
|
||||||
graceful restart on;
|
graceful restart on;
|
||||||
long lived graceful restart on;
|
long lived graceful restart on;
|
||||||
|
${lib.optionalString (ix.v4onv6) ''
|
||||||
|
ipv4 {
|
||||||
|
table ${ixName}4;
|
||||||
|
import all;
|
||||||
|
export ${if ix.remote.is_route_collector then "all" else "filter bgp_export_${ixName}4"};
|
||||||
|
${prefixLimitSnippet ix.remote.prefix_limit.v4}
|
||||||
|
};
|
||||||
|
''}
|
||||||
ipv6 {
|
ipv6 {
|
||||||
table ${ixName}6;
|
table ${ixName}6;
|
||||||
import all;
|
import all;
|
||||||
|
@ -124,7 +138,8 @@ in {
|
||||||
type = int;
|
type = int;
|
||||||
};
|
};
|
||||||
v4 = mkOption { # lukegbgp.config.peering.<foo>.local.v4
|
v4 = mkOption { # lukegbgp.config.peering.<foo>.local.v4
|
||||||
type = str;
|
type = nullOr str;
|
||||||
|
default = null;
|
||||||
};
|
};
|
||||||
v6 = mkOption { # lukegbgp.config.peering.<foo>.local.v6
|
v6 = mkOption { # lukegbgp.config.peering.<foo>.local.v6
|
||||||
type = str;
|
type = str;
|
||||||
|
@ -132,6 +147,10 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
v4onv6 = mkOption {
|
||||||
|
type = bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
remote = mkOption { # lukegbgp.config.peering.<foo>.remote
|
remote = mkOption { # lukegbgp.config.peering.<foo>.remote
|
||||||
type = submodule {
|
type = submodule {
|
||||||
options = {
|
options = {
|
||||||
|
|
Loading…
Reference in a new issue