Merge branch 'bird' into new-infra

This commit is contained in:
jeltz 2023-01-04 08:05:04 +01:00
commit 7c21275a11
Signed by: jeltz
GPG key ID: 800882B66C0C3326
13 changed files with 686 additions and 6 deletions

16
filter_plugins/enquote.py Normal file
View file

@ -0,0 +1,16 @@
class FilterModule:
def filters(self):
return {
"enquote": enquote,
}
def enquote(string, delimiter='"', escape="\\"):
translation = str.maketrans(
{
delimiter: f"{escape}{delimiter}",
escape: f"{escape}{escape}",
}
)
escaped = string.translate(translation)
return f"{delimiter}{escaped}{delimiter}"

9
filter_plugins/suffix.py Normal file
View file

@ -0,0 +1,9 @@
class FilterModule:
def filters(self):
return {
"suffix": suffix,
}
def suffix(value, suffix):
return value + suffix

4
hosts
View file

@ -127,6 +127,10 @@ radius-fleming.adm.auro.re
dns-1.int.infra.auro.re
isp-1.rtr.infra.auro.re
isp-2.rtr.infra.auro.re
edge-1.rtr.infra.auro.re
edge-2.rtr.infra.auro.re
infra-1.rtr.infra.auro.re
infra-2.rtr.infra.auro.re
dhcp-1.isp.auro.re
dhcp-2.isp.auro.re
radius-fleming-backup.adm.auro.re

194
playbooks/bird.yml Executable file
View file

@ -0,0 +1,194 @@
#!/usr/bin/env ansible-playbook
---
- hosts:
- isp-1.rtr.infra.auro.re
- isp-2.rtr.infra.auro.re
vars:
bird__router_ids:
isp-1.rtr.infra.auro.re: 10.136.0.1
isp-2.rtr.infra.auro.re: 10.136.0.2
bird__router_id: "{{ bird__router_ids[inventory_hostname] }}"
bird__ospf_broadcast_interfaces:
ens20: null
bird__ospf_stub_interfaces:
- client-0
- client-1
- client-2
- client-3
- client-4
bird__radv_interfaces:
client-0:
prefix:
- 2a09:6841::/56
domain_search:
- client-0.isp.auro.re
client-1:
prefix:
- 2a09:6841:0:100::/56
domain_search:
- client-1.isp.auro.re
client-2:
prefix:
- 2a09:6841:0:200::/56
domain_search:
- client-2.isp.auro.re
client-3:
prefix:
- 2a09:6841:0:300::/56
domain_search:
- client-3.isp.auro.re
client-4:
prefix:
- 2a09:6841:0:400::/56
domain_search:
- client-4.isp.auro.re
bird__radv_dns_servers:
- 2a09:6840:128::127
roles:
- bird
- hosts:
- infra-1.rtr.infra.auro.re
- infra-2.rtr.infra.auro.re
vars:
bird__router_ids:
infra-1.rtr.infra.auro.re: 10.203.1.3
infra-2.rtr.infra.auro.re: 10.203.1.4
bird__router_id: "{{ bird__router_ids[inventory_hostname] }}"
bird__ospf_broadcast_interfaces:
ens19: null
bird__ospf_stub_interfaces:
- ens20
- ens21
- ens22
- ens23
- ens1
- ens2
- ens1s3
roles:
- bird
- hosts:
- edge-1.rtr.infra.auro.re
- edge-2.rtr.infra.auro.re
vars:
bird__router_ids:
edge-1.rtr.infra.auro.re: 10.203.1.1
edge-2.rtr.infra.auro.re: 10.203.1.2
bird__asn:
aurore: 43619
crans: 204515
zayo: 8218
viarezo: 212424
bird__orig_prefixes:
aurore:
- 45.66.108.0/22
- 2a09:6840::/29
crans:
- 185.230.76.0/22
- 2a0c:700::/32
viarezo:
- 138.195.144.0/20
- 192.159.121.0/24
- 2a0c:b641:2f0::/44
martians:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 100.64.0.0/10
- 127.0.0.0/8
- 169.254.0.0/16
- 192.0.0.0/24
- 192.0.2.0/24
- 198.18.0.0/15
- 198.51.100.0/24
- 203.0.113.0/24
- 224.0.0.0/4
- 240.0.0.0/4
- ::/128
- ::1/128
- ::ffff:0:0/96
- ::/96
- 100::/64
- 2001:10::/28
- 2001:db8::/32
- fc00::/7
- fe80::/10
- fec0::/10
- ff00::/8
bird__router_id: "{{ bird__router_ids[inventory_hostname] }}"
bird__ospf_broadcast_interfaces:
ens22: null
bird__ospf_stub_networks:
- 0.0.0.0/0
- ::/0
bird__bgp_sessions:
- name: zayo
local:
address:
- 83.167.52.69
- 2001:1b48:2:103::d7:2
as: "{{ bird__asn.aurore }}"
remote:
address:
- 83.167.52.68
- 2001:1b48:2:103::d7:1
as: "{{ bird__asn.zayo }}"
import:
- accept: true
export:
- prefix: "{{ ['aurore', 'crans', 'viarezo']
| map('extract', bird__orig_prefixes)
| flatten }}"
sub: true
accept: true
- accept: false
- name: crans
local:
address:
- 185.230.79.254
- 2a0c:700:28::2
as: "{{ bird__asn.aurore }}"
remote:
address:
- 185.230.79.253
- 2a0c:700:28::1
as: "{{ bird__asn.crans }}"
import:
- prefix: "{{ bird__orig_prefixes.crans }}"
sub: true
accept: true
- accept: false
export:
- accept: true
- name: viarezo
local:
address:
- 192.159.121.134
- 2a0c:b641:2ff::6
as: "{{ bird__asn.aurore }}"
remote:
address:
- 192.159.121.133
- 2a0c:b641:2ff::5
as: "{{ bird__asn.viarezo }}"
import:
- prefix: "{{ bird__orig_prefixes.martians }}"
accept: false
- prefix: "{{ bird__orig_prefixes.viarezo }}"
sub: true
negate: true
local_pref: 50
- accept: true
export:
- prefix: "{{ bird__orig_prefixes.aurore }}"
as_prepend:
asn: "{{ bird__asn.aurore }}"
size: 3
- accept: true
bird__static_unreachable:
- 45.66.108.0/22
- 2a09:6840::/29
roles:
- bird
...

