prefect: Enable DN42 configuration
This commit is contained in:
parent
e77b7e97cf
commit
a08dfb632f
8 changed files with 512 additions and 0 deletions
|
@ -16,6 +16,9 @@
|
|||
./networking.nix
|
||||
./hardware.nix
|
||||
|
||||
# DN42 Services
|
||||
./dn42.nix
|
||||
|
||||
# Running Services
|
||||
./services/blog-update.nix
|
||||
./services/caddy.nix
|
||||
|
|
46
hosts/prefect/dn42.nix
Normal file
46
hosts/prefect/dn42.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
hedge.dn42 = {
|
||||
enable = true;
|
||||
bgp = {
|
||||
asn = "4242422459";
|
||||
staticRoutes = {
|
||||
ipv4 = [
|
||||
"172.20.43.96/27"
|
||||
];
|
||||
ipv6 = [
|
||||
"fd21:1500:66b0::/48"
|
||||
];
|
||||
};
|
||||
};
|
||||
peers = {
|
||||
lutoma = {
|
||||
tunnelType = "wireguard";
|
||||
wireguardConfig = {
|
||||
localPort = 485;
|
||||
remotePort = 42518;
|
||||
remoteEndpoint = "us-nyc.dn42.lutoma.org";
|
||||
remotePublicKey = "PVrvKh7MAkLfCdO2u1t6WqAsAMw1afeQ8OewdL/K2Cw=";
|
||||
};
|
||||
interfaceName = "wg-lutoma";
|
||||
bgp = {
|
||||
asn = "64719";
|
||||
multi_protocol = true;
|
||||
local_pref = 100;
|
||||
};
|
||||
addresses = {
|
||||
ipv4 = {
|
||||
local_address = "172.20.43.96";
|
||||
remote_address = "172.22.119.10";
|
||||
prefix_length = 32;
|
||||
};
|
||||
ipv6 = {
|
||||
local_address = "fe80::1";
|
||||
remote_address = "fe80::acab";
|
||||
prefix_length = 64;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
48
hosts/prefect/dn42/bgp.nix
Normal file
48
hosts/prefect/dn42/bgp.nix
Normal file
|
@ -0,0 +1,48 @@
|
|||
{ ... }:
|
||||
{
|
||||
sessions = [
|
||||
{ multi = true; name = "androw_2575"; neigh = "fe80::2575:6%andro_2575_zrh"; as = "4242422575"; link = "4"; }
|
||||
{ multi = true; name = "bandura_2923"; neigh = "fe80::2923%band_2923_nur"; as = "4242422923"; link = "3"; }
|
||||
{ multi = true; name = "dgy_0826"; neigh = "fe80::a0e:fb02%dgy_0826_la"; as = "4242420826"; link = "5"; }
|
||||
{ multi = false; v4 = true; v6 = false; name = "hackfront_1472_v4"; neigh = "172.23.167.1"; as = "4242421472"; link = "4"; }
|
||||
{ multi = false; v4 = false; v6 = true; name = "hackfront_1472_v6"; neigh = "fe80::1472%hackf_1472_it"; as = "4242421472"; link = "4"; }
|
||||
{ multi = true; name = "jlu5_1080"; neigh = "fe80::116%jlu5_1080_lon"; as = "4242421080"; link = "3"; }
|
||||
{ multi = true; name = "kioubit_3914"; neigh = "fe80::ade0%kioubit_3914_uk"; as = "4242423914"; link = "3"; }
|
||||
{ multi = true; name = "n0emis_0197"; neigh = "fe80::42:42:1%n0emi_0197_gtg"; as = "4242420197"; link = "4"; }
|
||||
{ multi = true; name = "napsterbater_1050"; neigh = "fe80::1:1050%napst_1050_fra"; as = "4242421050"; link = "2"; }
|
||||
{ multi = true; name = "niantic_1331"; neigh = "fe80::1331%niant_1331_ams"; as = "4242421331"; link = "3"; }
|
||||
{ multi = true; name = "yuetau_0925"; neigh = "fe80::925%yuetau_0925_nue"; as = "4242420925"; link = "3"; }
|
||||
];
|
||||
extraConfig = ''
|
||||
protocol bgp iBGP_par_v4 from dnpeers {
|
||||
#disabled;
|
||||
neighbor 172.20.4.97 as 4242421722;
|
||||
ipv4 {
|
||||
next hop self;
|
||||
import all;
|
||||
export where dn42_export_filter(3,25,34);
|
||||
import keep filtered;
|
||||
};
|
||||
ipv6 {
|
||||
next hop self;
|
||||
import none;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
protocol bgp iBGP_par_v6 from dnpeers {
|
||||
#disabled;
|
||||
neighbor fd54:fe4b:9ed1:1::1 as 4242421722;
|
||||
ipv4 {
|
||||
next hop self;
|
||||
import none;
|
||||
export none;
|
||||
};
|
||||
ipv6 {
|
||||
next hop self;
|
||||
import all;
|
||||
export where dn42_export_filter(3,25,34);
|
||||
import keep filtered;
|
||||
};
|
||||
}
|
||||
'';
|
||||
}
|
279
hosts/prefect/dn42/bird.conf
Normal file
279
hosts/prefect/dn42/bird.conf
Normal file
|
@ -0,0 +1,279 @@
|
|||
log stderr all;
|
||||
debug protocols all;
|
||||
timeformat protocol iso long;
|
||||
################################################
|
||||
# Variable header #
|
||||
################################################
|
||||
|
||||
define OWNAS = 4242422459;
|
||||
define OWNIP = 172.20.43.96;
|
||||
define OWNIPv6 = fd21:1500:66b0::1;
|
||||
define OWNNET = 172.20.43.96/27;
|
||||
define OWNNETv6 = fd21:1500:66b0::/48;
|
||||
define OWNNETSET = [172.20.43.96/29+];
|
||||
define OWNNETSETv6 = [fd21:1500:66b0::/48+];
|
||||
define DN42_REGION = 42;
|
||||
|
||||
################################################
|
||||
# Header end #
|
||||
################################################
|
||||
|
||||
router id OWNIP;
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
function is_self_net() {
|
||||
return net ~ OWNNETSET;
|
||||
}
|
||||
|
||||
function is_self_net_v6() {
|
||||
return net ~ OWNNETSETv6;
|
||||
}
|
||||
|
||||
function is_valid_network() {
|
||||
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
|
||||
];
|
||||
}
|
||||
|
||||
roa4 table dn42_roa;
|
||||
roa6 table dn42_roa_v6;
|
||||
|
||||
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() {
|
||||
return net ~ [
|
||||
fd00::/8{44,64} # ULA address space as per RFC 4193
|
||||
];
|
||||
}
|
||||
|
||||
protocol kernel {
|
||||
scan time 20;
|
||||
|
||||
ipv6 {
|
||||
import none;
|
||||
export filter {
|
||||
if source = RTS_STATIC then reject;
|
||||
krt_prefsrc = OWNIPv6;
|
||||
accept;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
protocol kernel {
|
||||
scan time 20;
|
||||
ipv4 {
|
||||
import none;
|
||||
export filter {
|
||||
if source = RTS_STATIC then reject;
|
||||
krt_prefsrc = OWNIP;
|
||||
accept;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
protocol static {
|
||||
route OWNNET reject;
|
||||
|
||||
ipv4 {
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
|
||||
protocol static {
|
||||
route OWNNETv6 reject;
|
||||
|
||||
ipv6 {
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
|
||||
template bgp dnpeers {
|
||||
local as OWNAS;
|
||||
path metric 1;
|
||||
}
|
||||
|
||||
protocol ospf v3 {
|
||||
ipv4 {
|
||||
export filter {
|
||||
if source = RTS_STATIC || source = RTS_BGP then reject;
|
||||
accept;
|
||||
};
|
||||
};
|
||||
|
||||
area 0 {
|
||||
interface "lo" {
|
||||
stub;
|
||||
};
|
||||
|
||||
interface "ospf_*"{
|
||||
type pointopoint;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
protocol ospf v3 {
|
||||
ipv6 {
|
||||
export filter {
|
||||
if source = RTS_STATIC || source = RTS_BGP then reject;
|
||||
accept;
|
||||
};
|
||||
};
|
||||
|
||||
area 0 {
|
||||
interface "lo" {
|
||||
stub;
|
||||
};
|
||||
|
||||
interface "ospf_*" {
|
||||
type pointopoint;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function update_latency(int link_latency) {
|
||||
bgp_community.add((64511, link_latency));
|
||||
if (64511, 9) ~ bgp_community then { bgp_community.delete([(64511, 1..8)]); return 9; }
|
||||
else if (64511, 8) ~ bgp_community then { bgp_community.delete([(64511, 1..7)]); return 8; }
|
||||
else if (64511, 7) ~ bgp_community then { bgp_community.delete([(64511, 1..6)]); return 7; }
|
||||
else if (64511, 6) ~ bgp_community then { bgp_community.delete([(64511, 1..5)]); return 6; }
|
||||
else if (64511, 5) ~ bgp_community then { bgp_community.delete([(64511, 1..4)]); return 5; }
|
||||
else if (64511, 4) ~ bgp_community then { bgp_community.delete([(64511, 1..3)]); return 4; }
|
||||
else if (64511, 3) ~ bgp_community then { bgp_community.delete([(64511, 1..2)]); return 3; }
|
||||
else if (64511, 2) ~ bgp_community then { bgp_community.delete([(64511, 1..1)]); return 2; }
|
||||
else return 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)]); return 21; }
|
||||
else if (64511, 22) ~ bgp_community then { bgp_community.delete([(64511, 23..29)]); return 22; }
|
||||
else if (64511, 23) ~ bgp_community then { bgp_community.delete([(64511, 24..29)]); return 23; }
|
||||
else if (64511, 24) ~ bgp_community then { bgp_community.delete([(64511, 25..29)]); return 24; }
|
||||
else if (64511, 25) ~ bgp_community then { bgp_community.delete([(64511, 26..29)]); return 25; }
|
||||
else if (64511, 26) ~ bgp_community then { bgp_community.delete([(64511, 27..29)]); return 26; }
|
||||
else if (64511, 27) ~ bgp_community then { bgp_community.delete([(64511, 28..29)]); return 27; }
|
||||
else if (64511, 28) ~ bgp_community then { bgp_community.delete([(64511, 29..29)]); return 28; }
|
||||
else return 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)]); return 31; }
|
||||
else if (64511, 32) ~ bgp_community then { bgp_community.delete([(64511, 33..34)]); return 32; }
|
||||
else if (64511, 33) ~ bgp_community then { bgp_community.delete([(64511, 34..34)]); return 33; }
|
||||
else return 34;
|
||||
}
|
||||
|
||||
function get_region() {
|
||||
if (64511, 41) ~ bgp_community then { return 41; }
|
||||
else if (64511, 42) ~ bgp_community then { return 42; }
|
||||
else if (64511, 43) ~ bgp_community then { return 43; }
|
||||
else if (64511, 44) ~ bgp_community then { return 44; }
|
||||
else if (64511, 45) ~ bgp_community then { return 45; }
|
||||
else if (64511, 46) ~ bgp_community then { return 46; }
|
||||
else if (64511, 47) ~ bgp_community then { return 47; }
|
||||
else if (64511, 48) ~ bgp_community then { return 48; }
|
||||
else if (64511, 49) ~ bgp_community then { return 49; }
|
||||
else if (64511, 50) ~ bgp_community then { return 50; }
|
||||
else if (64511, 51) ~ bgp_community then { return 51; }
|
||||
else if (64511, 52) ~ bgp_community then { return 52; }
|
||||
else if (64511, 53) ~ bgp_community then { return 53; }
|
||||
else return DN42_REGION;
|
||||
}
|
||||
|
||||
|
||||
function calculate_local_pref(int dn42_latency)
|
||||
int pref;
|
||||
{
|
||||
pref = 100;
|
||||
if (is_self_net() || is_self_net_v6()) then {
|
||||
pref = 2000;
|
||||
}
|
||||
else if (bgp_path.len = 1) then {
|
||||
pref = 1000;
|
||||
}
|
||||
else if (DN42_REGION = get_region()) then {
|
||||
pref= 500;
|
||||
}
|
||||
else {
|
||||
if (DN42_REGION > get_region()) then {
|
||||
pref = 500 - ((DN42_REGION - get_region()) * 10);
|
||||
}
|
||||
else {
|
||||
pref = 500 - ((get_region() - DN42_REGION) * 10);
|
||||
}
|
||||
}
|
||||
pref = pref - 10*dn42_latency - 10* bgp_path.len;
|
||||
if pref > 2000 then {
|
||||
pref = 10;
|
||||
}
|
||||
return pref;
|
||||
}
|
||||
|
||||
function update_flags(int link_latency; int link_bandwidth; int link_crypto)
|
||||
int dn42_latency;
|
||||
int dn42_bandwidth;
|
||||
int dn42_crypto;
|
||||
{
|
||||
dn42_latency = update_latency(link_latency);
|
||||
dn42_bandwidth = update_bandwidth(link_bandwidth) - 20;
|
||||
dn42_crypto = update_crypto(link_crypto) - 30;
|
||||
if dn42_bandwidth > 5 then dn42_bandwidth = 5;
|
||||
bgp_local_pref = calculate_local_pref(dn42_latency);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function dn42_import_filter(int link_latency; int link_bandwidth; int link_crypto) {
|
||||
if (is_valid_network() && !is_self_net()) || (is_valid_network_v6() && !is_self_net_v6()) then {
|
||||
if roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID && roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID then {
|
||||
print "[dn42] Import : ROA check failed for ", net, " ASN ", bgp_path.last, " on ", proto;
|
||||
reject;
|
||||
}
|
||||
update_flags(link_latency, link_bandwidth, link_crypto);
|
||||
if (65535, 666) ~ bgp_community then dest = RTD_BLACKHOLE;
|
||||
accept;
|
||||
}
|
||||
print "[dn42] Import : Invalid Network for ", net, " ASN ", bgp_path.last, " on ", proto;
|
||||
reject;
|
||||
}
|
||||
|
||||
function dn42_export_filter(int link_latency; int link_bandwith; int link_crypto) {
|
||||
if is_valid_network() || is_valid_network_v6() then {
|
||||
# if roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID && roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID then {
|
||||
# print "[dn42] Export : ROA check failed for ", net, " ASN ", bgp_path.last, " on ", proto;
|
||||
# reject;
|
||||
# }
|
||||
if source = RTS_STATIC then bgp_community.add((64511, DN42_REGION));
|
||||
update_flags(link_latency, link_bandwith, link_crypto);
|
||||
accept;
|
||||
}
|
||||
reject;
|
||||
}
|
15
hosts/prefect/dn42/default.nix
Normal file
15
hosts/prefect/dn42/default.nix
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
networking.interfaces.lo = {
|
||||
ipv4.addresses = [{ address = "172.20.43.96"; prefixLength = 32; }];
|
||||
ipv6.addresses = [
|
||||
{ address = "fd21:1500:66b0::1"; prefixLength = 128; }
|
||||
{ address = "fe80::1"; prefixLength = 128; }
|
||||
];
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
dnsutils
|
||||
mtr
|
||||
tcpdump
|
||||
wireguard-tools
|
||||
];
|
||||
}
|
83
hosts/prefect/dn42/services.nix
Normal file
83
hosts/prefect/dn42/services.nix
Normal file
|
@ -0,0 +1,83 @@
|
|||
let
|
||||
script = pkgs.writeShellScriptBin "update-roa" ''
|
||||
mkdir -p /etc/bird/
|
||||
${pkgs.curl}/bin/curl -sfSLR {-o,-z}/etc/bird/roa_dn42_v6.conf https://dn42.burble.com/roa/dn42_roa_bird2_6.conf
|
||||
${pkgs.curl}/bin/curl -sfSLR {-o,-z}/etc/bird/roa_dn42.conf https://dn42.burble.com/roa/dn42_roa_bird2_4.conf
|
||||
${pkgs.bird2}/bin/birdc c
|
||||
${pkgs.bird2}/bin/birdc reload in all
|
||||
'';
|
||||
bgp = import peers/bgp.nix { };
|
||||
in
|
||||
{
|
||||
systemd.timers.dn42-roa = {
|
||||
description = "Trigger a ROA table update";
|
||||
|
||||
timerConfig = {
|
||||
OnBootSec = "5m";
|
||||
OnUnitInactiveSec = "1h";
|
||||
Unit = "dn42-roa.service";
|
||||
};
|
||||
|
||||
wantedBy = [ "timers.target" ];
|
||||
before = [ "bird.service" ];
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
dn42-roa = {
|
||||
after = [ "network.target" ];
|
||||
description = "DN42 ROA Updated";
|
||||
unitConfig = {
|
||||
Type = "one-shot";
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = "${script}/bin/update-roa";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
services = {
|
||||
bird-lg = {
|
||||
proxy = {
|
||||
enable = true;
|
||||
allowedIPs = [ "172.20.4.97" "172.20.4.98" ];
|
||||
};
|
||||
frontend = {
|
||||
enable = false;
|
||||
servers = [ "fr-par" "fr-lyn" ];
|
||||
domain = "node.tchekda.dn42";
|
||||
};
|
||||
};
|
||||
|
||||
bird2 = {
|
||||
enable = true;
|
||||
checkConfig = false;
|
||||
config = builtins.readFile ./bird.conf + lib.concatStrings (builtins.map
|
||||
(x: "
|
||||
protocol bgp ${x.name} from dnpeers {
|
||||
neighbor ${x.neigh} as ${x.as};
|
||||
${if x.multi || x.v4 then "
|
||||
ipv4 {
|
||||
extended next hop on;
|
||||
import where dn42_import_filter(${x.link},25,34);
|
||||
export where dn42_export_filter(${x.link},25,34);
|
||||
import keep filtered;
|
||||
};
|
||||
" else ""}
|
||||
${if x.multi || x.v6 then "
|
||||
ipv6 {
|
||||
extended next hop on;
|
||||
import where dn42_import_filter(${x.link},25,34);
|
||||
export where dn42_export_filter(${x.link},25,34);
|
||||
import keep filtered;
|
||||
};
|
||||
" else ""}
|
||||
}
|
||||
")
|
||||
bgp.sessions) + bgp.extraConfig;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.thehedgehog.extraGroups = [ "bird2" ];
|
||||
}
|
8
hosts/prefect/dn42/tunnels.nix
Normal file
8
hosts/prefect/dn42/tunnels.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{ tunnel, ospf, ... }:
|
||||
let
|
||||
defaultPubKey = "e6kp9sca4XIzncKa9GEQwyOnMjje299Xg9ZdgXWMwHg=";
|
||||
defaultPrivKeyFile = "/run/agenix/dn42-privkey";
|
||||
in
|
||||
{
|
||||
tunnel_name = tunnel 485 defaultPrivKeyFile "GbaMZ4f32JpaAnYuBZuUNqPFHDFgRkhqLOZUTVQYAHo" "{REMOTE_HOST:REMOTE_PORT}" "wg-dn42-lutoma" "172.20.43.96" "{TUNNEL_IPV6}";
|
||||
}
|
30
hosts/prefect/dn42/wireguard.nix
Normal file
30
hosts/prefect/dn42/wireguard.nix
Normal file
|
@ -0,0 +1,30 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
defaultLocalIPv4 = "172.20.43.96/32";
|
||||
defaultLocalIPv6 = "fe80::1722:98/64";
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [ pkgs.wireguard-tools ];
|
||||
|
||||
networking.wireguard.interfaces = import tunnels.nix rec {
|
||||
customTunnel = listenPort: privKeyFile: peerPubKey: endpoint: name: tunnelIPv4: tunnelIPv6: localIPv4: localIPv6: isOspf: {
|
||||
listenPort = listenPort;
|
||||
privateKey = privKeyFile;
|
||||
allowedIPsAsRoutes = false;
|
||||
peers = [
|
||||
{
|
||||
publicKey = publicKey;
|
||||
allowedIPs = [ "0.0.0.0/0" "::/0" ];
|
||||
endpoint = endpoint;
|
||||
dynamicEndpointRefreshSeconds = 5;
|
||||
}
|
||||
];
|
||||
postSetup = ''
|
||||
${pkgs.iproute}/bin/ip addr add ${localIPv4} peer ${tunnelIPv4} dev ${name}
|
||||
${pkgs.iproute}/bin/ip -6 addr add ${localIPv6} peer ${tunnelIPv6} dev ${name}
|
||||
'' + lib.optionalString isOspf "${pkgs.iproute}/bin/ip -6 addr add ${defaultLocalIPv6} dev ${name}";
|
||||
};
|
||||
tunnel = listenPort: privateKey: publicKey: endpoint: name: tunnelIPv4: tunnelIPv6: customTunnel listenPort privateKey publicKey endpoint name tunnelIPv4 tunnelIPv6 defaultLocalIPv4 defaultLocalIPv6 false;
|
||||
ospf = listenPort: privateKey: publicKey: endpoint: name: tunnelIPv4: tunnelIPv6: ULAIPv6: customTunnel listenPort privateKey publicKey endpoint name tunnelIPv4 tunnelIPv6 defaultLocalIPv4 ULAIPv6 true;
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue