2026-03-06 21:08:48 +00:00
|
|
|
---
|
2026-03-07 01:47:58 +00:00
|
|
|
# Configure laconic-mia-sw01 for validator traffic relay via dedicated GRE tunnel
|
2026-03-06 21:08:48 +00:00
|
|
|
#
|
2026-03-07 01:47:58 +00:00
|
|
|
# Creates a NEW GRE tunnel (Tunnel100) separate from the DoubleZero-managed
|
|
|
|
|
# Tunnel500. The DZ agent controls Tunnel500's ACL (SEC-USER-500-IN) and
|
|
|
|
|
# overwrites any custom entries, so we cannot use it for validator traffic
|
|
|
|
|
# with src 137.239.194.65.
|
2026-03-07 01:44:25 +00:00
|
|
|
#
|
2026-03-07 01:47:58 +00:00
|
|
|
# Tunnel100 uses mia-sw01's free LAN IP (209.42.167.137) as the tunnel
|
|
|
|
|
# source, and biscayne's public IP (186.233.184.235) as the destination.
|
|
|
|
|
# This tunnel carries traffic over the ISP uplink, completely independent
|
|
|
|
|
# of the DoubleZero overlay.
|
2026-03-06 21:08:48 +00:00
|
|
|
#
|
2026-03-07 23:31:18 +00:00
|
|
|
# Outbound routing uses VRF isolation instead of PBR. Tunnel100 lives in
|
|
|
|
|
# VRF "relay" whose only default route points to was-sw01 via the backbone.
|
|
|
|
|
# Traffic decapsulated from Tunnel100 (src 137.239.194.65) routes via VRF
|
|
|
|
|
# relay's table, which sends it to was-sw01 where the source IP is
|
|
|
|
|
# legitimate. No PBR or traffic-policy needed — the TCAM profile
|
|
|
|
|
# (tunnel-interface-acl) doesn't support either on tunnel interfaces.
|
|
|
|
|
#
|
|
|
|
|
# Inbound: was-sw01 → backbone Et4/1 → mia-sw01 → egress-vrf relay →
|
|
|
|
|
# Tunnel100 → biscayne
|
|
|
|
|
# Outbound: biscayne → Tunnel100 (VRF relay) → egress-vrf default →
|
|
|
|
|
# backbone Et4/1 → was-sw01
|
2026-03-06 21:08:48 +00:00
|
|
|
#
|
|
|
|
|
# Usage:
|
|
|
|
|
# # Pre-flight checks only (safe, read-only)
|
2026-03-07 23:31:18 +00:00
|
|
|
# ansible-playbook -i inventory-switches/switches.yml playbooks/ashburn-relay-mia-sw01.yml
|
2026-03-06 21:08:48 +00:00
|
|
|
#
|
|
|
|
|
# # Apply config (after reviewing pre-flight output)
|
2026-03-07 23:31:18 +00:00
|
|
|
# ansible-playbook -i inventory-switches/switches.yml playbooks/ashburn-relay-mia-sw01.yml \
|
2026-03-06 21:08:48 +00:00
|
|
|
# -e apply=true
|
|
|
|
|
#
|
2026-03-07 01:49:25 +00:00
|
|
|
# # Persist to startup-config (write memory)
|
2026-03-07 23:31:18 +00:00
|
|
|
# ansible-playbook -i inventory-switches/switches.yml playbooks/ashburn-relay-mia-sw01.yml \
|
|
|
|
|
# -e commit=true
|
2026-03-06 21:08:48 +00:00
|
|
|
#
|
|
|
|
|
# # Rollback
|
2026-03-07 23:31:18 +00:00
|
|
|
# ansible-playbook -i inventory-switches/switches.yml playbooks/ashburn-relay-mia-sw01.yml \
|
|
|
|
|
# -e rollback=true
|
2026-03-06 21:08:48 +00:00
|
|
|
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Configure mia-sw01 validator relay tunnel
|
2026-03-07 22:28:21 +00:00
|
|
|
hosts: all
|
2026-03-06 21:08:48 +00:00
|
|
|
gather_facts: false
|
|
|
|
|
|
|
|
|
|
vars:
|
|
|
|
|
ashburn_ip: 137.239.194.65
|
2026-03-07 01:47:58 +00:00
|
|
|
biscayne_ip: 186.233.184.235
|
2026-03-06 21:08:48 +00:00
|
|
|
apply: false
|
|
|
|
|
commit: false
|
|
|
|
|
rollback: false
|
2026-03-07 01:47:58 +00:00
|
|
|
# New tunnel — not managed by DZ agent
|
|
|
|
|
tunnel_interface: Tunnel100
|
|
|
|
|
tunnel_source_ip: 209.42.167.137 # mia-sw01 free LAN IP
|
|
|
|
|
tunnel_local: 169.254.100.0 # /31 link, mia-sw01 side
|
|
|
|
|
tunnel_remote: 169.254.100.1 # /31 link, biscayne side
|
|
|
|
|
tunnel_acl: SEC-VALIDATOR-100-IN
|
|
|
|
|
# Loopback for tunnel source (so it's always up)
|
|
|
|
|
tunnel_source_lo: Loopback101
|
2026-03-07 23:31:18 +00:00
|
|
|
# VRF for outbound routing — isolates tunnel traffic from default table
|
|
|
|
|
tunnel_vrf: relay
|
2026-03-06 21:08:48 +00:00
|
|
|
backbone_interface: Ethernet4/1
|
2026-03-07 01:47:58 +00:00
|
|
|
backbone_peer: 172.16.1.188 # was-sw01 backbone IP
|
|
|
|
|
session_name: validator-tunnel
|
|
|
|
|
checkpoint_name: pre-validator-tunnel
|
2026-03-06 21:08:48 +00:00
|
|
|
|
|
|
|
|
tasks:
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
# Rollback path
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
- name: Rollback to checkpoint
|
|
|
|
|
when: rollback | bool
|
|
|
|
|
block:
|
|
|
|
|
- name: Execute rollback
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- "rollback running-config checkpoint {{ checkpoint_name }}"
|
|
|
|
|
- write memory
|
|
|
|
|
register: rollback_result
|
|
|
|
|
|
|
|
|
|
- name: Show rollback result
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
var: rollback_result.stdout_lines
|
|
|
|
|
|
|
|
|
|
- name: End play after rollback
|
|
|
|
|
ansible.builtin.meta: end_play
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-03-07 01:49:25 +00:00
|
|
|
# Write memory (persist to startup-config)
|
2026-03-06 21:08:48 +00:00
|
|
|
# ------------------------------------------------------------------
|
2026-03-07 01:49:25 +00:00
|
|
|
- name: Write memory to persist config
|
2026-03-06 21:08:48 +00:00
|
|
|
when: commit | bool
|
|
|
|
|
block:
|
2026-03-07 01:49:25 +00:00
|
|
|
- name: Write memory
|
2026-03-06 21:08:48 +00:00
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- write memory
|
2026-03-07 01:49:25 +00:00
|
|
|
register: write_result
|
2026-03-06 21:08:48 +00:00
|
|
|
|
2026-03-07 01:49:25 +00:00
|
|
|
- name: Show write result
|
2026-03-06 21:08:48 +00:00
|
|
|
ansible.builtin.debug:
|
2026-03-07 01:49:25 +00:00
|
|
|
var: write_result.stdout_lines
|
2026-03-06 21:08:48 +00:00
|
|
|
|
2026-03-07 01:49:25 +00:00
|
|
|
- name: End play after write
|
2026-03-06 21:08:48 +00:00
|
|
|
ansible.builtin.meta: end_play
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
# Pre-flight checks (always run unless commit/rollback)
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Check existing tunnel interfaces
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- show ip interface brief | include Tunnel
|
|
|
|
|
register: existing_tunnels
|
|
|
|
|
tags: [preflight]
|
|
|
|
|
|
|
|
|
|
- name: Display existing tunnels
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
var: existing_tunnels.stdout_lines
|
|
|
|
|
tags: [preflight]
|
|
|
|
|
|
|
|
|
|
- name: Check if Tunnel100 already exists
|
2026-03-06 21:08:48 +00:00
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- "show running-config interfaces {{ tunnel_interface }}"
|
|
|
|
|
register: tunnel_config
|
|
|
|
|
tags: [preflight]
|
|
|
|
|
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Display Tunnel100 config
|
2026-03-06 21:08:48 +00:00
|
|
|
ansible.builtin.debug:
|
|
|
|
|
var: tunnel_config.stdout_lines
|
|
|
|
|
tags: [preflight]
|
|
|
|
|
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Check if Loopback101 already exists
|
2026-03-06 21:08:48 +00:00
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
2026-03-07 01:47:58 +00:00
|
|
|
- "show running-config interfaces {{ tunnel_source_lo }}"
|
|
|
|
|
register: lo_config
|
2026-03-06 21:08:48 +00:00
|
|
|
tags: [preflight]
|
|
|
|
|
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Display Loopback101 config
|
2026-03-06 21:08:48 +00:00
|
|
|
ansible.builtin.debug:
|
2026-03-07 01:47:58 +00:00
|
|
|
var: lo_config.stdout_lines
|
2026-03-06 21:08:48 +00:00
|
|
|
tags: [preflight]
|
|
|
|
|
|
2026-03-07 23:31:18 +00:00
|
|
|
- name: Check VRF state
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- "show vrf {{ tunnel_vrf }}"
|
|
|
|
|
register: vrf_check
|
|
|
|
|
tags: [preflight]
|
|
|
|
|
ignore_errors: true
|
|
|
|
|
|
|
|
|
|
- name: Display VRF state
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
var: vrf_check.stdout_lines
|
|
|
|
|
tags: [preflight]
|
|
|
|
|
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Check route for ashburn IP
|
2026-03-06 21:08:48 +00:00
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
2026-03-07 01:44:25 +00:00
|
|
|
- "show ip route {{ ashburn_ip }}"
|
2026-03-07 01:47:58 +00:00
|
|
|
register: route_check
|
2026-03-06 21:08:48 +00:00
|
|
|
tags: [preflight]
|
|
|
|
|
|
2026-03-07 01:47:58 +00:00
|
|
|
- name: Display route check
|
2026-03-06 21:08:48 +00:00
|
|
|
ansible.builtin.debug:
|
2026-03-07 01:47:58 +00:00
|
|
|
var: route_check.stdout_lines
|
2026-03-06 21:08:48 +00:00
|
|
|
tags: [preflight]
|
|
|
|
|
|
|
|
|
|
- name: Pre-flight summary
|
|
|
|
|
when: not (apply | bool)
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
msg: |
|
|
|
|
|
=== Pre-flight complete ===
|
|
|
|
|
Review the output above:
|
2026-03-07 01:47:58 +00:00
|
|
|
1. Does {{ tunnel_interface }} already exist?
|
|
|
|
|
2. Does {{ tunnel_source_lo }} already exist?
|
2026-03-07 23:31:18 +00:00
|
|
|
3. Does VRF {{ tunnel_vrf }} already exist?
|
|
|
|
|
4. Current route for {{ ashburn_ip }}
|
2026-03-07 01:47:58 +00:00
|
|
|
|
|
|
|
|
Planned config:
|
2026-03-07 23:31:18 +00:00
|
|
|
- VRF {{ tunnel_vrf }}: isolates tunnel outbound traffic
|
2026-03-07 01:47:58 +00:00
|
|
|
- {{ tunnel_source_lo }}: {{ tunnel_source_ip }}/32
|
|
|
|
|
- {{ tunnel_interface }}: GRE src {{ tunnel_source_ip }} dst {{ biscayne_ip }}
|
2026-03-07 23:31:18 +00:00
|
|
|
VRF {{ tunnel_vrf }}, link address {{ tunnel_local }}/31
|
2026-03-07 01:47:58 +00:00
|
|
|
ACL {{ tunnel_acl }}: permit src {{ ashburn_ip }}, permit src {{ tunnel_remote }}
|
2026-03-07 23:31:18 +00:00
|
|
|
- Inbound: {{ ashburn_ip }}/32 egress-vrf {{ tunnel_vrf }} via {{ tunnel_remote }}
|
|
|
|
|
- Outbound: 0.0.0.0/0 in VRF {{ tunnel_vrf }} egress-vrf default via {{ backbone_peer }}
|
2026-03-06 21:08:48 +00:00
|
|
|
|
|
|
|
|
To apply config:
|
2026-03-07 23:31:18 +00:00
|
|
|
ansible-playbook -i inventory-switches/switches.yml \
|
|
|
|
|
playbooks/ashburn-relay-mia-sw01.yml -e apply=true
|
2026-03-06 21:08:48 +00:00
|
|
|
tags: [preflight]
|
|
|
|
|
|
|
|
|
|
- name: End play if not applying
|
|
|
|
|
when: not (apply | bool)
|
|
|
|
|
ansible.builtin.meta: end_play
|
|
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
2026-03-07 23:31:18 +00:00
|
|
|
# Apply config via session (checkpoint saved for rollback)
|
2026-03-06 21:08:48 +00:00
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
- name: Save checkpoint
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- "configure checkpoint save {{ checkpoint_name }}"
|
|
|
|
|
|
|
|
|
|
- name: Apply config session
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- command: "configure session {{ session_name }}"
|
2026-03-07 01:47:58 +00:00
|
|
|
# Loopback for tunnel source (always-up interface)
|
|
|
|
|
- command: "interface {{ tunnel_source_lo }}"
|
|
|
|
|
- command: "ip address {{ tunnel_source_ip }}/32"
|
|
|
|
|
- command: exit
|
2026-03-07 23:31:18 +00:00
|
|
|
# VRF for tunnel outbound isolation
|
|
|
|
|
- command: "vrf instance {{ tunnel_vrf }}"
|
|
|
|
|
- command: exit
|
|
|
|
|
- command: "ip routing vrf {{ tunnel_vrf }}"
|
2026-03-07 01:47:58 +00:00
|
|
|
# ACL for the new tunnel — we control this, DZ agent won't touch it
|
2026-03-06 21:08:48 +00:00
|
|
|
- command: "ip access-list {{ tunnel_acl }}"
|
2026-03-07 01:47:58 +00:00
|
|
|
- command: "counters per-entry"
|
|
|
|
|
- command: "10 permit icmp host {{ tunnel_remote }} any"
|
|
|
|
|
- command: "20 permit ip host {{ ashburn_ip }} any"
|
|
|
|
|
- command: "30 permit ip host {{ tunnel_remote }} any"
|
|
|
|
|
- command: "100 deny ip any any"
|
|
|
|
|
- command: exit
|
2026-03-07 23:31:18 +00:00
|
|
|
# GRE tunnel in VRF relay
|
2026-03-07 01:47:58 +00:00
|
|
|
- command: "interface {{ tunnel_interface }}"
|
|
|
|
|
- command: "mtu 9216"
|
2026-03-07 23:31:18 +00:00
|
|
|
- command: "vrf {{ tunnel_vrf }}"
|
2026-03-07 01:47:58 +00:00
|
|
|
- command: "ip address {{ tunnel_local }}/31"
|
|
|
|
|
- command: "ip access-group {{ tunnel_acl }} in"
|
|
|
|
|
- command: "tunnel mode gre"
|
|
|
|
|
- command: "tunnel source {{ tunnel_source_ip }}"
|
|
|
|
|
- command: "tunnel destination {{ biscayne_ip }}"
|
2026-03-06 21:08:48 +00:00
|
|
|
- command: exit
|
2026-03-07 23:31:18 +00:00
|
|
|
# Outbound: default route in VRF relay → backbone → was-sw01
|
|
|
|
|
- command: "ip route vrf {{ tunnel_vrf }} 0.0.0.0/0 egress-vrf default {{ backbone_peer }}"
|
|
|
|
|
# Inbound: route ashburn IP from default VRF into tunnel via VRF relay
|
|
|
|
|
- command: "ip route {{ ashburn_ip }}/32 egress-vrf {{ tunnel_vrf }} {{ tunnel_remote }}"
|
2026-03-06 21:08:48 +00:00
|
|
|
|
|
|
|
|
- name: Show session diff
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
|
|
|
|
- "configure session {{ session_name }}"
|
|
|
|
|
- show session-config diffs
|
|
|
|
|
- exit
|
|
|
|
|
register: session_diff
|
|
|
|
|
|
|
|
|
|
- name: Display session diff
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
var: session_diff.stdout_lines
|
|
|
|
|
|
2026-03-07 01:49:25 +00:00
|
|
|
- name: Commit session (checkpoint saved for rollback)
|
2026-03-06 21:08:48 +00:00
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
2026-03-07 01:49:25 +00:00
|
|
|
- "configure session {{ session_name }} commit"
|
2026-03-06 21:08:48 +00:00
|
|
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
# Verify
|
|
|
|
|
# ------------------------------------------------------------------
|
|
|
|
|
- name: Verify config
|
|
|
|
|
arista.eos.eos_command:
|
|
|
|
|
commands:
|
2026-03-07 01:47:58 +00:00
|
|
|
- "show running-config interfaces {{ tunnel_source_lo }}"
|
|
|
|
|
- "show running-config interfaces {{ tunnel_interface }}"
|
|
|
|
|
- "show ip access-lists {{ tunnel_acl }}"
|
2026-03-07 23:31:18 +00:00
|
|
|
- "show vrf {{ tunnel_vrf }}"
|
2026-03-07 01:44:25 +00:00
|
|
|
- "show ip route {{ ashburn_ip }}"
|
2026-03-07 23:31:18 +00:00
|
|
|
- "show ip route vrf {{ tunnel_vrf }} 0.0.0.0/0"
|
2026-03-06 21:08:48 +00:00
|
|
|
register: verify
|
|
|
|
|
|
|
|
|
|
- name: Display verification
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
var: verify.stdout_lines
|
|
|
|
|
|
|
|
|
|
- name: Reminder
|
|
|
|
|
ansible.builtin.debug:
|
|
|
|
|
msg: |
|
2026-03-07 01:49:25 +00:00
|
|
|
=== Config applied (running-config only) ===
|
2026-03-06 21:08:48 +00:00
|
|
|
Checkpoint: {{ checkpoint_name }}
|
|
|
|
|
|
|
|
|
|
Changes applied:
|
2026-03-07 01:47:58 +00:00
|
|
|
1. {{ tunnel_source_lo }}: {{ tunnel_source_ip }}/32
|
2026-03-07 23:31:18 +00:00
|
|
|
2. VRF {{ tunnel_vrf }}: outbound isolation for tunnel traffic
|
|
|
|
|
3. {{ tunnel_interface }}: GRE tunnel to {{ biscayne_ip }} in VRF {{ tunnel_vrf }}
|
2026-03-07 01:47:58 +00:00
|
|
|
link {{ tunnel_local }}/31, ACL {{ tunnel_acl }}
|
2026-03-07 23:31:18 +00:00
|
|
|
4. Inbound: {{ ashburn_ip }}/32 egress-vrf {{ tunnel_vrf }} via {{ tunnel_remote }}
|
|
|
|
|
5. Outbound: 0.0.0.0/0 in VRF {{ tunnel_vrf }} egress-vrf default via {{ backbone_peer }}
|
2026-03-06 21:08:48 +00:00
|
|
|
|
2026-03-07 01:49:25 +00:00
|
|
|
Config is in running-config but NOT saved to startup-config.
|
|
|
|
|
A reboot will revert to the previous state.
|
|
|
|
|
|
|
|
|
|
To persist (write memory):
|
2026-03-07 01:47:58 +00:00
|
|
|
ansible-playbook ... -e commit=true
|
2026-03-06 21:08:48 +00:00
|
|
|
|
2026-03-07 01:49:25 +00:00
|
|
|
To rollback immediately:
|
2026-03-06 21:08:48 +00:00
|
|
|
ansible-playbook ... -e rollback=true
|