View file

@ -7,6 +7,10 @@
- dhcp-2.isp.auro.re
- isp-1.rtr.infra.auro.re
- isp-2.rtr.infra.auro.re
- edge-1.rtr.infra.auro.re
- edge-2.rtr.infra.auro.re
- infra-1.rtr.infra.auro.re
- infra-2.rtr.infra.auro.re
vars:
# TODO: netbox
ifupdown2__hosts:
@ -115,6 +119,11 @@
- 2a09:6840:128::255/56
- 10.128.0.255/16
ens19: null
ens20:
forward: true
addresses:
- 2a09:6840:136:0:1::1/56
- 10.136.0.1/16
clients:
bridge_vlan_aware: true
bridge_ports:
@ -158,6 +167,11 @@
- 2a09:6840:128::158/56
- 10.128.0.158/16
ens19: null
ens20:
forward: true
addresses:
- 2a09:6840:136:0:2::1/56
- 10.136.0.2/16
clients:
bridge_vlan_aware: true
bridge_ports:
@ -189,6 +203,88 @@
vlan_id: 1004
vlan_raw_device: clients
ipv6_addrgen: false
edge-1.rtr.infra.auro.re:
ens18:
gateways:
- 2a09:6840:128::254
- 10.128.0.254
addresses:
- 2a09:6840:128::186/56
- 10.128.0.186/16
ens19: null # crans
ens20: null # vr
ens21: null # zayo
ens22: # backbone
addresses:
- 2a09:6840:203:1:1::1/64
- 10.203.1.1/16
edge-2.rtr.infra.auro.re:
ens18:
gateways:
- 2a09:6840:128::254
- 10.128.0.254
addresses:
- 2a09:6840:128::228/56
- 10.128.0.228/16
ens19: null # crans
ens20: null # vr
ens21: null # zayo
ens22: # backbone
addresses:
- 2a09:6840:203:1:2::1/64
- 10.203.1.2/16
infra-1.rtr.infra.auro.re:
ens18:
gateways:
- 2a09:6840:128::254
- 10.128.0.254
addresses:
- 2a09:6840:128::2:76/56
- 10.128.2.76/16
ens19:
addresses:
- 2a09:6840:1:3::1/64
- 10.203.1.3/16
ens20:
ipv6_addrgen: false
ens21:
ipv6_addrgen: false
ens22:
ipv6_addrgen: false
ens23:
ipv6_addrgen: false
ens1:
ipv6_addrgen: false
ens2:
ipv6_addrgen: false
enp1s3:
ipv6_addrgen: false
infra-2.rtr.infra.auro.re:
ens18:
gateways:
- 2a09:6840:128::254
- 10.128.0.254
addresses:
- 2a09:6840:128::2:27/56
- 10.128.2.27/16
ens19:
addresses:
- 2a09:6840:1:4::1/64
- 10.203.1.4/16
ens20:
ipv6_addrgen: false
ens21:
ipv6_addrgen: false
ens22:
ipv6_addrgen: false
ens23:
ipv6_addrgen: false
ens1:
ipv6_addrgen: false
ens2:
ipv6_addrgen: false
enp1s3:
ipv6_addrgen: false
ifupdown2__interfaces: "{{ ifupdown2__hosts[inventory_hostname] }}"
roles:
- ifupdown2
@ -200,6 +296,10 @@
- dhcp-2.isp.auro.re
- isp-1.rtr.infra.auro.re
- isp-2.rtr.infra.auro.re
- edge-1.rtr.infra.auro.re
- edge-2.rtr.infra.auro.re
- infra-1.rtr.infra.auro.re
- infra-2.rtr.infra.auro.re
vars:
resolvconf__nameservers:
- 2a09:6840:128::127

