misc: WIP: vpn

This commit is contained in:
jeltz 2023-11-07 04:11:28 +01:00
parent 061b6f1049
commit 02910a8fc0
Signed by: jeltz
GPG key ID: 800882B66C0C3326
24 changed files with 231 additions and 120 deletions

View file

@ -7,9 +7,9 @@ ifupdown2__gateways:
int: int:
- 2a09:6840:206::1 - 2a09:6840:206::1
- 10.206.0.1 - 10.206.0.1
pub: ext:
- 2a09:6840:111::254 - 2a09:6840:211::1
- 45.66.111.254 - 10.211.0.1
monit: monit:
- 2a09:6840:204::1 - 2a09:6840:204::1
- 10.204.0.1 - 10.204.0.1

View file

@ -57,4 +57,28 @@ bird__bgp:
- pref_src: "{{ bird__pref_src_addr }}" - pref_src: "{{ bird__pref_src_addr }}"
- accept - accept
export: reject 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
... ...

View file

@ -104,7 +104,13 @@ firewall__zones:
- 10.128.0.150 - 10.128.0.150
firewall__input: firewall__input:
- src: back - iif:
- back0 # FIXME link-local
- vpn0
verdict: accept
- src:
- back
- vpn
verdict: accept verdict: accept
- src: monit - src: monit
protocols: protocols:

58
group_vars/vpn/bird.yml Normal file
View file

@ -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
...

View file

@ -1,24 +1,15 @@
--- ---
ifupdown2__vrf:
wg-vrf:
table: "{{ iproute2__custom_tables.wireguard }}"
ifupdown2__wireguard: ifupdown2__wireguard:
wg0: wg0:
private_key: "{{ vault_wireguard_wg0_private }}" private_key: "{{ vault_wireguard_wg0_private }}"
listen_port: 5121 listen_port: 5121
goto_table: bird vrf: wg-vrf
peer_allowed_addresses: peer_allowed_addresses:
- 2a09:6840:212::1:1/128 - 2a09:6840:212::1:1/128
- 10.212.1.1/32 - 10.212.1.1/32
peer_public_key: 0kP/XjaGOpu4p9KHTAoAhkLwXzC8wJUdPIdhdpgeKhY= 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
... ...

View file

@ -0,0 +1,7 @@
---
iproute2__custom_tables:
wireguard: 2000
iproute2__custom_protos:
wireguard: 2000
...

View file

@ -38,8 +38,8 @@ ifupdown2__interfaces:
ipv6_addrgen: false ipv6_addrgen: false
vpn0: vpn0:
addresses: addresses:
- 2a09:6840:213::1:1 - 2a09:6840:213::1:1/64
- 10.213.1.1 - 10.213.1.1/16
bird__router_id: 10.203.1.3 bird__router_id: 10.203.1.3
@ -47,6 +47,9 @@ bird__bgp_addr:
back: back:
- 2a09:6840:203::1:3 - 2a09:6840:203::1:3
- 10.203.1.3 - 10.203.1.3
vpn:
- 2a09:6840:213::1:1
- 10.213.1.1
bird__pref_src_addr: bird__pref_src_addr:
- 2a09:6840:203::1:3 - 2a09:6840:203::1:3

View file

@ -38,8 +38,8 @@ ifupdown2__interfaces:
ipv6_addrgen: false ipv6_addrgen: false
vpn0: vpn0:
addresses: addresses:
- 2a09:6840:213::1:2 - 2a09:6840:213::1:2/64
- 10.213.1.2 - 10.213.1.2/16
bird__router_id: 10.203.1.4 bird__router_id: 10.203.1.4
@ -47,6 +47,9 @@ bird__bgp_addr:
back: back:
- 2a09:6840:203::1:4 - 2a09:6840:203::1:4
- 10.203.1.4 - 10.203.1.4
vpn:
- 2a09:6840:213:1:2
- 10.213.1.2
bird__pref_src_addr: bird__pref_src_addr:
- 2a09:6840:203::1:4 - 2a09:6840:203::1:4

View file

@ -363,12 +363,12 @@ knotd__zones:
dns-2.int: dns-2.int:
- 2a09:6840:206::1:2 - 2a09:6840:206::1:2
- 10.206.1.2 - 10.206.1.2
vpn-1.back: wg-1.vpn:
- 10.128.10.11 - 2a09:6840:213::1:3
- 2a09:6840:128::10:11 - 10.213.1.3
vpn-2.back: wg-2.vpn:
- 10.128.10.111 - 2a09:6840:213::1:4
- 2a09:6840:128::10:111 - 10.213.1.4
infra-1.back: infra-1.back:
- 2a09:6840:203::1:3 - 2a09:6840:203::1:3
- 10.203.1.3 - 10.203.1.3

View file

@ -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
...

24
hosts
View file

