262 lines
7.9 KiB
Django/Jinja
262 lines
7.9 KiB
Django/Jinja
# {{ ansible_managed }}
|
|
|
|
router id {{ bird_router_id }};
|
|
|
|
|
|
protocol device {
|
|
scan time 10;
|
|
}
|
|
|
|
protocol kernel {
|
|
scan time 5;
|
|
|
|
ipv6 {
|
|
import none;
|
|
export filter {
|
|
{% if bird_prefsrc is defined %}
|
|
krt_prefsrc = {{ bird_prefsrc }};
|
|
{% endif %}
|
|
if source = RTS_BGP then accept;
|
|
if source = RTS_STATIC then accept;
|
|
if source = RTS_DEVICE then reject;
|
|
accept;
|
|
};
|
|
};
|
|
}
|
|
|
|
protocol kernel {
|
|
scan time 5;
|
|
|
|
ipv4 {
|
|
import none;
|
|
export filter {
|
|
{% if bird_prefsrc_v4 is defined %}
|
|
krt_prefsrc = {{ bird_prefsrc_v4 }};
|
|
{% endif %}
|
|
if source = RTS_BGP then accept;
|
|
if source = RTS_STATIC then accept;
|
|
if source = RTS_DEVICE then reject;
|
|
accept;
|
|
};
|
|
};
|
|
}
|
|
|
|
protocol static {
|
|
{% for net in bird_bgp_advertised_networks %}
|
|
route {{ net }} reject;
|
|
{% endfor %}
|
|
|
|
ipv6 {
|
|
import all;
|
|
export none;
|
|
};
|
|
}
|
|
|
|
protocol static {
|
|
{% for net in bird_bgp_advertised_networks_v4 | default([]) %}
|
|
route {{ net }} reject;
|
|
{% endfor %}
|
|
ipv4 {
|
|
import all;
|
|
export none;
|
|
};
|
|
}
|
|
|
|
{%if bird_ospf_interfaces | default([]) | length > 0%}
|
|
############################################
|
|
# _|_| _|_|_| _|_|_| _|_|_|_| #
|
|
# _| _| _| _| _| _| #
|
|
# _| _| _|_| _|_|_| _|_|_| #
|
|
# _| _| _| _| _| #
|
|
# _|_| _|_|_| _| _| #
|
|
############################################
|
|
|
|
# Filter to export all direct and bgp routes into OSPF
|
|
filter export_all_OSPF {
|
|
if ( source = RTS_DEVICE ) then accept;
|
|
if ( source = RTS_STATIC_DEVICE ) then accept;
|
|
if ( source = RTS_STATIC ) then accept;
|
|
if ( source = RTS_BGP ) then accept;
|
|
reject;
|
|
}
|
|
|
|
protocol ospf v3 ospf6 {
|
|
ipv6 {
|
|
{% if bird_ospf_export_all | default(false) %}
|
|
export filter export_all_OSPF;
|
|
{% endif %}
|
|
};
|
|
area 0 {
|
|
{%for iface in bird_ospf_interfaces%}
|
|
interface "{{ iface.name }}" {
|
|
{%if iface.stub | default(false)%}
|
|
stub;
|
|
{%endif%}
|
|
};
|
|
{%endfor%}
|
|
};
|
|
}
|
|
{%endif%}
|
|
|
|
|
|
{% if bird_bgp_neighbors | default([]) | length > 0%}
|
|
###################################
|
|
# _|_|_| _|_|_| _|_|_| #
|
|
# _| _| _| _| _| #
|
|
# _|_|_| _| _|_| _|_|_| #
|
|
# _| _| _| _| _| #
|
|
# _|_|_| _|_|_| _| #
|
|
###################################
|
|
define OWNNETSET = [{{ bird_bgp_advertised_networks | join(', ') }}];
|
|
define OWNNETSET_v4 = [{{ bird_bgp_advertised_networks_v4 | default([]) | join(', ') }}];
|
|
define OWNASN = {{ bird_bgp_local_asn }};
|
|
|
|
function is_self_net() {
|
|
if net ~ OWNNETSET then return true;
|
|
if net ~ OWNNETSET_v4 then return true;
|
|
return false;
|
|
}
|
|
|
|
function has_private_asn() {
|
|
# Check if the AS path contains any private ASN
|
|
if (bgp_path ~ [64512..65534]) || (bgp_path ~ [4200000000..4294967294]) then {
|
|
print "Rejecting route with private ASN in AS path: ", bgp_path;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function is_reserved_net() {
|
|
# ULA
|
|
if net ~ fc00::/7 then return true;
|
|
# Link-local
|
|
if net ~ fe80::/10 then return true;
|
|
# Documentation
|
|
if net ~ 2001:db8::/32 then return true;
|
|
# Discard
|
|
if net ~ 100::/64 then return true;
|
|
# Orchid
|
|
if net ~ 2001:20::/28 then return true;
|
|
|
|
# IPv4
|
|
if net ~ 0.0.0.0/8 then return true;
|
|
if net ~ 10.0.0.0/8 then return true;
|
|
if net ~ 100.64.0.0/10 then return true;
|
|
if net ~ 127.0.0.0/8 then return true;
|
|
if net ~ 169.254.0.0/16 then return true;
|
|
if net ~ 172.16.0.0/12 then return true;
|
|
if net ~ 192.0.0.0/24 then return true;
|
|
if net ~ 192.0.2.0/24 then return true;
|
|
if net ~ 192.88.99.0/24 then return true;
|
|
if net ~ 192.168.0.0/16 then return true;
|
|
if net ~ 198.18.0.0/15 then return true;
|
|
if net ~ 198.51.100.0/24 then return true;
|
|
if net ~ 203.0.113.0/24 then return true;
|
|
if net ~ 224.0.0.0/4 then return true;
|
|
if net ~ 233.252.0.0/24 then return true;
|
|
if net ~ 240.0.0.0/4 then return true;
|
|
if net ~ 255.255.255.255/32 then return true;
|
|
return false;
|
|
}
|
|
|
|
{%for peer in bird_bgp_neighbors%}
|
|
# {{ peer.name }}
|
|
{% set peer_name = peer.name | lower | regex_replace('[\s\.\-\$%&/()=]', '_') %}
|
|
|
|
filter {{ peer_name }}_BGP_IMPORT {
|
|
# don't re-import networks announced by ourself
|
|
if is_self_net() then reject;
|
|
{% if not (peer.allow_reserved_networks | default(bird_bgp_allow_reserved_networks | default(false))) %}
|
|
# don't import reserved networks
|
|
if is_reserved_net() then reject;
|
|
{% endif %}
|
|
# never accept routes more specific than /{{ peer.min_pref_len | default(bird_bgp_min_pref_len | default(48)) }}
|
|
if net.len > {{ peer.min_pref_len | default(bird_bgp_min_pref_len | default(48)) }} then reject;
|
|
{% if not (peer.allow_private_asn | default(bird_bgp_allow_private_asn | default(false))) %}
|
|
# prevent importing paths with private ASNs
|
|
if has_private_asn() then reject;
|
|
{% endif %}
|
|
{% if (peer.max_as_path_length is defined) or (bird_bgp_max_as_path_length is defined) %}
|
|
if bgp_path.len > {{ peer.max_as_path_length | default(bird_bgp_max_as_path_length) }} then reject;
|
|
{% endif %}
|
|
{% if (peer.restrict_prefixes | default([]) | length > 0) %}
|
|
if net !~ [{{ peer.restrict_prefixes | join(', ') }}] then reject;
|
|
{% endif %}
|
|
accept;
|
|
}
|
|
|
|
# export rules for {{ peer_name }}
|
|
filter {{ peer_name }}_ALLOWED_BGP {
|
|
{% for n in range(peer.as_prepend | default(1)) %}
|
|
bgp_path.prepend({{ peer.local_asn | default('OWNASN') }});
|
|
{% endfor %}
|
|
{% if not (peer.allow_reserved_networks | default(bird_bgp_allow_reserved_networks | default(false))) %}
|
|
# don't export reserved networks
|
|
if is_reserved_net() then reject;
|
|
{% endif %}
|
|
# never send routes more specific than /{{ peer.min_pref_len | default(bird_bgp_min_pref_len | default(48)) }}
|
|
if net.len > {{ peer.min_pref_len | default(bird_bgp_min_pref_len | default(48)) }} then reject;
|
|
{% if not (peer.allow_private_asn | default(bird_bgp_allow_private_asn | default(false))) %}
|
|
# prevent exposing paths with private ASNs
|
|
if has_private_asn() then reject;
|
|
{% endif %}
|
|
if is_self_net() then accept;
|
|
{% if (peer.redistribute_learned | default(false)) %}
|
|
# redistribute all other routes learned from BGP
|
|
if source = RTS_BGP then {
|
|
{% if not (peer.redistribute_reserved | default(false)) %}
|
|
# don't redistribute reserved networks
|
|
if is_reserved_net() then reject;
|
|
|
|
{% endif %}
|
|
{% for n in range(peer.redistribute_prepend | default(0)) %}
|
|
bgp_path.prepend({{ peer.local_asn | default('OWNASN') }});
|
|
{% endfor %}
|
|
accept;
|
|
}
|
|
{% endif %}
|
|
reject;
|
|
}
|
|
protocol bgp {{ peer_name }} {
|
|
local {{ peer.local_ip }} as {{ peer.local_asn | default('OWNASN') }};
|
|
neighbor {{ peer.neighbor_ip }} as {{ peer.neighbor_asn }};
|
|
description "{{ peer.description | default(peer.name) }}";
|
|
{% if peer.password is defined %}
|
|
password "{{ peer.password }}";
|
|
{% endif %}
|
|
{% if peer.metric is defined %}
|
|
path metric {{ peer.metric }};
|
|
{% endif %}
|
|
|
|
{% if peer.ipv4 | default(false) == true %}
|
|
ipv4 {
|
|
import filter {{ peer_name }}_BGP_IMPORT;
|
|
export filter {{ peer_name }}_ALLOWED_BGP;
|
|
{% if peer.import_limit | default(1000) != false %}
|
|
import limit {{ peer.import_limit | default(1000) }} action block;
|
|
{% endif %}
|
|
next hop {{ ('address ' + peer.next_hop) if peer.next_hop is defined else 'self' }};
|
|
};
|
|
{% else %}
|
|
ipv6 {
|
|
import filter {{ peer_name }}_BGP_IMPORT;
|
|
export filter {{ peer_name }}_ALLOWED_BGP;
|
|
{% if peer.import_limit | default(1000) != false %}
|
|
import limit {{ peer.import_limit | default(1000) }} action block;
|
|
{% endif %}
|
|
next hop {{ ('address ' + peer.next_hop) if peer.next_hop is defined else 'self' }};
|
|
};
|
|
{% endif %}
|
|
}
|
|
{%endfor%}
|
|
|
|
|
|
# TODO: roa with routinator...
|
|
|
|
# roa4 table dn42_roa;
|
|
# protocol static {
|
|
# roa4 { table dn42_roa; };
|
|
# include "/etc/bird/roa_dn42.conf";
|
|
# };
|
|
{% endif %}
|