View file

@ -5,27 +5,87 @@
- isp-2.rtr.infra.auro.re
vars:
keepalived__virtual_router_id: 80
keepalived__interface: ens18
keepalived__interface: ens20
keepalived__virtual_addresses:
client-0:
- 100.64.0.1/27
- 2a09:6841::/56
- 2a09:6841::1/56
- fe80::1/10
client-1:
- 100.64.0.33/27
- 2a09:6841:0:100::/56
- 2a09:6841:0:100::1/56
- fe80::1/10
client-2:
- 100.64.0.65/27
- 2a09:6841:0:100::/56
- 2a09:6841:0:200::1/56
- fe80::1/10
client-3:
- 100.64.0.97/27
- 2a09:6841:0:200::/56
- 2a09:6841:0:300::1/56
- fe80::1/10
client-4:
- 100.64.0.129/27
- 2a09:6841:0:300::/56
- 2a09:6841:0:400::1/56
- fe80::1/10
roles:
- keepalived
- hosts:
- edge-1.rtr.infra.auro.re
- edge-2.rtr.infra.auro.re
vars:
keepalived__virtual_router_id: 81
keepalived__interface: ens22
keepalived__virtual_addresses:
ens19:
- 185.230.79.254/29
- 2a0c:700:28::2/64
- fe80::1/10
ens20:
- 192.159.121.134/30
- 2a0c:b641:2ff::6/126
- fe80::1/10
ens21:
- 83.167.52.69/31
- 2001:1b48:2:103::d7:2/126
- fe80::1/10
roles:
- keepalived
- hosts:
- infra-1.rtr.infra.auro.re
- infra-2.rtr.infra.auro.re
vars:
keepalived__virtual_router_id: 82
keepalived__interface: ens19
keepalived__virtual_addresses:
ens20:
- 10.204.0.1/16
- 2a09:6840:204::1/64
- fe80::1/10
ens21:
- 10.205.0.1/16
- 2a09:6840:205::1/64
- fe80::1/10
ens22:
- 10.206.0.1/16
- 2a09:6840:206::1/64
- fe80::1/10
ens23:
- 10.207.0.1/16
- 2a09:6840:207::1/64
- fe80::1/10
ens1:
- 10.208.0.1/16
- 2a09:6840:208::1/64
- fe80::1/10
ens2:
- 10.209.0.1/16
- 2a09:6840:209::1/64
- fe80::1/10
enp1s3:
- 10.210.0.1/16
- 2a09:6840:210::1/64
- fe80::1/10
roles:
- keepalived

View file