@ -19,7 +19,7 @@ eb-1.ups.infra.auro.re
ec-1.ups.infra.auro.re ec-1.ups.infra.auro.re
[vpn] [vpn]
#vpn-[1:2].back.infra.auro.re wg-[1:2].vpn.infra.auro.re
[dns] [dns]
dns-[1:2].int.infra.auro.re dns-[1:2].int.infra.auro.re
@ -54,17 +54,17 @@ ntp-[1:2].int.infra.auro.re
[radius] [radius]
radius-[1:2].isp.infra.auro.re radius-[1:2].isp.infra.auro.re
[vm_network] [vm_network:children]
#vpn-[1:2].back.infra.auro.re vpn
edge-[1:2].back.infra.auro.re edge
dhcp-[1:2].isp.infra.auro.re dhcp
dns-[1:2].int.infra.auro.re dns
radius-[1:2].isp.infra.auro.re radius
ntp-[1:2].int.infra.auro.re ntp
#ldap-[1:2].int.infra.auro.re #ldap
isp-[1:2].back.infra.auro.re isp
infra-[1:2].back.infra.auro.re infra
prometheus-[1:2].monit.infra.auro.re prom
[pve:children] [pve:children]
pve_network pve_network

View file

@ -3,6 +3,7 @@
- hosts: - hosts:
- infra - infra
- isp - isp
- vpn
roles: roles:
- bird - bird

View file

@ -1,17 +1,10 @@
#!/usr/bin/env ansible-playbook #!/usr/bin/env ansible-playbook
--- ---
- hosts: - hosts:
- edge-1.back.infra.auro.re - edge
- edge-2.back.infra.auro.re - isp
- isp-1.back.infra.auro.re - infra
- isp-2.back.infra.auro.re - vpn
- 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
roles: roles:
- iproute2 - iproute2
... ...

View file

@ -11,12 +11,6 @@
- ldap - ldap
- isp - isp
- vpn - 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: roles:
- systemd_link - systemd_link
... ...

View file

@ -1,7 +1,7 @@
--- ---
bird__ospf_stub_interfaces: [] bird__kernel: {}
bird__ospf_stub_networks: [] bird__pipes: {}
bird__ospf_broadcast_interfaces: {} bird__tables: {}
bird__ospf_hello: 2 bird__ospf_hello: 2
bird__ospf_retransmit: 5 bird__ospf_retransmit: 5
bird__ospf_wait: 10 bird__ospf_wait: 10
@ -10,5 +10,5 @@ bird__radv_interfaces: {}
bird__radv_dns_servers: [] bird__radv_dns_servers: []
bird__radv_max_interval: 5 bird__radv_max_interval: 5
bird__static_unreachable: [] bird__static_unreachable: []
bird__bgp_sessions: [] bird__bgp_sessions: {}
... ...

View file

@ -135,7 +135,7 @@ def str_of_condition(condition: Condition, ctx: bool) -> str:
case Proto(protos=protos): case Proto(protos=protos):
protos = [quoted(bird_name(p, ctx.ipv4)) for p in 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]): case Source(sources=[source]):
return f"krt_source = {source}" return f"krt_source = {source}"

View file

