2020-06-07 14:03:12 +00:00
|
|
|
# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2020-05-08 22:26:21 +00:00
|
|
|
{ lib, config, ... }:
|
|
|
|
let
|
|
|
|
generateSnippet = base: args: lib.concatStringsSep "\n" (lib.mapAttrsToList ( ixName: ix: generateSnippetForIX (args // { ixName = ixName; ix = ix; }) ) base );
|
|
|
|
generateSnippetForIX = { ixName, ix, ... }@args: ''
|
|
|
|
ipv4 table ${ixName}4;
|
|
|
|
ipv6 table ${ixName}6;
|
|
|
|
protocol pipe ${ixName}pipe_4 {
|
|
|
|
table ${ixName}4;
|
|
|
|
peer table master4;
|
|
|
|
import where ((ro, ${toString ix.local.asn}, ${toString ix.remote.export_community}) ~ bgp_ext_community);
|
|
|
|
export all;
|
|
|
|
};
|
|
|
|
protocol pipe ${ixName}pipe_6 {
|
|
|
|
table ${ixName}6;
|
|
|
|
peer table master6;
|
|
|
|
import where ((ro, ${toString ix.local.asn}, ${toString ix.remote.export_community}) ~ bgp_ext_community);
|
|
|
|
export all;
|
|
|
|
};
|
|
|
|
'' + lib.concatImapStringsSep "\n" ( i: v: generateSnippetForRouter (args // { routerNum = i; router = v; }) ) ix.remote.routers;
|
|
|
|
enabledSnippet = { enabled ? true, ... }: "disabled ${if enabled then "off" else "on"}";
|
|
|
|
generateSnippetForRouter = { ixName, ix, routerNum, router, ... }: ''
|
|
|
|
protocol bgp ${ixName}${toString routerNum}_4 {
|
|
|
|
${enabledSnippet router};
|
|
|
|
local ${ix.local.v4} as ${toString ix.local.asn};
|
|
|
|
neighbor ${router.v4} as ${toString ix.remote.asn};
|
|
|
|
ipv4 {
|
|
|
|
table ${ixName}4;
|
|
|
|
import all;
|
|
|
|
export where ((ro, ${toString ix.local.asn}, 1000) ~ bgp_ext_community);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
protocol bgp ${ixName}${toString routerNum}_6 {
|
|
|
|
${enabledSnippet router};
|
|
|
|
local ${ix.local.v6} as ${toString ix.local.asn};
|
|
|
|
neighbor ${router.v6} as ${toString ix.remote.asn};
|
|
|
|
ipv6 {
|
|
|
|
table ${ixName}6;
|
|
|
|
import all;
|
|
|
|
export where ((ro, ${toString ix.local.asn}, 1000) ~ bgp_ext_community);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
'';
|
|
|
|
|
|
|
|
inherit (lib) mkOption mkAfter types;
|
|
|
|
in {
|
|
|
|
options.services.lukegbgp = {
|
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
};
|
|
|
|
config = mkOption { # lukegbgp.config
|
|
|
|
type = with types; submodule {
|
|
|
|
options = {
|
|
|
|
local = mkOption { # lukegbgp.config.local
|
|
|
|
type = submodule {
|
|
|
|
options = {
|
|
|
|
routerID = mkOption { # lukegbgp.config.local.routerID
|
|
|
|
type = str;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
peering = mkOption { # lukegbgp.config.peering
|
|
|
|
type = attrsOf (submodule {
|
|
|
|
options = {
|
|
|
|
local = mkOption { # lukegbgp.config.peering.<foo>.local
|
|
|
|
type = submodule {
|
|
|
|
options = {
|
|
|
|
asn = mkOption { # lukegbgp.config.peering.<foo>.local.asn
|
|
|
|
type = int;
|
|
|
|
};
|
|
|
|
v4 = mkOption { # lukegbgp.config.peering.<foo>.local.v4
|
|
|
|
type = str;
|
|
|
|
};
|
|
|
|
v6 = mkOption { # lukegbgp.config.peering.<foo>.local.v6
|
|
|
|
type = str;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
remote = mkOption { # lukegbgp.config.peering.<foo>.remote
|
|
|
|
type = submodule {
|
|
|
|
options = {
|
|
|
|
asn = mkOption { # lukegbgp.config.peering.<foo>.remote.asn
|
|
|
|
type = int;
|
|
|
|
};
|
|
|
|
export_community = mkOption { # lukegbgp.config.peering.<foo>.remote.export_community
|
|
|
|
type = int;
|
|
|
|
};
|
|
|
|
routers = mkOption { # lukegbgp.config.peering.<foo>.remote.routers
|
|
|
|
type = listOf (submodule {
|
|
|
|
options = {
|
|
|
|
enabled = mkOption { # lukegbgp.config.peering.<foo>.remote.routers.<n>.enabled
|
|
|
|
type = bool;
|
|
|
|
default = true;
|
|
|
|
};
|
|
|
|
v4 = mkOption { # lukegbgp.config.peering.<foo>.remote.routers.<n>.v4
|
|
|
|
type = str;
|
|
|
|
};
|
|
|
|
v6 = mkOption { # lukegbgp.config.peering.<foo>.remote.routers.<n>.v6
|
|
|
|
type = str;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
2020-11-04 16:41:15 +00:00
|
|
|
export = mkOption { # lukegbgp.config.export
|
2020-11-04 17:41:28 +00:00
|
|
|
default = { v4 = ["92.118.31.0/24"]; v6 = ["2a09:a440::/48"]; };
|
2020-11-04 16:41:15 +00:00
|
|
|
type = submodule {
|
|
|
|
options = {
|
|
|
|
v4 = mkOption { # lukegbgp.config.export.v4
|
|
|
|
type = listOf str;
|
|
|
|
default = ["92.118.31.0/24"];
|
|
|
|
};
|
|
|
|
v6 = mkOption { # lukegbgp.config.export.v6
|
|
|
|
type = listOf str;
|
|
|
|
default = ["2a09:a440::/48"];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2020-05-08 22:26:21 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = {
|
|
|
|
services.bird2 = lib.mkIf config.services.lukegbgp.enable {
|
|
|
|
enable = true;
|
|
|
|
config = ''
|
|
|
|
router id ${config.services.lukegbgp.config.local.routerID};
|
|
|
|
|
|
|
|
${generateSnippet config.services.lukegbgp.config.peering {}}
|
|
|
|
|
|
|
|
protocol kernel {
|
|
|
|
persist;
|
|
|
|
ipv4 {
|
|
|
|
import none;
|
|
|
|
export all;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
protocol kernel {
|
|
|
|
persist;
|
|
|
|
ipv6 {
|
|
|
|
import none;
|
|
|
|
export all;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
protocol device {
|
|
|
|
};
|
|
|
|
|
|
|
|
protocol static export4 {
|
|
|
|
ipv4 {
|
|
|
|
import filter {
|
|
|
|
bgp_ext_community.add((ro, 205479, 1000));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2000));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2001));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2002));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2003));
|
2020-11-04 16:41:15 +00:00
|
|
|
bgp_ext_community.add((ro, 205479, 3000));
|
2021-03-29 11:47:44 +00:00
|
|
|
bgp_ext_community.add((ro, 205479, 4000));
|
|
|
|
bgp_ext_community.add((ro, 205479, 4001));
|
|
|
|
bgp_ext_community.add((ro, 205479, 4002));
|
2020-05-08 22:26:21 +00:00
|
|
|
accept;
|
|
|
|
};
|
|
|
|
};
|
2020-11-04 16:41:15 +00:00
|
|
|
${lib.concatMapStrings (ip: "route ${ip} blackhole;") config.services.lukegbgp.config.export.v4}
|
2020-05-08 22:26:21 +00:00
|
|
|
};
|
|
|
|
protocol static export6 {
|
|
|
|
ipv6 {
|
|
|
|
import filter {
|
|
|
|
bgp_ext_community.add((ro, 205479, 1000));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2000));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2001));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2002));
|
|
|
|
bgp_ext_community.add((ro, 205479, 2003));
|
2020-11-04 16:41:15 +00:00
|
|
|
bgp_ext_community.add((ro, 205479, 3000));
|
2021-03-29 11:47:44 +00:00
|
|
|
bgp_ext_community.add((ro, 205479, 4000));
|
|
|
|
bgp_ext_community.add((ro, 205479, 4001));
|
|
|
|
bgp_ext_community.add((ro, 205479, 4002));
|
2020-05-08 22:26:21 +00:00
|
|
|
accept;
|
|
|
|
};
|
|
|
|
};
|
2020-11-04 16:41:15 +00:00
|
|
|
${lib.concatMapStrings (ip: "route ${ip} blackhole;") config.services.lukegbgp.config.export.v6}
|
2020-05-08 22:26:21 +00:00
|
|
|
};
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
networking.firewall.allowedTCPPorts = lib.mkIf config.services.lukegbgp.enable (lib.mkAfter [ 179 ]);
|
|
|
|
|
|
|
|
boot.kernel.sysctl = {
|
|
|
|
"net.ipv6.conf.default.accept_ra" = 0;
|
|
|
|
"net.ipv6.conf.all.accept_ra" = 0;
|
|
|
|
"net.ipv6.conf.default.autoconf" = 0;
|
|
|
|
"net.ipv6.conf.all.autoconf" = 0;
|
|
|
|
};
|
|
|
|
};
|
2020-11-04 16:41:15 +00:00
|
|
|
}
|