diff --git a/group_vars/all/ifupdown2.yml b/group_vars/all/ifupdown2.yml index e9e4576..b4949f8 100644 --- a/group_vars/all/ifupdown2.yml +++ b/group_vars/all/ifupdown2.yml @@ -7,9 +7,9 @@ ifupdown2__gateways: int: - 2a09:6840:206::1 - 10.206.0.1 - pub: - - 2a09:6840:111::254 - - 45.66.111.254 + ext: + - 2a09:6840:211::1 + - 10.211.0.1 monit: - 2a09:6840:204::1 - 10.204.0.1 diff --git a/group_vars/infra/bird.yml b/group_vars/infra/bird.yml index 44282e5..3529ec8 100644 --- a/group_vars/infra/bird.yml +++ b/group_vars/infra/bird.yml @@ -57,4 +57,28 @@ bird__bgp: - pref_src: "{{ bird__pref_src_addr }}" - accept export: reject + wg1: + local: + address: "{{ bird__bgp_addr.vpn }}" + as: "{{ bird__as.aurore }}" + neighbor: + address: + - 2a09:6840:213::1:3 + - 10.213.1.3 + as: "{{ bird__as.aurore }}" + rr_cluster_client: 10.203.1.1 + import: reject + export: accept + wg2: + local: + address: "{{ bird__bgp_addr.vpn }}" + as: "{{ bird__as.aurore }}" + neighbor: + address: + - 2a09:6840:213::1:4 + - 10.203.1.4 + as: "{{ bird__as.aurore }}" + rr_cluster_client: 10.203.1.1 + import: reject + export: accept ... diff --git a/group_vars/infra/firewall.yml b/group_vars/infra/firewall.yml index 9289370..a449ae4 100644 --- a/group_vars/infra/firewall.yml +++ b/group_vars/infra/firewall.yml @@ -104,7 +104,13 @@ firewall__zones: - 10.128.0.150 firewall__input: - - src: back + - iif: + - back0 # FIXME link-local + - vpn0 + verdict: accept + - src: + - back + - vpn verdict: accept - src: monit protocols: diff --git a/group_vars/vpn/bird.yml b/group_vars/vpn/bird.yml new file mode 100644 index 0000000..b63fd68 --- /dev/null +++ b/group_vars/vpn/bird.yml @@ -0,0 +1,58 @@ +--- +bird__kernel: + kernel: + learn: true + import: accept + export: accept + vrf: + import: reject + export: accept + table: wg + kernel: "{{ iproute2__custom_protos.wireguard }}" + +bird__ospf: + limits: + import: 4000 + export: 4000 + table: wg + import: accept + export: + protos: + - kernel + - wireguard + areas: + 1: + broadcast: + - vpn0 + +bird__tables: + - wg + +bird__bgp: + infra1: + local: + address: "{{ bird__bgp_addr.vpn }}" + as: "{{ bird__as.aurore }}" + neighbor: + address: + - 2a09:6840:213::1:1 + - 10.213.1.1 + as: "{{ bird__as.aurore }}" + table: wg + import: accept + export: reject + next_hop_self: true + infra2: + local: + address: "{{ bird__bgp_addr.vpn }}" + as: "{{ bird__as.aurore }}" + neighbor: + address: + - 2a09:6840:213::1:2 + - 10.213.1.2 + as: "{{ bird__as.aurore }}" + table: wg + import: accept + export: reject + next_hop_self: true +... diff --git a/host_vars/vpn-1.back.infra.auro.re.yml b/group_vars/vpn/ifupdown2.yml similarity index 51% rename from host_vars/vpn-1.back.infra.auro.re.yml rename to group_vars/vpn/ifupdown2.yml index ba23e2f..cd7c311 100644 --- a/host_vars/vpn-1.back.infra.auro.re.yml +++ b/group_vars/vpn/ifupdown2.yml @@ -1,24 +1,15 @@ --- +ifupdown2__vrf: + wg-vrf: + table: "{{ iproute2__custom_tables.wireguard }}" + ifupdown2__wireguard: wg0: private_key: "{{ vault_wireguard_wg0_private }}" listen_port: 5121 - goto_table: bird + vrf: wg-vrf peer_allowed_addresses: - 2a09:6840:212::1:1/128 - 10.212.1.1/32 peer_public_key: 0kP/XjaGOpu4p9KHTAoAhkLwXzC8wJUdPIdhdpgeKhY= - -ifupdown2__interfaces: - adm0: - addresses: - - 2a09:6840:128::10:11/64 - - 10.128.10.11/16 - ext0: - addresses: - - 45.66.111.200/30 - vpn0: - addresses: - - 2a09:6840:213::1:3/64 - - 10.213.1.3/16 ... diff --git a/group_vars/vpn/iproute2.yml b/group_vars/vpn/iproute2.yml new file mode 100644 index 0000000..f81f76a --- /dev/null +++ b/group_vars/vpn/iproute2.yml @@ -0,0 +1,7 @@ +--- +iproute2__custom_tables: + wireguard: 2000 + +iproute2__custom_protos: + wireguard: 2000 +... diff --git a/host_vars/infra-1.back.infra.auro.re.yml b/host_vars/infra-1.back.infra.auro.re.yml index 523a190..3ad96b9 100644 --- a/host_vars/infra-1.back.infra.auro.re.yml +++ b/host_vars/infra-1.back.infra.auro.re.yml @@ -38,8 +38,8 @@ ifupdown2__interfaces: ipv6_addrgen: false vpn0: addresses: - - 2a09:6840:213::1:1 - - 10.213.1.1 + - 2a09:6840:213::1:1/64 + - 10.213.1.1/16 bird__router_id: 10.203.1.3 @@ -47,6 +47,9 @@ bird__bgp_addr: back: - 2a09:6840:203::1:3 - 10.203.1.3 + vpn: + - 2a09:6840:213::1:1 + - 10.213.1.1 bird__pref_src_addr: - 2a09:6840:203::1:3 diff --git a/host_vars/infra-2.back.infra.auro.re.yml b/host_vars/infra-2.back.infra.auro.re.yml index 1997760..740408f 100644 --- a/host_vars/infra-2.back.infra.auro.re.yml +++ b/host_vars/infra-2.back.infra.auro.re.yml @@ -38,8 +38,8 @@ ifupdown2__interfaces: ipv6_addrgen: false vpn0: addresses: - - 2a09:6840:213::1:2 - - 10.213.1.2 + - 2a09:6840:213::1:2/64 + - 10.213.1.2/16 bird__router_id: 10.203.1.4 @@ -47,6 +47,9 @@ bird__bgp_addr: back: - 2a09:6840:203::1:4 - 10.203.1.4 + vpn: + - 2a09:6840:213:1:2 + - 10.213.1.2 bird__pref_src_addr: - 2a09:6840:203::1:4 diff --git a/host_vars/ns-master.int.infra.auro.re/knotd.yml b/host_vars/ns-master.int.infra.auro.re/knotd.yml index 5892a9f..bf3879b 100644 --- a/host_vars/ns-master.int.infra.auro.re/knotd.yml +++ b/host_vars/ns-master.int.infra.auro.re/knotd.yml @@ -363,12 +363,12 @@ knotd__zones: dns-2.int: - 2a09:6840:206::1:2 - 10.206.1.2 - vpn-1.back: - - 10.128.10.11 - - 2a09:6840:128::10:11 - vpn-2.back: - - 10.128.10.111 - - 2a09:6840:128::10:111 + wg-1.vpn: + - 2a09:6840:213::1:3 + - 10.213.1.3 + wg-2.vpn: + - 2a09:6840:213::1:4 + - 10.213.1.4 infra-1.back: - 2a09:6840:203::1:3 - 10.203.1.3 diff --git a/host_vars/wg-1.vpn.infra.auro.re.yml b/host_vars/wg-1.vpn.infra.auro.re.yml new file mode 100644 index 0000000..a3960c2 --- /dev/null +++ b/host_vars/wg-1.vpn.infra.auro.re.yml @@ -0,0 +1,24 @@ +--- +systemd_link__links: + vpn0: 02:00:00:b5:ca:c7 + ext0: 02:00:00:e3:65:49 + +ifupdown2__interfaces: + ext0: + gateways: "{{ ifupdown2__gateways.ext }}" + addresses: + - 2a09:6840:211::1:1/64 + - 10.211.1.1/16 + - 45.66.111.200/30 + vpn0: + addresses: + - 2a09:6840:213::1:3/64 + - 10.213.1.3/16 + +bird__router_id: 10.213.1.3 + +bird__bgp_addr: + vpn: + - 2a09:6840:213::1:3 + - 10.213.1.3 +... diff --git a/hosts b/hosts index d29d2bd..de1876a 100644 --- a/hosts +++ b/hosts @@ -19,7 +19,7 @@ eb-1.ups.infra.auro.re ec-1.ups.infra.auro.re [vpn] -#vpn-[1:2].back.infra.auro.re +wg-[1:2].vpn.infra.auro.re [dns] dns-[1:2].int.infra.auro.re @@ -54,17 +54,17 @@ ntp-[1:2].int.infra.auro.re [radius] radius-[1:2].isp.infra.auro.re -[vm_network] -#vpn-[1:2].back.infra.auro.re -edge-[1:2].back.infra.auro.re -dhcp-[1:2].isp.infra.auro.re -dns-[1:2].int.infra.auro.re -radius-[1:2].isp.infra.auro.re -ntp-[1:2].int.infra.auro.re -#ldap-[1:2].int.infra.auro.re -isp-[1:2].back.infra.auro.re -infra-[1:2].back.infra.auro.re -prometheus-[1:2].monit.infra.auro.re +[vm_network:children] +vpn +edge +dhcp +dns +radius +ntp +#ldap +isp +infra +prom [pve:children] pve_network diff --git a/playbooks/bird.yml b/playbooks/bird.yml index 2901dec..73bd8c9 100755 --- a/playbooks/bird.yml +++ b/playbooks/bird.yml @@ -3,6 +3,7 @@ - hosts: - infra - isp + - vpn roles: - bird diff --git a/playbooks/iproute2.yml b/playbooks/iproute2.yml index 4e918a5..5cf5aa6 100755 --- a/playbooks/iproute2.yml +++ b/playbooks/iproute2.yml @@ -1,17 +1,10 @@ #!/usr/bin/env ansible-playbook --- - hosts: - - edge-1.back.infra.auro.re - - edge-2.back.infra.auro.re - - isp-1.back.infra.auro.re - - isp-2.back.infra.auro.re - - infra-1.back.infra.auro.re - - infra-2.back.infra.auro.re - - vpn-1.back.infra.auro.re - - vpn-2.back.infra.auro.re - vars: - iproute2__custom_tables: - bird: 100 + - edge + - isp + - infra + - vpn roles: - iproute2 ... diff --git a/playbooks/systemd_link.yml b/playbooks/systemd_link.yml index 7db0aa9..c0c40fd 100755 --- a/playbooks/systemd_link.yml +++ b/playbooks/systemd_link.yml @@ -11,12 +11,6 @@ - ldap - isp - vpn - vars: - systemd_link__hosts: - vpn-1.back.infra.auro.re: - adm0: 02:00:00:3b:74:20 - vpn0: 02:00:00:b5:ca:c7 - pub0: 02:00:00:e3:65:49 roles: - systemd_link ... diff --git a/roles/bird/defaults/main.yml b/roles/bird/defaults/main.yml index 68e90f2..82eab8f 100644 --- a/roles/bird/defaults/main.yml +++ b/roles/bird/defaults/main.yml @@ -1,7 +1,7 @@ --- -bird__ospf_stub_interfaces: [] -bird__ospf_stub_networks: [] -bird__ospf_broadcast_interfaces: {} +bird__kernel: {} +bird__pipes: {} +bird__tables: {} bird__ospf_hello: 2 bird__ospf_retransmit: 5 bird__ospf_wait: 10 @@ -10,5 +10,5 @@ bird__radv_interfaces: {} bird__radv_dns_servers: [] bird__radv_max_interval: 5 bird__static_unreachable: [] -bird__bgp_sessions: [] +bird__bgp_sessions: {} ... diff --git a/roles/bird/filter_plugins/bird.py b/roles/bird/filter_plugins/bird.py index bcb366a..504178c 100644 --- a/roles/bird/filter_plugins/bird.py +++ b/roles/bird/filter_plugins/bird.py @@ -135,7 +135,7 @@ def str_of_condition(condition: Condition, ctx: bool) -> str: case Proto(protos=protos): protos = [quoted(bird_name(p, ctx.ipv4)) for p in protos] - return f"proto ~ [ {', '.join(protos)} ]" + return " || ".join(f"proto = {p}" for p in protos) case Source(sources=[source]): return f"krt_source = {source}" diff --git a/roles/bird/templates/bird.conf.j2 b/roles/bird/templates/bird.conf.j2 index c10128b..459ac43 100644 --- a/roles/bird/templates/bird.conf.j2 +++ b/roles/bird/templates/bird.conf.j2 @@ -1,9 +1,26 @@ {{ ansible_managed | comment }} +{% macro import_export(obj, ipv4) %} +{{ obj.import | default([]) | bird_import(ipv4) }} +{% if obj.limits.import is defined %} +import limit {{ obj.limits.import }}; +{% endif %} +{{ obj.export | default([]) | bird_export(ipv4) }} +{% if obj.limits.export is defined %} +export limit {{ obj.limits.export }}; +{% endif %} +{% endmacro %} + log syslog all; router id {{ bird__router_id }}; +{% for table in bird__tables %} +{% for version in ["ipv4", "ipv6"] %} +{{ version }} table {{ table | bird_name(version == "ipv4") }}; +{% endfor %} +{% endfor %} + protocol device { scan time 10; } @@ -22,45 +39,36 @@ protocol kernel {{ name | bird_name(ipv4) }} { persist; {% endif %} {{ version }} { - {{ kernel.import - | default([]) - | bird_import(ipv4) - | indent(8) }} -{% if kernel.limits.import is defined %} - import limit {{ kernel.limits.import }}; -{% endif %} - {{ kernel.export - | default([]) - | bird_export(ipv4) - | indent(8) }} -{% if kernel.limits.export is defined %} - export limit {{ kernel.limits.export }}; +{% if kernel.table is defined %} + table {{ kernel.table | bird_name(ipv4) }}; {% endif %} + {{ import_export(kernel, ipv4) | indent(8) }} }; } {% endfor %} {% endfor %} +{% for name, pipe in bird__pipes.items() %} +{% for version in ["ipv4", "ipv6"] %} +{% set ipv4 = version == "ipv4" %} +protocol pipe {{ name | bird_name(ipv4) }} { + table {{ pipe.table | bird_name(ipv4) }}; + peer_table {{ pipe.peer_table | bird_name(ipv4) }}; + {{ import_export(kernel, ipv4) | indent(8) }} +} +{% endfor %} +{% endfor %} + {% if bird__ospf is defined %} {% for version in ["ipv4", "ipv6"] %} {% set ipv4 = version == "ipv4" %} {% set ospf_version = "v2" if ipv4 else "v3" %} protocol ospf {{ ospf_version }} {{ "ospf" | bird_name(ipv4) }} { {{ version }} { - {{ bird__ospf.import - | default([]) - | bird_import(ipv4) - | indent(8) }} -{% if bird__ospf.limits.import is defined %} - import limit {{ bird__ospf.limits.import }}; -{% endif %} - {{ bird__ospf.export - | default([]) - | bird_export(ipv4) - | indent(8) }} -{% if bird__ospf.limits.export is defined %} - export limit {{ bird__ospf.limits.export }}; +{% if bird__ospf.table is defined %} + table {{ bird__ospf.table | bird_name(ipv4) }}; {% endif %} + {{ import_export(bird__ospf, ipv4) | indent(8) }} }; {% for id, area in bird__ospf.areas.items() %} area {{ id }} { @@ -97,20 +105,13 @@ protocol bgp {{ name | bird_name(ipv4) }} { rr cluster id {{ bgp.rr_cluster_client }}; {% endif %} {{ version }} { - {{ bgp.import - | default([]) - | bird_import(ipv4) - | indent(8) }} -{% if bgp.limits.import is defined %} - import limit {{ bgp.limits.import }}; +{% if bgp.table is defined %} + table {{ bgp.table | bird_name(ipv4) }}; {% endif %} - {{ bgp.export - | default([]) - | bird_export(ipv4) - | indent(8) }} -{% if bgp.limits.export is defined %} - export limit {{ bgp.limits.export }}; +{% if bgp.next_hop_self is defined %} + next hop self; {% endif %} + {{ import_export(bgp, ipv4) | indent(8) }} }; } {% endfor %} diff --git a/roles/firewall/files/firewall b/roles/firewall/files/firewall index aed4041..fbcce56 100644 --- a/roles/firewall/files/firewall +++ b/roles/firewall/files/firewall @@ -155,8 +155,8 @@ class Protocols(RestrictiveBaseModel): class Rule(RestrictiveBaseModel): - iif: str | None - oif: str | None + iif: AutoSet[str] | None + oif: AutoSet[str] | None protocols: Protocols = Protocols() src: AutoSet[IPvAnyNetwork | ZoneName] | None dst: AutoSet[IPvAnyNetwork | ZoneName] | None diff --git a/roles/ifupdown2/defaults/main.yml b/roles/ifupdown2/defaults/main.yml index 2c5b16c..1ea7393 100644 --- a/roles/ifupdown2/defaults/main.yml +++ b/roles/ifupdown2/defaults/main.yml @@ -1,6 +1,7 @@ --- ifupdown2__interfaces: {} ifupdown2__wireguard: {} +ifupdown2__vrf: {} ifupdown2__wireguard_keepalive: 0 ifupdown2__wireguard_proto: boot ifupdown2__prio_base: 100 diff --git a/roles/ifupdown2/templates/interfaces.j2 b/roles/ifupdown2/templates/interfaces.j2 index e3f473e..de4ff68 100644 --- a/roles/ifupdown2/templates/interfaces.j2 +++ b/roles/ifupdown2/templates/interfaces.j2 @@ -21,6 +21,9 @@ pre-up ip rule add prio {{ prio + 1 }} iif $IFACE blackhole post-down ip rule del prio {{ prio }} iif $IFACE table {{ iface.goto_table }} post-down ip rule del prio {{ prio + 1 }} iif $IFACE blackhole {% endif %} +{% if iface.vrf is defined %} +vrf {{ iface.vrf }} +{% endif %} {% if iface.ipv6_addrgen is defined %} ipv6-addrgen {{ iface.ipv6_addrgen | ternary("yes", "no") }} @@ -63,5 +66,11 @@ iface {{ name }} {% for address in iface.peer_allowed_addresses | default([]) %} post-up ip route add {{ address }} proto {{ ifupdown2__wireguard_proto }} dev $IFACE {% endfor %} +{% endfor %} +{% for name, iface in ifupdown2__vrf.items() | sort(attribute="0") %} +auto {{ name }} +iface {{ name }} + {{ iface_common(iface, index=loop.index) | indent(4) }} + vrf-table {{ iface.table }} {% endfor %} diff --git a/roles/iproute2/defaults/main.yml b/roles/iproute2/defaults/main.yml index d5965eb..cc9bc65 100644 --- a/roles/iproute2/defaults/main.yml +++ b/roles/iproute2/defaults/main.yml @@ -1,8 +1,4 @@ --- -iproute2__default_tables: - local: 255 - main: 254 - default: 253 - unspec: 0 iproute2__custom_tables: {} +iproute2__custom_protos: {} ... diff --git a/roles/iproute2/tasks/main.yml b/roles/iproute2/tasks/main.yml index 2dd3832..872155f 100644 --- a/roles/iproute2/tasks/main.yml +++ b/roles/iproute2/tasks/main.yml @@ -1,17 +1,12 @@ --- -- name: Ensure that default and custom tables names don't overlap - assert: - that: "not (iproute2__default_tables.keys() - | intersect(iproute2__custom_tables.keys()))" - -- name: Configure rt_tables +- name: Configure custom tables and protos template: - src: rt_tables.j2 - dest: /etc/iproute2/rt_tables + src: "{{ item }}.j2" + dest: "/etc/iproute2/{{ item }}.d/custom.conf" owner: root group: root mode: u=rw,g=r,o=r - vars: - iproute2__tables: "{{ iproute2__default_tables - | combine(iproute2__custom_tables) }}" + loop: + - rt_tables + - rt_protos ... diff --git a/roles/iproute2/templates/rt_protos.j2 b/roles/iproute2/templates/rt_protos.j2 new file mode 100644 index 0000000..b3902d9 --- /dev/null +++ b/roles/iproute2/templates/rt_protos.j2 @@ -0,0 +1,5 @@ +{{ ansible_managed | comment }} + +{% for name, id in iproute2__custom_protos.items() %} +{{ id }} {{ name }} +{% endfor %} diff --git a/roles/iproute2/templates/rt_tables.j2 b/roles/iproute2/templates/rt_tables.j2 index 441314f..c1b8a42 100644 --- a/roles/iproute2/templates/rt_tables.j2 +++ b/roles/iproute2/templates/rt_tables.j2 @@ -1,5 +1,5 @@ {{ ansible_managed | comment }} -{% for name, id in iproute2__tables.items() %} +{% for name, id in iproute2__custom_tables.items() %} {{ id }} {{ name }} {% endfor %}