added dn42 bgp communities
This commit is contained in:
parent
16e12e76e1
commit
36654301a2
|
@ -6,6 +6,7 @@ let
|
|||
networking.dn42.enable = true;
|
||||
virtualisation.interfaces.enp1s0.vlan = 1;
|
||||
networking.useNetworkd = true;
|
||||
networking.domain = "test.nixos";
|
||||
systemd.network.netdevs.dummy0.netdevConfig = {
|
||||
Kind = "dummy";
|
||||
Name = "dummy0";
|
||||
|
@ -20,14 +21,21 @@ pkgs.nixosTest rec {
|
|||
nodes = {
|
||||
foo = {
|
||||
imports = [ common ];
|
||||
networking.hostName = "foo";
|
||||
networking.dn42 = {
|
||||
as = 64600;
|
||||
bandwidth = 25;
|
||||
geo = 41;
|
||||
country = 1276;
|
||||
addr.v4 = "172.20.0.1";
|
||||
nets.v4 = [ "172.20.0.0/24" ];
|
||||
addr.v6 = "fec0::1";
|
||||
nets.v6 = [ "fec0::/64" ];
|
||||
peers.bar = {
|
||||
as = 64601;
|
||||
latency = 1;
|
||||
bandwidth = 25;
|
||||
crypto = 31;
|
||||
extendedNextHop = true;
|
||||
addr.v6 = (builtins.head nodes.bar.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
srcAddr.v6 = (builtins.head nodes.foo.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
|
@ -57,14 +65,21 @@ pkgs.nixosTest rec {
|
|||
};
|
||||
bar = {
|
||||
imports = [ common ];
|
||||
networking.hostName = "bar";
|
||||
networking.dn42 = {
|
||||
as = 64601;
|
||||
bandwidth = 25;
|
||||
geo = 41;
|
||||
country = 1276;
|
||||
addr.v4 = "172.20.1.1";
|
||||
nets.v4 = [ "172.20.1.0/24" ];
|
||||
addr.v6 = "fec0:0:0:1::1";
|
||||
nets.v6 = [ "fec0:0:0:1::/64" ];
|
||||
peers.foo = {
|
||||
as = 64600;
|
||||
latency = 1;
|
||||
bandwidth = 25;
|
||||
crypto = 31;
|
||||
extendedNextHop = true;
|
||||
addr.v6 = (builtins.head nodes.foo.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
srcAddr.v6 = (builtins.head nodes.bar.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
|
|
|
@ -6,6 +6,7 @@ let
|
|||
networking.dn42.enable = true;
|
||||
virtualisation.interfaces.enp1s0.vlan = 1;
|
||||
networking.useNetworkd = true;
|
||||
networking.domain = "text.nixos";
|
||||
systemd.network.netdevs.dummy0.netdevConfig = {
|
||||
Kind = "dummy";
|
||||
Name = "dummy0";
|
||||
|
@ -20,14 +21,21 @@ pkgs.nixosTest rec {
|
|||
nodes = {
|
||||
foo = {
|
||||
imports = [ common ];
|
||||
networking.hostName = "foo";
|
||||
networking.dn42 = {
|
||||
as = 64600;
|
||||
bandwidth = 25;
|
||||
geo = 41;
|
||||
country = 1276;
|
||||
addr.v4 = "172.20.0.1";
|
||||
nets.v4 = [ "172.20.0.0/24" ];
|
||||
addr.v6 = "fec1::1";
|
||||
nets.v6 = [ "fec1::/64" ];
|
||||
peers.bar = {
|
||||
as = 64601;
|
||||
latency = 1;
|
||||
bandwidth = 25;
|
||||
crypto = 31;
|
||||
addr.v4 = (builtins.head nodes.bar.networking.interfaces.enp1s0.ipv4.addresses).address;
|
||||
addr.v6 = (builtins.head nodes.bar.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
srcAddr.v4 = (builtins.head nodes.foo.networking.interfaces.enp1s0.ipv4.addresses).address;
|
||||
|
@ -58,14 +66,21 @@ pkgs.nixosTest rec {
|
|||
};
|
||||
bar = {
|
||||
imports = [ common ];
|
||||
networking.hostName = "bar";
|
||||
networking.dn42 = {
|
||||
as = 64601;
|
||||
bandwidth = 25;
|
||||
geo = 41;
|
||||
country = 1276;
|
||||
addr.v4 = "172.20.1.1";
|
||||
nets.v4 = [ "172.20.1.0/24" ];
|
||||
addr.v6 = "fec1:0:0:1::1";
|
||||
nets.v6 = [ "fec1:0:0:1::/64" ];
|
||||
peers.foo = {
|
||||
as = 64600;
|
||||
latency = 1;
|
||||
bandwidth = 25;
|
||||
crypto = 31;
|
||||
addr.v4 = (builtins.head nodes.foo.networking.interfaces.enp1s0.ipv4.addresses).address;
|
||||
addr.v6 = (builtins.head nodes.foo.networking.interfaces.enp1s0.ipv6.addresses).address;
|
||||
srcAddr.v4 = (builtins.head nodes.bar.networking.interfaces.enp1s0.ipv4.addresses).address;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.networking.dn42;
|
||||
in
|
||||
|
@ -18,15 +19,14 @@ in
|
|||
services.bird2 = {
|
||||
enable = true;
|
||||
config = ''
|
||||
router id ${cfg.routerId};
|
||||
define OWNAS = ${toString cfg.as};
|
||||
define OWNIP = ${toString cfg.addr.v6};
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
define BANDWIDTH = ${toString cfg.bandwidth};
|
||||
define REGION_GEO = ${toString cfg.geo};
|
||||
define REGION_COUNTRY = ${toString cfg.country};
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
define ASN_BLACKLIST = [];
|
||||
|
||||
function is_self_net_v4() -> bool {
|
||||
return net ~ [${builtins.concatStringsSep ", " cfg.nets.v4}];
|
||||
|
@ -36,39 +36,18 @@ in
|
|||
return net ~ [${builtins.concatStringsSep ", " cfg.nets.v6}];
|
||||
}
|
||||
|
||||
function is_valid_network_v4() -> bool {
|
||||
return net ~ [
|
||||
172.20.0.0/14{21,29}, # dn42
|
||||
172.20.0.0/24{28,32}, # dn42 Anycast
|
||||
172.21.0.0/24{28,32}, # dn42 Anycast
|
||||
172.22.0.0/24{28,32}, # dn42 Anycast
|
||||
172.23.0.0/24{28,32}, # dn42 Anycast
|
||||
172.31.0.0/16+, # ChaosVPN
|
||||
10.100.0.0/14+, # ChaosVPN
|
||||
10.127.0.0/16{16,32}, # neonetwork
|
||||
10.0.0.0/8{15,24} # Freifunk.net
|
||||
];
|
||||
function is_self_net() -> bool {
|
||||
return is_self_net_v4() || is_self_net_v6();
|
||||
}
|
||||
|
||||
/*
|
||||
roa4 table dn42_roa;
|
||||
roa6 table dn42_roa_v6;
|
||||
include "${../resources/community_filter.conf}";
|
||||
include "${../resources/filters.conf}";
|
||||
|
||||
router id ${cfg.routerId};
|
||||
hostname "${config.networking.hostName}.${config.networking.domain}";
|
||||
|
||||
protocol static {
|
||||
roa4 { table dn42_roa; };
|
||||
include "/etc/bird/roa_dn42.conf";
|
||||
};
|
||||
|
||||
protocol static {
|
||||
roa6 { table dn42_roa_v6; };
|
||||
include "/etc/bird/roa_dn42_v6.conf";
|
||||
};
|
||||
*/
|
||||
|
||||
function is_valid_network_v6() -> bool {
|
||||
return net ~ [
|
||||
fd00::/8{44,64} # ULA address space as per RFC 4193
|
||||
];
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
|
||||
protocol kernel {
|
||||
|
@ -121,46 +100,17 @@ in
|
|||
|
||||
template bgp dnpeers {
|
||||
local as ${builtins.toString cfg.as};
|
||||
path metric 1;
|
||||
|
||||
enforce first as on;
|
||||
graceful restart on;
|
||||
long lived graceful restart on;
|
||||
interpret communities on;
|
||||
advertise hostname on;
|
||||
prefer older on;
|
||||
|
||||
ipv4 {
|
||||
import filter {
|
||||
if is_valid_network_v4() && !is_self_net_v4() then {
|
||||
/*if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then {
|
||||
# Reject when unknown or invalid according to ROA
|
||||
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
|
||||
reject;
|
||||
} else*/ accept;
|
||||
} else reject;
|
||||
};
|
||||
|
||||
export filter { if is_valid_network_v4() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
|
||||
|
||||
import limit 9000 action block;
|
||||
import table on;
|
||||
};
|
||||
|
||||
ipv6 {
|
||||
import filter {
|
||||
if is_valid_network_v6() && !is_self_net_v6() then {
|
||||
/*if (roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID) then {
|
||||
# Reject when unknown or invalid according to ROA
|
||||
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
|
||||
reject;
|
||||
} else*/ accept;
|
||||
} else reject;
|
||||
};
|
||||
|
||||
export filter { if is_valid_network_v6() && source ~ [RTS_STATIC, RTS_BGP] then accept; else reject; };
|
||||
|
||||
import limit 9000 action block;
|
||||
import table on;
|
||||
};
|
||||
# defaults
|
||||
enable route refresh on;
|
||||
interpret communities on;
|
||||
default bgp_local_pref 100;
|
||||
}
|
||||
|
||||
${builtins.concatStringsSep "\n" (builtins.attrValues
|
||||
|
@ -170,6 +120,14 @@ in
|
|||
protocol bgp ${name}_4 from dnpeers {
|
||||
neighbor ${conf.addr.v4} as ${builtins.toString conf.as};
|
||||
source address ${conf.srcAddr.v4};
|
||||
|
||||
ipv4 {
|
||||
import limit 9000 action block;
|
||||
import table on;
|
||||
|
||||
import where dn_import_filter(${toString conf.latency}, ${toString conf.bandwidth}, ${toString conf.crypto});
|
||||
export where dn_export_filter(${toString conf.latency}, ${toString conf.bandwidth}, ${toString conf.crypto});
|
||||
};
|
||||
}
|
||||
''}
|
||||
|
||||
|
@ -178,9 +136,22 @@ in
|
|||
enable extended messages on;
|
||||
|
||||
ipv4 {
|
||||
extended next hop on;
|
||||
import limit 9000 action block;
|
||||
import table on;
|
||||
|
||||
extended next hop on;
|
||||
import where dn_import_filter(${toString conf.latency}, ${toString conf.bandwidth}, ${toString conf.crypto});
|
||||
export where dn_export_filter(${toString conf.latency}, ${toString conf.bandwidth}, ${toString conf.crypto});
|
||||
};
|
||||
''}
|
||||
|
||||
ipv6 {
|
||||
import limit 9000 action block;
|
||||
import table on;
|
||||
|
||||
import where dn_import_filter(${toString conf.latency}, ${toString conf.bandwidth}, ${toString conf.crypto});
|
||||
export where dn_export_filter(${toString conf.latency}, ${toString conf.bandwidth}, ${toString conf.crypto});
|
||||
};
|
||||
|
||||
neighbor ${conf.addr.v6}%'${conf.interface}' as ${builtins.toString conf.as};
|
||||
source address ${conf.srcAddr.v6};
|
||||
|
|
|
@ -22,6 +22,26 @@ in
|
|||
description = "Autonomous System Number";
|
||||
};
|
||||
|
||||
bandwidth = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
geo = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
country = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
blockedAs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
addr = {
|
||||
v4 = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
@ -60,6 +80,21 @@ in
|
|||
default = false;
|
||||
};
|
||||
|
||||
latency = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
bandwidth = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
crypto = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = "";
|
||||
};
|
||||
|
||||
addr = {
|
||||
v4 = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
function update_latency(int link_latency) {
|
||||
bgp_community.add((64511, link_latency));
|
||||
if (64511, 9) ~ bgp_community then { bgp_community.delete([(64511, 1..8)]); }
|
||||
else if (64511, 8) ~ bgp_community then { bgp_community.delete([(64511, 1..7)]); }
|
||||
else if (64511, 7) ~ bgp_community then { bgp_community.delete([(64511, 1..6)]); }
|
||||
else if (64511, 6) ~ bgp_community then { bgp_community.delete([(64511, 1..5)]); }
|
||||
else if (64511, 5) ~ bgp_community then { bgp_community.delete([(64511, 1..4)]); }
|
||||
else if (64511, 4) ~ bgp_community then { bgp_community.delete([(64511, 1..3)]); }
|
||||
else if (64511, 3) ~ bgp_community then { bgp_community.delete([(64511, 1..2)]); }
|
||||
else if (64511, 2) ~ bgp_community then { bgp_community.delete([(64511, 1..1)]); }
|
||||
}
|
||||
|
||||
function update_bandwidth(int link_bandwidth) {
|
||||
bgp_community.add((64511, link_bandwidth));
|
||||
if (64511, 21) ~ bgp_community then { bgp_community.delete([(64511, 22..29)]); }
|
||||
else if (64511, 22) ~ bgp_community then { bgp_community.delete([(64511, 23..29)]); }
|
||||
else if (64511, 23) ~ bgp_community then { bgp_community.delete([(64511, 24..29)]); }
|
||||
else if (64511, 24) ~ bgp_community then { bgp_community.delete([(64511, 25..29)]); }
|
||||
else if (64511, 25) ~ bgp_community then { bgp_community.delete([(64511, 26..29)]); }
|
||||
else if (64511, 26) ~ bgp_community then { bgp_community.delete([(64511, 27..29)]); }
|
||||
else if (64511, 27) ~ bgp_community then { bgp_community.delete([(64511, 28..29)]); }
|
||||
else if (64511, 28) ~ bgp_community then { bgp_community.delete([(64511, 29..29)]); }
|
||||
}
|
||||
|
||||
function update_crypto(int link_crypto) {
|
||||
bgp_community.add((64511, link_crypto));
|
||||
if (64511, 31) ~ bgp_community then { bgp_community.delete([(64511, 32..34)]); }
|
||||
else if (64511, 32) ~ bgp_community then { bgp_community.delete([(64511, 33..34)]); }
|
||||
else if (64511, 33) ~ bgp_community then { bgp_community.delete([(64511, 34..34)]); }
|
||||
}
|
||||
|
||||
function update_flags(int link_latency; int link_bandwidth; int link_crypto) {
|
||||
if link_bandwidth > BANDWIDTH then link_bandwidth = BANDWIDTH;
|
||||
|
||||
update_latency(link_latency);
|
||||
update_bandwidth(link_bandwidth);
|
||||
update_crypto(link_crypto);
|
||||
}
|
||||
|
||||
function update_region() {
|
||||
if is_self_net() then {
|
||||
bgp_community.add((64511, REGION_GEO));
|
||||
bgp_community.add((64511, REGION_COUNTRY));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
function is_valid_network_v4() -> bool{
|
||||
return net ~ [
|
||||
172.20.0.0/14{21,29}, # dn42
|
||||
172.20.0.0/24{28,32}, # dn42 Anycast
|
||||
172.21.0.0/24{28,32}, # dn42 Anycast
|
||||
172.22.0.0/24{28,32}, # dn42 Anycast
|
||||
172.23.0.0/24{28,32}, # dn42 Anycast
|
||||
172.31.0.0/16+, # ChaosVPN
|
||||
10.100.0.0/14+, # ChaosVPN
|
||||
10.127.0.0/16{16,32}, # neonetwork
|
||||
10.0.0.0/8{15,24} # Freifunk.net
|
||||
];
|
||||
}
|
||||
|
||||
function is_valid_network_v6() -> bool {
|
||||
return net ~ [
|
||||
fd00::/8{44,64}
|
||||
];
|
||||
}
|
||||
|
||||
function is_valid_network() -> bool {
|
||||
return is_valid_network_v4() || is_valid_network_v6();
|
||||
}
|
||||
|
||||
function kernel_export() {
|
||||
krt_prefsrc = OWNIP;
|
||||
accept;
|
||||
}
|
||||
|
||||
function reject_invalid_roa() {
|
||||
#if (roa_check(dnroa, net, bgp_path.last) != ROA_VALID) then {
|
||||
# print "Reject: ROA failed|", net, "|", bgp_path;
|
||||
# reject;
|
||||
#}
|
||||
}
|
||||
|
||||
function reject_default_route() {
|
||||
if (net = fd00::/8 || net = ::/0) then
|
||||
reject;
|
||||
}
|
||||
|
||||
function reject_blacklisted()
|
||||
int set blacklist;
|
||||
{
|
||||
blacklist = ASN_BLACKLIST;
|
||||
|
||||
if ( bgp_path ~ blacklist ) then {
|
||||
print "Reject: blacklisted ASN|", bgp_path;
|
||||
reject;
|
||||
}
|
||||
}
|
||||
|
||||
function honor_graceful_shutdown() {
|
||||
if (65535, 0) ~ bgp_community then {
|
||||
bgp_local_pref = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function dn_import_filter(int link_latency; int link_bandwidth; int link_crypto) {
|
||||
#if ( net.type != NET_IP6 ) then {
|
||||
# print "Reject: non-IPv6 on IPv6 Channel|", net, "|", bgp_path;
|
||||
# reject;
|
||||
#}
|
||||
|
||||
if ( ! is_valid_network() ) then {
|
||||
print "Reject: invalid network|", net, "|", bgp_path;
|
||||
reject;
|
||||
}
|
||||
|
||||
if ( is_self_net() ) then {
|
||||
print "Reject: export our network|", net, "|", bgp_path.first;
|
||||
reject;
|
||||
}
|
||||
|
||||
if ( bgp_path.len > 25 ) then {
|
||||
print "Reject: AS path too long|", net, "|", bgp_path;
|
||||
reject;
|
||||
}
|
||||
|
||||
reject_blacklisted();
|
||||
reject_invalid_roa();
|
||||
reject_default_route();
|
||||
|
||||
if (bgp_path.len = 1) then
|
||||
bgp_local_pref = bgp_local_pref + 500;
|
||||
|
||||
update_flags(link_latency, link_bandwidth, link_crypto);
|
||||
|
||||
accept;
|
||||
}
|
||||
|
||||
function dn_export_filter(int link_latency; int link_bandwidth; int link_crypto) {
|
||||
if (source !~ [RTS_STATIC, RTS_BGP]) then
|
||||
reject;
|
||||
|
||||
if (bgp_path.last != bgp_path.first) then
|
||||
reject;
|
||||
|
||||
reject_default_route();
|
||||
|
||||
update_flags(link_latency, link_bandwidth, link_crypto);
|
||||
update_region();
|
||||
|
||||
bgp_med = 0;
|
||||
bgp_med = bgp_med + ( ( 4 - ( link_crypto - 30 ) ) * 600 );
|
||||
bgp_med = bgp_med + ( ( 9 - ( link_bandwidth - 20 ) ) * 100);
|
||||
bgp_med = bgp_med + ( ( link_latency - 1) * 300);
|
||||
|
||||
accept;
|
||||
}
|
||||
|
||||
function dn_export_collector() {
|
||||
if (source !~ [RTS_STATIC, RTS_BGP]) then
|
||||
reject;
|
||||
|
||||
update_region();
|
||||
accept;
|
||||
}
|
||||
|
Loading…
Reference in New Issue