{ config, pkgs, lib, ... }: let address4 = "172.22.99.253"; address6 = "fe80::deca:fbad"; neighbors = import ./neighbors.nix; makeBgpNeighbor = { name, asn, description ? "Someone", address, interface ? name, ... }: '' neighbor ${address} remote-as ${builtins.toString asn} neighbor ${address} peer-group dn neighbor ${address} interface ${interface} neighbor ${address} description ${description} ''; bgpNeighbors = builtins.attrValues (builtins.mapAttrs (name: conf: let makeNeighbor = address: makeBgpNeighbor (conf // { inherit name address; }); in # Bird peers don't do IPv6 routes over IPv4, so they get # additional config: let neighbor4 = if conf ? address4 then makeNeighbor conf.address4 else ""; neighbor6 = if conf ? address6 then makeNeighbor conf.address6 else ""; in "${neighbor4}${neighbor6}" ) neighbors); bgpNeighbors6 = builtins.attrValues (builtins.mapAttrs (name: conf: if conf ? address6 then '' neighbor ${conf.address6} peer-group dn neighbor ${conf.address6} route-map ${name}-next-hop in '' else "" ) neighbors); common = '' service advanced-vty line vty ip prefix-list dn42-in seq 10 permit 172.22.0.0/15 ge 22 le 28 ip prefix-list dn42-in seq 12 permit 172.20.0.0/16 ge 21 le 28 ip prefix-list dn42-in seq 15 permit 172.22.0.0/23 ge 32 ip prefix-list dn42-in seq 16 permit 172.23.0.0/24 ge 32 ip prefix-list dn42-in seq 20 deny 10.10.10.0/24 le 32 ip prefix-list dn42-in seq 21 permit 10.0.0.0/8 ge 12 le 28 ip prefix-list dn42-in seq 30 permit 172.31.0.0/16 ge 22 le 28 ip prefix-list dn42-in seq 1000 deny 0.0.0.0/0 le 32 ! ipv6 prefix-list def seq 5 permit 2000::/3 ge 32 ipv6 prefix-list def seq 10 permit fd00::/8 ge 9 le 64 ipv6 prefix-list def seq 1000 deny ::/0 le 128 ''; in { imports = [ ../../../lib/lxc-container.nix ../../../lib/shared.nix ../../../lib/admins.nix ]; networking.hostName = "dn42"; networking.defaultGateway = "172.22.99.4"; networking.nameservers = [ "172.20.72.6" "172.20.72.10" ]; networking.interfaces.eth0 = { ipv4.addresses = [ { address = address4; prefixLength = 24; } ]; }; environment.systemPackages = with pkgs; [ vim # for `vtysh` quagga ]; # SSH for nixops services.openssh.enable = true; services.openssh.permitRootLogin = "yes"; # No Firewalling! networking.firewall.enable = false; networking.useDHCP = false; services.quagga = { zebra = { config = '' ip forwarding ipv6 forwarding interface eth0 ipv6 address fe80::a800:42ff:fe7a:3246/64 ipv6 address 2a02:8106:208:5201::ffff/64 ipv6 address fd23:42:c3d2:523::ffff/64 ipv6 nd prefix fd23:42:c3d2:523::/64 60 20 ipv6 nd ra-interval 5 no ipv6 nd suppress-ra ip route 0.0.0.0/0 172.22.99.4 ip route 10.0.0.0/8 Null0 ip route 172.16.0.0/12 Null0 ip route 192.168.0.0/16 Null0 ipv6 route 2000::/3 2a02:8106:208:5201::c3d2:4 eth0 ${common} ''; }; bgp = { enable = true; config = '' router bgp 64699 bgp router-id ${address4} network 172.22.99.0/24 neighbor dn peer-group neighbor dn soft-reconfiguration inbound neighbor dn prefix-list dn42-in in ${builtins.concatStringsSep "\n" bgpNeighbors} address-family ipv6 network fd23:42:c3d2:500::/56 neighbor dn activate neighbor dn soft-reconfiguration inbound neighbor dn prefix-list def in ${builtins.concatStringsSep "\n" bgpNeighbors6} exit-address-family exit route-map set-next-hop permit 10 set ip next-hop 172.22.99.253 route-map set-next-hop6 permit 10 set ipv6 next-hop global 2001:6f8:1194:c3d2::ffff set ipv6 next-hop local fe80::a800:42ff:fe7a:3246 route-map set-next-hop-zw-server1 permit 10 set ip next-hop 172.22.99.250 route-map zw-next-hop permit 10 set ipv6 next-hop local fe80::814:48ff:fe01:2201 set ipv6 next-hop local fe80::814:48ff:fe01:2201 ${common} ''; }; ospf = { enable = true; config = '' router ospf ospf router-id ${address4} redistribute connected redistribute static network 172.22.99.0/24 area 0.0.0.0 area 0.0.0.0 authentication message-digest default-metric 1 interface eth0 ip ospf message-digest-key 1 md5 ${builtins.readFile ../../../secrets/shared/ospf/message-digest-key.nix} ${common} ''; }; ospf6 = { enable = true; config = '' router ospf6 router-id 172.22.99.253 redistribute connected area 0.0.0.0 range 2001:6f8:1194:c3d2::/64 interface eth0 area 0.0.0.0 interface eth0 ipv6 ospf6 cost 1 ipv6 ospf6 network broadcast ${common} ''; }; }; services.openvpn = let openvpnNeighbors = lib.filterAttrs (_: conf: conf ? openvpn) neighbors; keyfile = name: builtins.toFile "${name}.key" (builtins.readFile (../../../secrets/hosts/dn42/openvpn + "/${name}.key")); mkServer = name: conf: { config = '' dev ${name} dev-type tun ifconfig ${address4} ${conf.address4} user nobody group nogroup persist-tun persist-key ping 30 ping-restart 45 verb 1 ${conf.openvpn} secret ${keyfile name} ''; up = '' ${pkgs.iproute}/bin/ip a a fe80::deca:fbad/64 dev $1 ''; }; in { servers = builtins.mapAttrs (name: conf: mkServer name conf) openvpnNeighbors; }; # This value determines the NixOS release with which your system is to be # compatible, in order to avoid breaking some software such as database # servers. You should change this only after NixOS release notes say you # should. system.stateVersion = "18.09"; # Did you read the comment? }