Initial commit, squashed
This commit is contained in:
		
						commit
						158e8740b8
					
				
					 83 changed files with 2718 additions and 0 deletions
				
			
		
							
								
								
									
										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
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue