Initial commit, squashed
This commit is contained in:
commit
158e8740b8
83 changed files with 2718 additions and 0 deletions
18
roles/exit/files/keepalive-service
Normal file
18
roles/exit/files/keepalive-service
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
class="${1}"
|
||||
name="${2}"
|
||||
state="${3}"
|
||||
|
||||
case "${state}" in
|
||||
"MASTER" | "FAULT")
|
||||
systemctl start "${name}"
|
||||
;;
|
||||
"BACKUP" | "STOP")
|
||||
systemctl stop "${name}"
|
||||
;;
|
||||
*)
|
||||
logger "keepalived unknown state for ${name}: ${state}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
21
roles/exit/handlers/main.yml
Normal file
21
roles/exit/handlers/main.yml
Normal file
|
@ -0,0 +1,21 @@
|
|||
- name: reload frr
|
||||
command:
|
||||
cmd: /usr/lib/frr/frr-reload
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: reload interfaces
|
||||
command:
|
||||
cmd: ifreload -a
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: restart keepalived
|
||||
service: name=keepalived state=restarted
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: restart radvd
|
||||
service: name=radvd state=restarted
|
||||
when: "'handler' not in ansible_skip_tags"
|
||||
|
||||
- name: reload systemd
|
||||
systemd: daemon_reload=yes
|
||||
when: "'handler' not in ansible_skip_tags"
|
2
roles/exit/meta/main.yml
Normal file
2
roles/exit/meta/main.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
dependencies:
|
||||
- role: fabric
|
26
roles/exit/tasks/dhcp.yml
Normal file
26
roles/exit/tasks/dhcp.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
- name: Install keepalived
|
||||
import_tasks: keepalived.yml
|
||||
|
||||
- name: Create keepalive notify script for systemd services
|
||||
copy:
|
||||
dest: /usr/local/bin/
|
||||
src: keepalive-service
|
||||
mode: 0755
|
||||
|
||||
- name: Configure DHCP relays
|
||||
template:
|
||||
dest: "/etc/default/isc-dhcp-relay"
|
||||
src: isc-dhcp-relay.j2
|
||||
|
||||
- name: Set up keepalived
|
||||
template:
|
||||
dest: /etc/keepalived/keepalived.conf
|
||||
src: keepalived.conf.j2
|
||||
mode: 0600
|
||||
notify: restart keepalived
|
||||
|
||||
- name: Enable keepalived
|
||||
service:
|
||||
name: keepalived
|
||||
enabled: yes
|
||||
state: started
|
25
roles/exit/tasks/keepalived.yml
Normal file
25
roles/exit/tasks/keepalived.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
# We should just apt install it but it’s broken with Cumulus 5.4 + Debian 10.
|
||||
- name: Install keepalived
|
||||
block:
|
||||
- name: Install deps for keepalived
|
||||
package:
|
||||
name: autoconf,automake,build-essential,pkg-config,libxtables-dev,libip4tc-dev,libip6tc-dev,libipset-dev,libnl-3-dev,libnl-genl-3-dev,libssl-dev
|
||||
|
||||
- name: Checkout keepalived source
|
||||
git:
|
||||
repo: https://github.com/acassen/keepalived
|
||||
dest: /usr/local/src/keepalived
|
||||
version: v2.2.7
|
||||
|
||||
- name: Build and install keepalived
|
||||
shell: |
|
||||
./autogen.sh
|
||||
./configure --sysconfdir=/etc
|
||||
make
|
||||
make install
|
||||
args:
|
||||
chdir: /usr/local/src/keepalived
|
||||
creates: /usr/local/sbin/keepalived
|
||||
notify: reload systemd
|
||||
|
||||
- meta: flush_handlers
|
26
roles/exit/tasks/main.yml
Normal file
26
roles/exit/tasks/main.yml
Normal file
|
@ -0,0 +1,26 @@
|
|||
- name: Set up networks
|
||||
template:
|
||||
dest: /etc/network/interfaces.d/networks.intf
|
||||
src: networks.intf.j2
|
||||
mode: 0644
|
||||
notify: reload interfaces
|
||||
|
||||
- name: Set up firewall links
|
||||
template:
|
||||
dest: /etc/network/interfaces.d/firewall.intf
|
||||
src: firewall.intf.j2
|
||||
mode: 0644
|
||||
notify: reload interfaces
|
||||
|
||||
- name: Set up FRR
|
||||
template:
|
||||
dest: /etc/frr/frr.conf
|
||||
src: frr.conf.j2
|
||||
mode: 0600
|
||||
notify: reload frr
|
||||
|
||||
- name: Set up radvd
|
||||
import_tasks: radvd.yml
|
||||
|
||||
- name: Set up DHCP relay
|
||||
import_tasks: dhcp.yml
|
36
roles/exit/tasks/radvd.yml
Normal file
36
roles/exit/tasks/radvd.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
# We should just apt install it but we need features not in released
|
||||
# version. Also the cumulus package is two versions behind.
|
||||
- name: Install radvd
|
||||
block:
|
||||
- name: Install deps for radvd
|
||||
package:
|
||||
name: autoconf,automake,bison,build-essential,flex,gettext,libtool,pkg-config,libbsd-dev,libbsd0
|
||||
|
||||
- name: Checkout radvd source
|
||||
git:
|
||||
repo: https://github.com/radvd-project/radvd
|
||||
dest: /usr/local/src/radvd
|
||||
version: f67335b5335b6ed5ca68d6fa71c08cccb4f3a629
|
||||
|
||||
- name: Build and install radvd
|
||||
shell: |
|
||||
./autogen.sh
|
||||
./configure --without-check
|
||||
make
|
||||
make install
|
||||
args:
|
||||
chdir: /usr/local/src/radvd
|
||||
creates: /usr/local/sbin/radvd
|
||||
|
||||
- name: Configure radvd
|
||||
template:
|
||||
dest: /etc/radvd.conf
|
||||
src: radvd.conf.j2
|
||||
mode: 0644
|
||||
notify: restart radvd
|
||||
|
||||
- name: Enable radvd
|
||||
service:
|
||||
name: radvd
|
||||
enabled: true
|
||||
state: started
|
41
roles/exit/templates/firewall.intf.j2
Normal file
41
roles/exit/templates/firewall.intf.j2
Normal file
|
@ -0,0 +1,41 @@
|
|||
{% set exit = inventory_hostname.split('-')[1]|int %}
|
||||
{% set lo_address = interfaces
|
||||
| selectattr('name', '==', 'lo')
|
||||
| map(attribute='ip_addresses') | first
|
||||
| selectattr('role') | selectattr('role.value', '==', 'loopback')
|
||||
| map(attribute='address') %}
|
||||
{% set ip = lo_address | ipv4 | first %}
|
||||
{% set ip6 = lo_address | ipv6 | first -%}
|
||||
|
||||
auto inside
|
||||
iface inside
|
||||
vrf-table auto
|
||||
address {{ ip }}
|
||||
address {{ ip6 }}
|
||||
|
||||
auto outside
|
||||
iface outside
|
||||
vrf-table auto
|
||||
address {{ ip }}
|
||||
address {{ ip6 }}
|
||||
|
||||
{% for iface in ifaces_firewall %}
|
||||
auto {{ iface }}.2
|
||||
iface {{ iface }}.2
|
||||
vrf inside
|
||||
|
||||
auto {{ iface }}.4
|
||||
iface {{ iface }}.4
|
||||
vrf outside
|
||||
|
||||
{% endfor -%}
|
||||
|
||||
# Backup firewall routes are exchanged over these subinterfaces.
|
||||
auto peerlink.2
|
||||
iface peerlink.2
|
||||
vrf inside
|
||||
|
||||
auto peerlink.4
|
||||
iface peerlink.4
|
||||
vrf outside
|
||||
address {{ "169.254.1.0/24" | ipaddr(exit + 1) }}
|
401
roles/exit/templates/frr.conf.j2
Normal file
401
roles/exit/templates/frr.conf.j2
Normal file
|
@ -0,0 +1,401 @@
|
|||
{% set lo_address = interfaces | selectattr('name', '==', 'lo')
|
||||
| map(attribute='ip_addresses') | first
|
||||
| selectattr('role') | selectattr('role.value', '==', 'loopback')
|
||||
| map(attribute='address') %}
|
||||
{% set my_index = inventory_hostname.split('-')[1]|int %}
|
||||
{% set bridge = interfaces | selectattr('type') | selectattr('type.value', '==', 'bridge') | first %}
|
||||
{% set my_vlans = bridge.tagged_vlans | sort(attribute='vid') -%}
|
||||
|
||||
frr defaults datacenter
|
||||
log syslog informational
|
||||
service integrated-vtysh-config
|
||||
|
||||
# Route to the outside world.
|
||||
vrf outside
|
||||
ip route 0.0.0.0/0 {{ (interfaces | selectattr('name', '==', iface_uplink) | first).custom_fields.gateway.address | ipaddr('address') }} {{ iface_uplink }}
|
||||
ipv6 route ::/0 fe80::2 {{ iface_uplink }}
|
||||
|
||||
# Don’t announce anything at start until we get routes from all our peers.
|
||||
# Without this packets might get dropped until all routes are synced.
|
||||
bgp update-delay 10
|
||||
|
||||
# Route installation into kernel fails (rarely) without this option.
|
||||
# It is not documented anywhere and appears to be a Cumulus extension.
|
||||
zebra nexthop proto only
|
||||
|
||||
router-id {{ lo_address | ipv4 | first | ipaddr('address') }}
|
||||
|
||||
# Default VRF.
|
||||
router bgp {{ asn.asn }}
|
||||
bgp bestpath as-path multipath-relax
|
||||
|
||||
neighbor fabric peer-group
|
||||
neighbor fabric remote-as external
|
||||
neighbor fabric capability extended-nexthop
|
||||
|
||||
neighbor peerlink.4094 interface remote-as external
|
||||
neighbor peerlink.4094 capability extended-nexthop
|
||||
neighbor peerlink.4094 bfd 3 150 150
|
||||
|
||||
{% for iface in ifaces_fabric %}
|
||||
neighbor {{ iface }} interface peer-group fabric
|
||||
neighbor {{ iface }} bfd 3 150 150
|
||||
{% endfor %}
|
||||
|
||||
address-family ipv4 unicast
|
||||
redistribute connected route-map loopback
|
||||
|
||||
neighbor fabric soft-reconfiguration inbound
|
||||
neighbor fabric route-map fabric->default in
|
||||
neighbor fabric route-map default->fabric out
|
||||
|
||||
import vrf outside
|
||||
import vrf route-map default-import
|
||||
exit-address-family
|
||||
|
||||
address-family ipv6 unicast
|
||||
redistribute connected route-map loopback
|
||||
|
||||
neighbor fabric activate
|
||||
neighbor fabric soft-reconfiguration inbound
|
||||
neighbor fabric route-map fabric->default in
|
||||
neighbor fabric route-map default->fabric out
|
||||
|
||||
import vrf outside
|
||||
import vrf route-map default-import
|
||||
exit-address-family
|
||||
|
||||
address-family l2vpn evpn
|
||||
advertise-all-vni
|
||||
advertise-default-gw
|
||||
neighbor fabric activate
|
||||
neighbor peerlink.4094 activate
|
||||
exit-address-family
|
||||
|
||||
|
||||
# Outside VRF. Direct route to the world, everything else goes to the firewall.
|
||||
router bgp {{ asn.asn }} vrf outside
|
||||
bgp bestpath as-path multipath-relax
|
||||
|
||||
neighbor peerlink.4 interface remote-as external
|
||||
neighbor peerlink.4 capability extended-nexthop
|
||||
neighbor peerlink.4 bfd 3 150 150
|
||||
|
||||
neighbor firewall peer-group
|
||||
neighbor firewall remote-as external
|
||||
neighbor firewall capability extended-nexthop
|
||||
|
||||
{% for iface in ifaces_firewall %}
|
||||
neighbor {{ iface }}.4 interface peer-group firewall
|
||||
neighbor {{ iface }}.4 bfd 3 150 150
|
||||
{% endfor %}
|
||||
|
||||
address-family ipv4 unicast
|
||||
neighbor peerlink.4 soft-reconfiguration inbound
|
||||
neighbor peerlink.4 route-map peer.4->me in
|
||||
neighbor peerlink.4 route-map me->peer.4 out
|
||||
|
||||
neighbor firewall allowas-in 1
|
||||
neighbor firewall default-originate
|
||||
neighbor firewall soft-reconfiguration inbound
|
||||
neighbor firewall route-map outside->firewall out
|
||||
{% for iface in ifaces_firewall %}
|
||||
neighbor {{ iface }}.4 route-map firewall-{{ loop.index }}->outside in
|
||||
{% endfor %}
|
||||
|
||||
redistribute static
|
||||
redistribute connected route-map loopback-outside
|
||||
import vrf default
|
||||
import vrf route-map outside-import
|
||||
exit-address-family
|
||||
|
||||
address-family ipv6 unicast
|
||||
neighbor peerlink.4 activate
|
||||
neighbor peerlink.4 allowas-in origin
|
||||
neighbor peerlink.4 soft-reconfiguration inbound
|
||||
neighbor peerlink.4 route-map peer.4->me in
|
||||
neighbor peerlink.4 route-map me->peer.4 out
|
||||
|
||||
neighbor firewall activate
|
||||
neighbor firewall allowas-in 1
|
||||
neighbor firewall default-originate
|
||||
neighbor firewall soft-reconfiguration inbound
|
||||
neighbor firewall route-map outside->firewall out
|
||||
{% for iface in ifaces_firewall %}
|
||||
neighbor {{ iface }}.4 route-map firewall-{{ loop.index }}->outside in
|
||||
{% endfor %}
|
||||
|
||||
redistribute static
|
||||
redistribute connected route-map loopback-outside
|
||||
import vrf default
|
||||
import vrf route-map outside-import
|
||||
exit-address-family
|
||||
|
||||
|
||||
# Inside VRF. Default route via firewall. Direct routes to servers and offices.
|
||||
router bgp {{ asn.asn }} vrf inside
|
||||
bgp bestpath as-path multipath-relax
|
||||
|
||||
neighbor peerlink.2 interface remote-as external
|
||||
neighbor peerlink.2 capability extended-nexthop
|
||||
neighbor peerlink.2 bfd 3 150 150
|
||||
|
||||
neighbor firewall peer-group
|
||||
neighbor firewall remote-as external
|
||||
neighbor firewall capability extended-nexthop
|
||||
|
||||
{% for iface in ifaces_firewall %}
|
||||
neighbor {{ iface }}.2 interface peer-group firewall
|
||||
neighbor {{ iface }}.2 bfd 3 150 150
|
||||
{% endfor %}
|
||||
|
||||
address-family ipv4 unicast
|
||||
neighbor peerlink.2 soft-reconfiguration inbound
|
||||
neighbor peerlink.2 route-map peer.2->me in
|
||||
neighbor peerlink.2 route-map me->peer.2 out
|
||||
|
||||
neighbor firewall allowas-in 1
|
||||
neighbor firewall soft-reconfiguration inbound
|
||||
neighbor firewall route-map inside->firewall out
|
||||
{% for iface in ifaces_firewall %}
|
||||
neighbor {{ iface }}.2 route-map firewall-{{ loop.index }}->inside in
|
||||
{% endfor %}
|
||||
|
||||
redistribute connected route-map loopback-inside
|
||||
{% for vlan in my_vlans %}
|
||||
import vrf {{ vlan.name }}
|
||||
{% endfor %}
|
||||
import vrf default
|
||||
import vrf route-map inside-import
|
||||
exit-address-family
|
||||
|
||||
address-family ipv6 unicast
|
||||
neighbor peerlink.2 activate
|
||||
neighbor peerlink.2 soft-reconfiguration inbound
|
||||
neighbor peerlink.2 route-map peer.2->me in
|
||||
neighbor peerlink.2 route-map me->peer.2 out
|
||||
|
||||
neighbor firewall activate
|
||||
neighbor firewall allowas-in 1
|
||||
neighbor firewall soft-reconfiguration inbound
|
||||
neighbor firewall route-map inside->firewall out
|
||||
{% for iface in ifaces_firewall %}
|
||||
neighbor {{ iface }}.2 route-map firewall-{{ loop.index }}->inside in
|
||||
{% endfor %}
|
||||
|
||||
redistribute connected route-map loopback-inside
|
||||
{% for vlan in my_vlans %}
|
||||
import vrf {{ vlan.name }}
|
||||
{% endfor %}
|
||||
import vrf default
|
||||
import vrf route-map inside-import
|
||||
exit-address-family
|
||||
|
||||
|
||||
{% for vlan in my_vlans %}
|
||||
# VRF for L2 network {{ vlan.name }}. Imports gateway from inside VRF.
|
||||
router bgp {{ asn.asn }} vrf {{ vlan.name }}
|
||||
bgp bestpath as-path multipath-relax
|
||||
|
||||
address-family ipv4 unicast
|
||||
redistribute connected
|
||||
import vrf inside
|
||||
import vrf route-map office-import
|
||||
exit-address-family
|
||||
|
||||
address-family ipv6 unicast
|
||||
redistribute connected
|
||||
import vrf inside
|
||||
import vrf route-map office-import
|
||||
exit-address-family
|
||||
|
||||
{% endfor %}
|
||||
|
||||
# Prefix lists.
|
||||
ip prefix-list default permit 0.0.0.0/0
|
||||
ipv6 prefix-list default permit ::/0
|
||||
|
||||
ip prefix-list fabric permit 10.34.0.0/24 ge 32
|
||||
ipv6 prefix-list fabric permit 2001:1470:fffd:3400::/64 ge 128
|
||||
|
||||
{% for vlan in my_vlans %}
|
||||
{% set prefixes = query('netbox.netbox.nb_lookup', 'prefixes', api_filter='vlan_id='~vlan.id, raw_data=true) %}
|
||||
{% for prefix in prefixes %}
|
||||
{% if prefix.family.value == 4 %}
|
||||
ip prefix-list office permit {{ prefix.prefix }} ge 24
|
||||
{% else %}
|
||||
ipv6 prefix-list office permit {{ prefix.prefix }} ge 64
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
ip prefix-list vpn permit {{ wg_net | ipaddr('subnet') }}
|
||||
|
||||
ip prefix-list nat permit {{ wg_ip | ipaddr('host') }}
|
||||
{% for network in nat %}
|
||||
ip prefix-list nat permit {{ network }}
|
||||
{% endfor %}
|
||||
|
||||
{% for prefix in query('netbox.netbox.nb_lookup', 'prefixes', raw_data=true, api_filter='role=bgp') | selectattr('tenant') %}
|
||||
{% if prefix.family.value == 4 %}
|
||||
ip prefix-list dc permit {{ prefix.prefix }} ge 32
|
||||
{% else %}
|
||||
ipv6 prefix-list dc permit {{ prefix.prefix }} ge 64
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# Route maps for redistributing own IPs from various VRFs.
|
||||
route-map loopback permit 1
|
||||
match interface lo
|
||||
route-map loopback-inside permit 1
|
||||
match interface inside
|
||||
route-map loopback-outside permit 1
|
||||
match interface outside
|
||||
|
||||
# Route maps for importing between VRFs.
|
||||
route-map default-import permit 10
|
||||
match ip address prefix-list default
|
||||
route-map default-import permit 11
|
||||
match ipv6 address prefix-list default
|
||||
route-map default-import permit 21
|
||||
match ipv6 address prefix-list office
|
||||
route-map default-import permit 30
|
||||
match ip address prefix-list nat
|
||||
|
||||
route-map outside-import permit 10
|
||||
match ip address prefix-list dc
|
||||
route-map outside-import permit 11
|
||||
match ipv6 address prefix-list dc
|
||||
|
||||
route-map office-import permit 10
|
||||
match ip address prefix-list default
|
||||
route-map office-import permit 11
|
||||
match ipv6 address prefix-list default
|
||||
|
||||
route-map inside-import permit 20
|
||||
match ip address prefix-list office
|
||||
route-map inside-import permit 21
|
||||
match ipv6 address prefix-list office
|
||||
|
||||
# Route maps for advertised and received routes.
|
||||
# Inside ↔ fabric.
|
||||
route-map default->fabric permit 10
|
||||
match ip address prefix-list default
|
||||
route-map default->fabric permit 11
|
||||
match ipv6 address prefix-list default
|
||||
route-map default->fabric permit 20
|
||||
match ip address prefix-list fabric
|
||||
|
||||
route-map fabric->default permit 10
|
||||
match ip address prefix-list fabric
|
||||
route-map fabric->default permit 20
|
||||
match ip address prefix-list dc
|
||||
route-map fabric->default permit 21
|
||||
match ipv6 address prefix-list dc
|
||||
|
||||
# Inside ↔ firewall.
|
||||
route-map inside->firewall permit 1
|
||||
match interface lo
|
||||
route-map inside->firewall permit 20
|
||||
match ip address prefix-list office
|
||||
route-map inside->firewall permit 21
|
||||
match ipv6 address prefix-list office
|
||||
|
||||
route-map firewall->inside permit 1
|
||||
match ip address prefix-list fabric
|
||||
route-map firewall->inside permit 2
|
||||
match ipv6 address prefix-list fabric
|
||||
route-map firewall->inside permit 10
|
||||
match ip address prefix-list default
|
||||
route-map firewall->inside permit 11
|
||||
match ipv6 address prefix-list default
|
||||
|
||||
# Outside ↔ firewall.
|
||||
route-map outside->firewall permit 10
|
||||
match ip address prefix-list default
|
||||
route-map outside->firewall permit 11
|
||||
match ipv6 address prefix-list default
|
||||
|
||||
route-map firewall->outside permit 1
|
||||
match ip address prefix-list fabric
|
||||
route-map firewall->outside permit 2
|
||||
match ipv6 address prefix-list fabric
|
||||
route-map firewall->outside permit 21
|
||||
match ipv6 address prefix-list office
|
||||
route-map firewall->outside permit 30
|
||||
match ip address prefix-list nat
|
||||
|
||||
# Tag routes from each firewall. Set weight for primary to 200 and secondary to 100.
|
||||
{% for firewall in ifaces_firewall %}
|
||||
route-map firewall-{{ loop.index }}->inside permit 1
|
||||
set tag {{ loop.index }}
|
||||
set weight {{ 100 * loop.index }}
|
||||
call firewall->inside
|
||||
route-map firewall-{{ loop.index }}->outside permit 1
|
||||
set tag {{ loop.index }}
|
||||
set weight {{ 100 * loop.index }}
|
||||
call firewall->outside
|
||||
{% endfor %}
|
||||
|
||||
# Backup routes over peer link are announced to the peer with BGP
|
||||
# metrics 190 and 90. These values are copied to weights by receiving
|
||||
# peer, to be used alongside local routes with weights 200 and 100.
|
||||
# These are the route maps for peerlink in the inside VRF.
|
||||
{% for firewall in ifaces_firewall %}
|
||||
{% set metric = 100 * loop.index - 10 %}
|
||||
route-map me->peer.2 permit {{ loop.index }}
|
||||
match tag {{ loop.index }}
|
||||
on-match goto 100
|
||||
set metric {{ metric }}
|
||||
route-map peer.2->me permit {{ loop.index }}
|
||||
match metric {{ metric }}
|
||||
on-match goto 100
|
||||
set weight {{ metric }}
|
||||
{% endfor %}
|
||||
|
||||
# Advertised backup routes for paths that go through the firewall
|
||||
# (default route).
|
||||
route-map me->peer.2 permit 110
|
||||
match ip address prefix-list default
|
||||
route-map me->peer.2 permit 111
|
||||
match ipv6 address prefix-list default
|
||||
|
||||
# Received backup routes (same as above).
|
||||
route-map peer.2->me permit 110
|
||||
match ip address prefix-list default
|
||||
route-map peer.2->me permit 111
|
||||
match ipv6 address prefix-list default
|
||||
|
||||
# These are the route maps for peerlink in the outside VRF.
|
||||
{% for firewall in ifaces_firewall %}
|
||||
{% set metric = 100 * loop.index - 10 %}
|
||||
route-map me->peer.4 permit {{ loop.index }}
|
||||
match tag {{ loop.index }}
|
||||
on-match goto 100
|
||||
set metric {{ metric }}
|
||||
route-map peer.4->me permit {{ loop.index }}
|
||||
match metric {{ metric }}
|
||||
on-match goto 100
|
||||
set weight {{ metric }}
|
||||
{% endfor %}
|
||||
|
||||
# Backup routes for uplink and paths that go through the firewall
|
||||
# (default route and NAT/IPv6 addresses for office networks).
|
||||
route-map me->peer.4 permit 110
|
||||
match ip address prefix-list default
|
||||
route-map me->peer.4 permit 111
|
||||
match ipv6 address prefix-list default
|
||||
route-map me->peer.4 permit 120
|
||||
match ip address prefix-list nat
|
||||
route-map me->peer.4 permit 131
|
||||
match ipv6 address prefix-list office
|
||||
|
||||
# Received backup routes (same as above).
|
||||
route-map peer.4->me permit 110
|
||||
match ip address prefix-list default
|
||||
route-map peer.4->me permit 111
|
||||
match ipv6 address prefix-list default
|
||||
route-map peer.4->me permit 120
|
||||
match ip address prefix-list nat
|
||||
route-map peer.4->me permit 131
|
||||
match ipv6 address prefix-list office
|
16
roles/exit/templates/isc-dhcp-relay.j2
Normal file
16
roles/exit/templates/isc-dhcp-relay.j2
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% set bridge = interfaces | selectattr('type') | selectattr('type.value', '==', 'bridge') | first %}
|
||||
{% set dhcp_networks = query('netbox.netbox.nb_lookup', 'prefixes', api_filter='role=dhcp-pool', raw_data=true)
|
||||
| selectattr('vlan') | map(attribute='vlan.vid') | sort -%}
|
||||
|
||||
# What servers should the DHCP relay forward requests to?
|
||||
SERVERS="{{ dhcp }}"
|
||||
|
||||
# On what interfaces should the DHCP relay (dhrelay) serve DHCP requests?
|
||||
# Always include the interface towards the DHCP server.
|
||||
# This variable requires a -i for each interface configured above.
|
||||
# This will be used in the actual dhcrelay command
|
||||
# For example, "-i eth0 -i eth1"
|
||||
INTF_CMD="{{ bridge.tagged_vlans | map(attribute='vid') | intersect(dhcp_networks) | sort | map('regex_replace', '^', '-id bridge.') | join(' ') }} -iu {{ iface_uplink }} -iu peerlink.4"
|
||||
|
||||
# Additional options that are passed to the DHCP relay daemon?
|
||||
OPTIONS="-U outside"
|
22
roles/exit/templates/keepalived.conf.j2
Normal file
22
roles/exit/templates/keepalived.conf.j2
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% set exits = [inventory_hostname, peer] -%}
|
||||
|
||||
global_defs {
|
||||
enable_script_security
|
||||
script_user root
|
||||
}
|
||||
|
||||
vrrp_instance dhcrelay {
|
||||
virtual_router_id 50
|
||||
virtual_ipaddress { 169.254.1.1/24 }
|
||||
interface peerlink.4
|
||||
{% for exit in exits %}
|
||||
@{{ exit }} priority {{ loop.index }}
|
||||
@{{ exit }} unicast_src_ip {{ "169.254.1.0/24" | ipaddr(loop.index + 1) | ipaddr('address') }}
|
||||
{% endfor %}
|
||||
unicast_peer {
|
||||
{% for exit in exits %}
|
||||
@^{{ exit }} {{ "169.254.1.0/24" | ipaddr(loop.index + 1) | ipaddr('address') }}
|
||||
{% endfor %}
|
||||
}
|
||||
notify /usr/local/bin/keepalive-service
|
||||
}
|
35
roles/exit/templates/networks.intf.j2
Normal file
35
roles/exit/templates/networks.intf.j2
Normal file
|
@ -0,0 +1,35 @@
|
|||
{# Note that there must be exactly one VLAN-aware bridge. #}
|
||||
{% set bridge = interfaces | selectattr('type') | selectattr('type.value', '==', 'bridge') | first %}
|
||||
{% set my_vlans = bridge.tagged_vlans | sort(attribute='vid') -%}
|
||||
|
||||
# VRFs.
|
||||
{% for vlan in my_vlans %}
|
||||
auto {{ vlan.name }}
|
||||
iface {{ vlan.name }}
|
||||
vrf-table auto
|
||||
|
||||
{% endfor %}
|
||||
|
||||
# Interfaces.
|
||||
{% for vlan in my_vlans %}
|
||||
{% set prefixes = query('netbox.netbox.nb_lookup', 'prefixes', api_filter='vlan_id='~vlan.id, raw_data=true)
|
||||
| map(attribute='prefix') %}
|
||||
auto {{ bridge.name }}.{{ vlan.vid }}
|
||||
iface {{ bridge.name }}.{{ vlan.vid }}
|
||||
vrf {{ vlan.name }}
|
||||
mtu 9216
|
||||
{% if peer is defined %}
|
||||
{% set my_index = inventory_hostname.split('-')[1]|int %}
|
||||
{% for prefix in prefixes %}
|
||||
address {{ prefix | ipaddr(1 + my_index) }}
|
||||
{% endfor %}
|
||||
{% if prefixes %}
|
||||
address-virtual 00:00:5e:00:01:01 {{ prefixes | ipaddr(1) | join(' ') }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% for prefix in prefixes %}
|
||||
address {{ prefix }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
16
roles/exit/templates/radvd.conf.j2
Normal file
16
roles/exit/templates/radvd.conf.j2
Normal file
|
@ -0,0 +1,16 @@
|
|||
{# Note that there must be exactly one VLAN-aware bridge. #}
|
||||
{% set bridge = interfaces | selectattr('type') | selectattr('type.value', '==', 'bridge') | first %}
|
||||
{% set my_vlans = bridge.tagged_vlans | sort(attribute='vid') -%}
|
||||
|
||||
# Send IPv6 RAs from virtual router IP for each network. Also set DNS options.
|
||||
# Both exits announce the same gateway, so don’t revoke it if we go down.
|
||||
{% for vlan in my_vlans %}
|
||||
interface bridge-{{ vlan.vid }}-v0 {
|
||||
AdvSendAdvert on;
|
||||
RemoveAdvOnExit off;
|
||||
prefix ::/64;
|
||||
RDNSS {{ dns6 | join(' ') }} { };
|
||||
DNSSL {{ domain }} { };
|
||||
};
|
||||
|
||||
{% endfor %}
|
Loading…
Add table
Add a link
Reference in a new issue