@ -0,0 +1,15 @@
---
bird__ospf_stub_interfaces: []
bird__ospf_stub_networks: []
bird__ospf_broadcast_interfaces: {}
bird__ospf_hello: 2
bird__ospf_retransmit: 5
bird__ospf_wait: 10
bird__ospf_dead: 20
bird__radv_interfaces: {}
bird__radv_dns_servers: []
bird__radv_max_interval: 5
bird__static_unreachable: []
bird__bgp_sessions: []
bird__prometheus_listen_address: 0.0.0.0:9324
...

View file

@ -0,0 +1,11 @@
---
- name: Reload bird
systemd:
name: bird.service
state: reloaded
- name: Restart prometheus-bird-exporter
systemd:
name: prometheus-bird-exporter.service
state: restarted
...

40
roles/bird/tasks/main.yml Normal file
View file

@ -0,0 +1,40 @@
---
- name: Install bird
apt:
name:
- bird2
- prometheus-bird-exporter
- name: Configure bird
template:
src: bird.conf.j2
dest: /etc/bird/bird.conf
owner: root
group: bird
mode: u=rw,g=r,o=
notify:
- Reload bird
- name: Configure prometheus-bird-exporter
template:
src: prometheus-bird-exporter.j2
dest: /etc/default/prometheus-bird-exporter
owner: root
group: root
mode: u=rw,g=r,o=
notify:
- Restart prometheus-bird-exporter
- name: Enable and start bird
systemd:
name: bird.service
state: started
enabled: true
- name: Enable and start prometheus-bird-exporter
systemd:
name: prometheus-bird-exporter.service
state: started
enabled: true
...

View file

