From 1cb23df8a2ff65c4196e4f5ee5bd46301f187869 Mon Sep 17 00:00:00 2001 From: sump pump Date: Thu, 21 May 2020 03:00:50 +0000 Subject: [PATCH] Update bird/bird.conf.tmpl, bird/rpki/known_hosts, bird/rpki/hosts/denco_mane_lixo, README.md files --- README.md | 5 +- bird/bird.conf.tmpl | 91 ++++++++++++++++++++++++--------- bird/rpki/hosts/denco_mane_lixo | 1 + bird/rpki/known_hosts | 0 4 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 bird/rpki/hosts/denco_mane_lixo create mode 100644 bird/rpki/known_hosts diff --git a/README.md b/README.md index 7830f3a..0379a22 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,10 @@ For options we expose here, for information see: https://bird.network.cz/?get_do * `bgp_path_metric`: Enable comparison of path lengths when deciding which BGP route is the best one (`0` or `1`): defaults to `1` * `bgp_aigp`: BGP AIGP state (`enable`, `disable`, or `originate`): defaults to `originate` (see BIRD documentation) - + * `bgp_rpki_retry`: If RPKI cache data cannot be obtained, the time period in seconds between a failed query the next attempt. Defaults to `90`. + * `bgp_rpki_refresh`: How long to wait in seconds before attempting to poll RPKI cache data after the last successful poll. Defaults to `900`. + * `bgp_rpki_expire`: How long to keep any records locally cached before they are deleted. Defaults to `172800` (2 days). + * `bgp_rpki_known_hosts`: The file path for the SSH key `known_hosts` file to use when validating remote RPKI hosts. Defaults to `/etc/bird/rpki/known_hosts` (provided by Lixonet; don't change this unless you need to!). # Setup Prerequisites: diff --git a/bird/bird.conf.tmpl b/bird/bird.conf.tmpl index 54e68c4..33a1338 100644 --- a/bird/bird.conf.tmpl +++ b/bird/bird.conf.tmpl @@ -15,8 +15,38 @@ debug protocols all; # Enable debugging (this should be switched off in prod) router id ${address}; # Custom routing tables -# See: https://bird.network.cz/?get_doc&v=20&f=bird-2.html (recommend; BIRD is neat) -ipv4 table lixonet; +# See: https://bird.network.cz/?get_doc&v=20&f=bird-2.html (recommended read) +ipv4 table lixonet_v4; +roa4 table r4; # ROA RPKI + +# RPKI +# See: https://brooks.sh/2019/11/11/validating-bgp-routes-with-rpki-in-bird/ +protocol rpki { + roa4 { table r4; }; + + {{ range files "bird/rpki/hosts" }} {{ if ne . "${name}" }}# {{.}} + {{ file (print "bird/rpki/" .) }} + {{ end }}{{ end }} + + # Time period in seconds between a failed query the next attempt + retry keep ${bgp_rpki_retry:-90}; + + # Tells how long to wait before attempting to poll the cache + refresh keep ${bgp_rpki_refresh:-900}; + + # How long to keep any records locally cached before they are deleted + # The "refresh" interval will control how often records are refreshed + # and not considered expired. + expire keep ${bgp_rpki_expire:-172800}; + + # Enable SSH transport, disable TCP transport (insecure) + port 22; + transport ssh { + remote public key "${bgp_rpki_known_hosts:-/etc/bird/rpki/known_hosts}"; + #user "lixonet"; + #bird private key ""; + }; +} # Filters # Define a series of filters for Lixonet routing policies: @@ -24,10 +54,24 @@ ipv4 table lixonet; # See: https://gitlab.labs.nic.cz/labs/bird/wikis/BGP_filtering # For syntax docs, see: https://bird.network.cz/?get_doc&v=16&f=bird-5.html +# Returns TRUE if the given prefix is found in a kept RPKI cache. +# Returns FALSE if the given prefix is either, +# - Valid in the cached RPKI list, or +# - RPKI has not yet been established and the route cannot be validated +# From BIRD documentation (https://bird.network.cz/?get_doc&v=20&f=bird-5.html): +# roa_check: Checks the current route (which should be from BGP to +# have AS_PATH argument) in the specified ROA table and returns +# ROA_UNKNOWN if there is no relevant ROA, ROA_VALID if there is +# a matching ROA, or ROA_INVALID if there are some relevant ROAs +# but none of them match. +function is_rpki_invalid_v4 () { + return roa_check(r4, net, bgp_path.last_nonaggregated) = ROA_INVALID; +} + # Returns TRUE if the given tested network is within the global network prefix for # Lixonet. Used to filter networks outside of this range as they are not within # the global mesh network. -function is_lixonet_global() +function is_lixonet_global_v4() { return net ~ [ ${network_address}/${global_prefix:-16}+ ]; } @@ -35,39 +79,39 @@ function is_lixonet_global() # Returns TRUE if the given tested network is within the router network prefix for # Lixonet. Used to filter these routes from BGP as Tinc statically assigns them # for us. Helps prevent a security vulnerability of hijacking another router. -function is_lixonet_router() +function is_lixonet_router_v4() { return net ~ [ ${network_address}/${router_prefix:-24}+ ]; } -function is_own_route() +function is_own_route_v4() { {{ if len "${routes:-}" }}{{ range "$routes" | split "," }}if net ~ [ {{.}}+ ] then return true; {{ end }}{{ end }} return false; } -filter bgp_import_filter +filter bgp_import_filter_v4 { - # TODO: check RPKI here! if source ~ [RTS_STATIC] then reject; # Reject our own routes - if is_lixonet_router() then reject; # Reject poisons - if is_own_route() then reject; # Reject poisons - if is_lixonet_global() then accept; # Accept anything else + if is_rpki_invalid_v4() then reject; # Reject posions + if is_lixonet_router_v4() then reject; # Reject poisons + if is_own_route_v4() then reject; # Reject poisons + if is_lixonet_global_v4() then accept; # Accept anything else reject; # Reject anything else (non-Lixonet) } -filter bgp_export_filter +filter bgp_export_filter_v4 { - if is_lixonet_router() then reject; # Reject poisons - if is_lixonet_global() then accept; # Accept anything else + if is_lixonet_router_v4() then reject; # Reject poisons + if is_lixonet_global_v4() then accept; # Accept anything else reject; # Reject anything else (non-Lixonet) } -filter kernel_export_filter +filter kernel_export_filter_v4 { - if is_own_route() then reject; # Reject poisons - if is_lixonet_global() then accept; # Accept anything else + if is_own_route_v4() then reject; # Reject poisons + if is_lixonet_global_v4() then accept; # Accept anything else reject; # Reject anything else (non-Lixonet) } @@ -77,7 +121,7 @@ filter kernel_export_filter # See how dn42 does it; we're very similar: https://dn42.net/howto/Bird protocol static { ipv4 { - table lixonet; + table lixonet_v4; import all; export none; }; @@ -112,9 +156,9 @@ protocol kernel { # Primary routing table persist; # Don't remove routes on bird shutdown scan time 10; # Scan kernel routing table every 10 seconds ipv4 { - table lixonet; + table lixonet_v4; import none; # Don't try to import any routes from the kernel - export filter kernel_export_filter; # Export everything we are told to the kernel + export filter kernel_export_filter_v4; # Export everything we are told to the kernel }; }; @@ -137,7 +181,7 @@ template bgp lixonet_client { # BGP IPv4 channel settings ipv4 { - table lixonet; + table lixonet_v4; # Always advertise our own local address as a next hop, even in cases where the # current Next Hop attribute should be used unchanged. @@ -155,15 +199,14 @@ template bgp lixonet_client { # Set filters for both exported (sent) and imported (received) BGP prefixes. # This is explicitly required per RFC 8212, at least on export. # See: https://gitlab.labs.nic.cz/labs/bird/commit/3831b619661d08d935fd78656732cd2f339ff811 - export filter bgp_export_filter; - import filter bgp_import_filter; + export filter bgp_export_filter_v4; + import filter bgp_import_filter_v4; }; }; # Neighbors - {{ range files "bird/neighbors" }} {{ if ne . "${name}" }} protocol bgp {{ . }} from lixonet_client { description "Lixonet BGP link from ${address} (ASN: ${asn}) to {{ . }}"; {{ file (print "bird/neighbors/" .) }} -}; {{ end }} {{ end }} +};{{ end }}{{ end }} diff --git a/bird/rpki/hosts/denco_mane_lixo b/bird/rpki/hosts/denco_mane_lixo new file mode 100644 index 0000000..b8f8520 --- /dev/null +++ b/bird/rpki/hosts/denco_mane_lixo @@ -0,0 +1 @@ +remote 172.30.0.8 port 22 diff --git a/bird/rpki/known_hosts b/bird/rpki/known_hosts new file mode 100644 index 0000000..e69de29