251 lines
9.6 KiB
Cheetah
251 lines
9.6 KiB
Cheetah
# Lixonet BIRD configuration
|
|
# This is a templated file that automatically generates values at configuration time
|
|
# If you edit this file, it will be overwritten. Changes to the general structure of
|
|
# this configuration file that should be persisted should be committed to Git.
|
|
# For BIRD 2.0 configuration reference, see:
|
|
# https://bird.network.cz/?get_doc&f=bird.html&v=20
|
|
# For a great example configuration file, see:
|
|
# https://fossies.org/linux/bird/doc/bird.conf.example
|
|
|
|
# Global variables
|
|
# See: https://bird.network.cz/?get_doc&v=20&f=bird-3.html#ss3.2
|
|
|
|
log stderr all; # Using docker; defer logging to stderr (to Docker logs)
|
|
#debug protocols all; # Enable debugging (this should be switched off in prod)
|
|
router id ${tinc_peer_address};
|
|
timeformat protocol iso long; # See: https://github.com/czerwonk/bird_exporter
|
|
|
|
# Custom routing tables
|
|
# See: https://bird.network.cz/?get_doc&v=20&f=bird-2.html (recommended read)
|
|
ipv4 table ${netname:-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" }} # {{.}}
|
|
# {{ file (print "bird/rpki/hosts/" .) }}
|
|
# {{ 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};
|
|
# }
|
|
|
|
# Filters
|
|
# Define a series of filters for Lixonet routing policies:
|
|
# - Cannot advertise a route which is in the router subnet: typically 172.x.0.0/24
|
|
# 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 the exact global network prefix for
|
|
# Lixonet. Used to filter the "unreachable" static route we typically static.
|
|
function is_exact_lixonet_global_v4()
|
|
{
|
|
return net ~ [ ${network_address}/${global_prefix:-16} ];
|
|
}
|
|
|
|
# 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_v4()
|
|
{
|
|
return net ~ [ ${network_address}/${global_prefix:-16}+ ];
|
|
}
|
|
|
|
# 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_v4()
|
|
{
|
|
return net ~ [ ${network_address}/${router_prefix:-24}+ ];
|
|
}
|
|
|
|
function is_own_route_v4()
|
|
{
|
|
{{ if len "${bgp_routes:-}" }}{{ range "$bgp_routes" | split "," }}if net ~ [ {{.}}+ ] then return true;
|
|
{{ end }}{{ end }}
|
|
return false;
|
|
}
|
|
|
|
function is_wireguard_route_v4()
|
|
{
|
|
{{ if len "${wg_routes:-}" }}{{ range "$wg_routes" | split "," }}if net ~ [ {{.}}+ ] then return true;
|
|
{{ end }}{{ end }}
|
|
return false;
|
|
}
|
|
|
|
filter bgp_import_filter_v4
|
|
{
|
|
if source ~ [RTS_STATIC] then reject; # Reject our own routes
|
|
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_v4
|
|
{
|
|
if is_lixonet_router_v4() then reject; # Reject poisons
|
|
if is_exact_lixonet_global_v4() then reject; # Reject the unreachable route
|
|
if is_lixonet_global_v4() then accept; # Accept anything else
|
|
reject; # Reject anything else (non-Lixonet)
|
|
}
|
|
|
|
# In some cases, like WireGuard, we can be a peer to a client which is
|
|
# available over another "adjacent" VPN layer. In these cases, allow
|
|
# importing routes that are added to the kernel which fall under the
|
|
# Wireguard layer
|
|
filter kernel_import_filter_v4
|
|
{
|
|
if is_own_route_v4() then reject; # Reject unexpected routes
|
|
if is_wireguard_route_v4() then accept; # Accept WireGuard routes
|
|
reject; # Reject anything else
|
|
}
|
|
|
|
filter kernel_export_filter_v4
|
|
{
|
|
#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)
|
|
}
|
|
|
|
# Static routes
|
|
# Define propagated routes here from the lixonet.conf "routes" variable
|
|
# Attached to the above "lixonet" routing table; "provide" these routes into it
|
|
# See how dn42 does it; we're very similar: https://dn42.net/howto/Bird
|
|
protocol static {
|
|
ipv4 {
|
|
table ${netname:-lixonet}_v4;
|
|
import all;
|
|
export none;
|
|
};
|
|
|
|
# Announce the whole network as unreachable; this returns packets that reach
|
|
# this router as unreachable (ICMP type=3, code=0) if no more specific route
|
|
# is defined for the network subnet
|
|
route ${network_address}/${global_prefix:-16} unreachable;
|
|
|
|
# Announced networks
|
|
{{ if len "${bgp_routes:-}" }}{{ range "$bgp_routes" | split "," }}route {{.}} via ${internal_gateway:-\"lo\"};
|
|
{{ end }}{{ end }}
|
|
};
|
|
|
|
# Device
|
|
# See: https://bird.network.cz/?get_doc&v=20&f=bird-6.html#ss6.4
|
|
# This controls which interfaces BGP, etc. will bind to for communication
|
|
# This prevents BGP from listening on eth0/off-network
|
|
protocol device {
|
|
scan time 10; # Scan the interfaces often
|
|
interface "${netname:-lixonet}" {
|
|
preferred ${tinc_peer_address};
|
|
};
|
|
};
|
|
|
|
# Direct (unnecessary for Lixonet)
|
|
# See: https://bird.network.cz/?get_doc&v=20&f=bird-6.html#ss6.5
|
|
# Disable automatically generating direct routes to all network interfaces.
|
|
protocol direct {
|
|
disabled; # Disable by default
|
|
};
|
|
|
|
# Kernel routing table
|
|
# See: https://bird.network.cz/?get_doc&v=20&f=bird.html#toc6.6
|
|
protocol kernel { # Primary routing table
|
|
learn; # Learn alien routes from the kernel
|
|
persist; # Don't remove routes on bird shutdown
|
|
scan time 10; # Scan kernel routing table every 10 seconds
|
|
graceful restart;
|
|
ipv4 {
|
|
table ${netname:-lixonet}_v4;
|
|
import filter kernel_import_filter_v4; # Import anything we allow from the kernel
|
|
export filter kernel_export_filter_v4; # Export everything we are told to the kernel
|
|
};
|
|
};
|
|
|
|
# BFD
|
|
protocol bfd {
|
|
interface "${netname:-lixonet}" {
|
|
min rx interval 1 s;
|
|
min tx interval 1 s;
|
|
idle tx interval 5 s;
|
|
multiplier 5;
|
|
};
|
|
};
|
|
|
|
# BGP (primary Lixonet routing protocol)
|
|
# This is a template to use when connecting to other BGP clients on the EE network
|
|
# This template is applied to ALL neighbors, so consider these global settings that
|
|
# apply to all neighbors. See "Neighbors" section of this configuration for
|
|
# individual neighbor configurations where per-neighbor configurations (such as their
|
|
# ASN) are applied.
|
|
template bgp lixonet_client {
|
|
local as ${bgp_asn}; # Local AS advertised to peers
|
|
|
|
source address ${tinc_peer_address}; # What local IP address we use for any outbound TCP
|
|
# connections on port 179
|
|
|
|
path metric ${bgp_path_metric:-1}; # 1 = Prefer routes with shorter paths (like Cisco does)
|
|
|
|
# Turn on BFD (bidirectional forwarding detection)
|
|
bfd on;
|
|
|
|
# BGP channels
|
|
# See: Channel configuration (BIRD BGP configuration) and the table shown there.
|
|
|
|
# BGP IPv4 channel settings
|
|
ipv4 {
|
|
table ${netname:-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.
|
|
# Reason: tinc NEEDS this, otherwise Layer3 inter-routing on the mesh will be broken
|
|
next hop self ebgp;
|
|
|
|
# aigp (see: http://www.rfc-editor.org/info/rfc7311)
|
|
# Lixonet default: originate AIGP
|
|
# This not only allows AIGP attribute propagation, but also new AIGP attributes are
|
|
# automatically attached to non-BGP routes with valid IGP metric (e.g. ospf_metric1)
|
|
# as they are exported to the BGP session.
|
|
# Thank-you, BIRD <3 - mane and nurd
|
|
aigp ${bgp_aigp:-originate};
|
|
|
|
# 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_v4;
|
|
import filter bgp_import_filter_v4;
|
|
};
|
|
};
|
|
|
|
# Neighbors
|
|
{{ range files "bird/peers" }} {{ if ne . "${tinc_peer_name}" }}
|
|
protocol bgp {{ . }} from lixonet_client {
|
|
description "Lixonet BGP link to {{ . }}";
|
|
{{ include (print "bird/peers/" .) }}
|
|
};{{ end }}{{ end }}
|