@ -0,0 +1,209 @@
{{ ansible_managed | comment }}
log syslog all;
router id {{ bird__router_id }};
protocol device {
scan time 10;
}
protocol direct {
ipv4;
ipv6;
}
protocol kernel kernel4 {
ipv4 {
import all;
export where source !~ [ RTS_DEVICE, RTS_STATIC ];
};
}
protocol kernel kernel6 {
ipv6 {
import all;
export where source !~ [ RTS_DEVICE, RTS_STATIC ];
};
}
{% if bird__static_unreachable | ansible.utils.ipv4 %}
protocol static unreachable4 {
ipv4 {
import all;
};
{% for route in bird__static_unreachable | ansible.utils.ipv4 %}
route {{ route }} unreachable;
{% endfor %}
}
{% endif %}
{% if bird__static_unreachable | ansible.utils.ipv6 %}
protocol static unreachable6 {
ipv6 {
import all;
};
{% for route in bird__static_unreachable | ansible.utils.ipv6 %}
route {{ route }} unreachable;
{% endfor %}
}
{% endif %}
{% if bird__ospf_broadcast_interfaces %}
protocol ospf v2 ospf4 {
ipv4 {
import all;
export where source ~ [ RTS_STATIC, RTS_DEVICE ];
};
area 0 {
{% for network in bird__ospf_stub_networks | ansible.utils.ipv4 %}
stubnet {{ network }};
{% endfor %}
{% for name, iface in bird__ospf_broadcast_interfaces.items() %}
interface {{ name | enquote }} {
type broadcast;
hello {{ iface.hello | default(bird__ospf_hello) | int }};
retransmit {{ iface.retransmit
| default(bird__ospf_retransmit)
| int }};
wait {{ iface.wait | default(bird__ospf_wait) | int }};
dead {{ iface.dead | default(bird__ospf_dead) | int }};
};
{% endfor %}
{% for name in bird__ospf_stub_interfaces %}
interface {{ name | enquote }} {
stub;
};
{% endfor %}
};
}
{% endif %}
{% if bird__ospf_broadcast_interfaces %}
protocol ospf v3 ospf6 {
ipv6 {
import all;
export where source ~ [ RTS_STATIC, RTS_DEVICE ];
};
area 0 {
{% for network in bird__ospf_stub_networks | ansible.utils.ipv6 %}
stubnet {{ network }};
{% endfor %}
{% for name, iface in bird__ospf_broadcast_interfaces.items() %}
interface {{ name | enquote }} {
type broadcast;
hello {{ iface.hello | default(bird__ospf_hello) | int }};
retransmit {{ iface.retransmit
| default(bird__ospf_retransmit)
| int }};
wait {{ iface.wait | default(bird__ospf_wait) | int }};
dead {{ iface.dead | default(bird__ospf_dead) | int }};
};
{% endfor %}
{% for name in bird__ospf_stub_interfaces %}
interface {{ name | enquote }} {
stub;
};
{% endfor %}
};
}
{% endif %}
{% macro bird_filter(filter, last) %}
{% if filter.as_prepend is defined %}
{% for _ in range(filter.as_prepend.size) %}
bgp_path.prepend({{ filter.as_prepend.asn }});
{% endfor %}
{% endif %}
{% if filter.local_pref is defined %}
bgp_local_pref = {{ filter.local_pref }};
{% endif %}
{% if filter.accept is defined %}
{{ filter.accept | ternary("accept", "reject") }};
{% endif %}
{% endmacro %}
{% for session in bird__bgp_sessions %}
{% for version in [4, 6] %}
{% for direction in ["import", "export"] %}
filter bgp{{ version }}_{{ direction }}_{{ session.name }} {
{% for filter in session[direction] %}
{% if filter.prefix | default([]) %}
{% set op =
filter.negate
| default(False)
| ternary("!~", "~") %}
{% set networks =
filter.prefix
| default([])
| ansible.utils.ipaddr(version=version)
| map("suffix", filter.sub
| default(False)
| ternary("+", "")) %}
{% if networks %}
if net {{ op }} [ {{ networks | join(", ") }} ] then {
{{ bird_filter(filter) | indent(8) }}
}
{% endif %}
{% else %}
{{ bird_filter(filter) | indent(4) }}
{% endif %}
{% endfor %}
}
{% endfor %}
{% endfor %}
{% endfor %}
{% for session in bird__bgp_sessions %}
{% for local_address in session.local.address %}
{% set version =
local_address
| ansible.utils.ipaddr(query="version") %}
{% set remote_address =
session.remote.address
| ansible.utils.ipaddr(version=version)
| first %}
protocol bgp bgp{{ version }}_{{ session.name }} {
local {{ local_address }} as {{ session.local.as }};
neighbor {{ remote_address }} as {{ session.remote.as }};
{{ "ipv4" if version == 4 else "ipv6" }} {
import filter bgp{{ version }}_import_{{ session.name }};
export filter bgp{{ version }}_export_{{ session.name }};
};
}
{% endfor %}
{% endfor %}
{% if bird__radv_interfaces %}
protocol radv {
{% for name, iface in bird__radv_interfaces.items() %}
interface {{ name | enquote }} {
max ra interval {{ bird__radv_max_interval | int }};
{% for prefix in iface.prefix | default([]) %}
prefix {{ prefix | ipaddr }};
{% endfor %}
{% for domain in iface.domain_search | default([]) %}
dnssl {{ domain | enquote }};
{% endfor %}
};
{% endfor %}
{% for address in bird__radv_dns_servers %}
rdnss {{ address | ipaddr }};
{% endfor %}
}
{% endif %}

View file

@ -0,0 +1,3 @@
{{ ansible_managed | comment }}
ARGS="-format.new -bird.v2 -web.listen-address {{ bird__prometheus_listen_address }}"

View file

@ -1,5 +1,6 @@
---
keepalived__virtual_addresses: {}
keepalived__virtual_routes: {}
keepalived__notify_master: []
keepalived__notify_backup: []
keepalived__notify_fault: []

View file

@ -55,6 +55,15 @@ vrrp_instance instance_v4 {
{{ address }} dev {{ dev }}
{% endif %}
{% endfor %}
{% endfor %}
}
virtual_routes {
{% for dev, addresses in keepalived__virtual_routes.items() %}
{% for address in addresses %}
{% if address | ansible.utils.ipv4 %}
{{ address }} dev {{ dev }}
{% endif %}
{% endfor %}
{% endfor %}
}
{% if not (ipv4_enabled and ipv6_enabled) %}
@ -81,6 +90,15 @@ vrrp_instance instance_v6 {
{{ address }} dev {{ dev }}
{% endif %}
{% endfor %}
{% endfor %}
}
virtual_routes {
{% for dev, addresses in keepalived__virtual_routes.items() %}
{% for address in addresses %}
{% if address | ansible.utils.ipv6 %}
{{ address }} dev {{ dev }}
{% endif %}
{% endfor %}
{% endfor %}
}
{% if not (ipv4_enabled and ipv6_enabled) %}