@ -1,9 +1,26 @@
{{ ansible_managed | comment }} {{ 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; log syslog all;
router id {{ bird__router_id }}; 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 { protocol device {
scan time 10; scan time 10;
} }
@ -22,45 +39,36 @@ protocol kernel {{ name | bird_name(ipv4) }} {
persist; persist;
{% endif %} {% endif %}
{{ version }} { {{ version }} {
{{ kernel.import {% if kernel.table is defined %}
| default([]) table {{ kernel.table | bird_name(ipv4) }};
| 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 }};
{% endif %} {% endif %}
{{ import_export(kernel, ipv4) | indent(8) }}
}; };
} }
{% endfor %} {% endfor %}
{% 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 %} {% if bird__ospf is defined %}
{% for version in ["ipv4", "ipv6"] %} {% for version in ["ipv4", "ipv6"] %}
{% set ipv4 = version == "ipv4" %} {% set ipv4 = version == "ipv4" %}
{% set ospf_version = "v2" if ipv4 else "v3" %} {% set ospf_version = "v2" if ipv4 else "v3" %}
protocol ospf {{ ospf_version }} {{ "ospf" | bird_name(ipv4) }} { protocol ospf {{ ospf_version }} {{ "ospf" | bird_name(ipv4) }} {
{{ version }} { {{ version }} {
{{ bird__ospf.import {% if bird__ospf.table is defined %}
| default([]) table {{ bird__ospf.table | bird_name(ipv4) }};
| 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 }};
{% endif %} {% endif %}
{{ import_export(bird__ospf, ipv4) | indent(8) }}
}; };
{% for id, area in bird__ospf.areas.items() %} {% for id, area in bird__ospf.areas.items() %}
area {{ id }} { area {{ id }} {
@ -97,20 +105,13 @@ protocol bgp {{ name | bird_name(ipv4) }} {
rr cluster id {{ bgp.rr_cluster_client }}; rr cluster id {{ bgp.rr_cluster_client }};
{% endif %} {% endif %}
{{ version }} { {{ version }} {
{{ bgp.import {% if bgp.table is defined %}
| default([]) table {{ bgp.table | bird_name(ipv4) }};
| bird_import(ipv4)
| indent(8) }}
{% if bgp.limits.import is defined %}
import limit {{ bgp.limits.import }};
{% endif %} {% endif %}
{{ bgp.export {% if bgp.next_hop_self is defined %}
| default([]) next hop self;
| bird_export(ipv4)
| indent(8) }}
{% if bgp.limits.export is defined %}
export limit {{ bgp.limits.export }};
{% endif %} {% endif %}
{{ import_export(bgp, ipv4) | indent(8) }}
}; };
} }
{% endfor %} {% endfor %}

View file

@ -155,8 +155,8 @@ class Protocols(RestrictiveBaseModel):
class Rule(RestrictiveBaseModel): class Rule(RestrictiveBaseModel):
iif: str | None iif: AutoSet[str] | None
oif: str | None oif: AutoSet[str] | None
protocols: Protocols = Protocols() protocols: Protocols = Protocols()
src: AutoSet[IPvAnyNetwork | ZoneName] | None src: AutoSet[IPvAnyNetwork | ZoneName] | None
dst: AutoSet[IPvAnyNetwork | ZoneName] | None dst: AutoSet[IPvAnyNetwork | ZoneName] | None

View file

@ -1,6 +1,7 @@
--- ---
ifupdown2__interfaces: {} ifupdown2__interfaces: {}
ifupdown2__wireguard: {} ifupdown2__wireguard: {}
ifupdown2__vrf: {}
ifupdown2__wireguard_keepalive: 0 ifupdown2__wireguard_keepalive: 0
ifupdown2__wireguard_proto: boot ifupdown2__wireguard_proto: boot
ifupdown2__prio_base: 100 ifupdown2__prio_base: 100

View file

@ -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 }} iif $IFACE table {{ iface.goto_table }}
post-down ip rule del prio {{ prio + 1 }} iif $IFACE blackhole post-down ip rule del prio {{ prio + 1 }} iif $IFACE blackhole
{% endif %} {% endif %}
{% if iface.vrf is defined %}
vrf {{ iface.vrf }}
{% endif %}
{% if iface.ipv6_addrgen is defined %} {% if iface.ipv6_addrgen is defined %}
ipv6-addrgen {{ iface.ipv6_addrgen ipv6-addrgen {{ iface.ipv6_addrgen
| ternary("yes", "no") }} | ternary("yes", "no") }}
@ -63,5 +66,11 @@ iface {{ name }}
{% for address in iface.peer_allowed_addresses | default([]) %} {% for address in iface.peer_allowed_addresses | default([]) %}
post-up ip route add {{ address }} proto {{ ifupdown2__wireguard_proto }} dev $IFACE post-up ip route add {{ address }} proto {{ ifupdown2__wireguard_proto }} dev $IFACE
{% endfor %} {% 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 %} {% endfor %}

View file

@ -1,8 +1,4 @@
--- ---
iproute2__default_tables:
local: 255
main: 254
default: 253
unspec: 0
iproute2__custom_tables: {} iproute2__custom_tables: {}
iproute2__custom_protos: {}
... ...

View file

@ -1,17 +1,12 @@
--- ---
- name: Ensure that default and custom tables names don't overlap - name: Configure custom tables and protos
assert:
that: "not (iproute2__default_tables.keys()
| intersect(iproute2__custom_tables.keys()))"
- name: Configure rt_tables
template: template:
src: rt_tables.j2 src: "{{ item }}.j2"
dest: /etc/iproute2/rt_tables dest: "/etc/iproute2/{{ item }}.d/custom.conf"
owner: root owner: root
group: root group: root
mode: u=rw,g=r,o=r mode: u=rw,g=r,o=r
vars: loop:
iproute2__tables: "{{ iproute2__default_tables - rt_tables
| combine(iproute2__custom_tables) }}" - rt_protos
... ...

View file

@ -0,0 +1,5 @@
{{ ansible_managed | comment }}
{% for name, id in iproute2__custom_protos.items() %}
{{ id }} {{ name }}
{% endfor %}

View file

@ -1,5 +1,5 @@
{{ ansible_managed | comment }} {{ ansible_managed | comment }}
{% for name, id in iproute2__tables.items() %} {% for name, id in iproute2__custom_tables.items() %}
{{ id }} {{ name }} {{ id }} {{ name }}
{% endfor %} {% endfor %}