230 lines
8.5 KiB
YAML
230 lines
8.5 KiB
YAML
---
|
|
# Configure laconic-mia-sw01 for validator traffic relay (inbound + outbound)
|
|
#
|
|
# Outbound: Redirects outbound traffic from biscayne (src 137.239.194.65)
|
|
# arriving via the doublezero0 GRE tunnel to was-sw01 via the backbone,
|
|
# preventing BCP38 drops at mia-sw01's ISP uplink.
|
|
#
|
|
# Inbound: Routes traffic destined to 137.239.194.65 from the default VRF
|
|
# to biscayne via Tunnel500 in vrf1. Without this, mia-sw01 sends
|
|
# 137.239.194.65 out the ISP uplink back to was-sw01 (routing loop).
|
|
#
|
|
# Approach: The existing per-tunnel ACL (SEC-USER-500-IN) controls what
|
|
# traffic enters vrf1 from Tunnel500. We add 137.239.194.65 to the ACL
|
|
# and add a default route in vrf1 via egress-vrf default pointing to
|
|
# was-sw01's backbone IP. For inbound, an inter-VRF static route in the
|
|
# default VRF forwards 137.239.194.65/32 to biscayne via Tunnel500.
|
|
#
|
|
# The other vrf1 tunnels (502, 504, 505) have their own ACLs that only
|
|
# permit their specific source IPs, so the default route won't affect them.
|
|
#
|
|
# Usage:
|
|
# # Pre-flight checks only (safe, read-only)
|
|
# ansible-playbook -i inventory/switches.yml playbooks/ashburn-relay-mia-sw01.yml
|
|
#
|
|
# # Apply config (after reviewing pre-flight output)
|
|
# ansible-playbook -i inventory/switches.yml playbooks/ashburn-relay-mia-sw01.yml \
|
|
# -e apply=true
|
|
#
|
|
# # Commit persisted config
|
|
# ansible-playbook -i inventory/switches.yml playbooks/ashburn-relay-mia-sw01.yml -e commit=true
|
|
#
|
|
# # Rollback
|
|
# ansible-playbook -i inventory/switches.yml playbooks/ashburn-relay-mia-sw01.yml -e rollback=true
|
|
|
|
- name: Configure mia-sw01 outbound validator redirect
|
|
hosts: mia-sw01
|
|
gather_facts: false
|
|
|
|
vars:
|
|
ashburn_ip: 137.239.194.65
|
|
apply: false
|
|
commit: false
|
|
rollback: false
|
|
tunnel_interface: Tunnel500
|
|
tunnel_vrf: vrf1
|
|
tunnel_acl: SEC-USER-500-IN
|
|
tunnel_nexthop: 169.254.7.7 # biscayne's end of the Tunnel500 /31
|
|
backbone_interface: Ethernet4/1
|
|
session_name: validator-outbound
|
|
checkpoint_name: pre-validator-outbound
|
|
|
|
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
|
|
|
|
# ------------------------------------------------------------------
|
|
# Commit finalization
|
|
# ------------------------------------------------------------------
|
|
- name: Finalize pending session
|
|
when: commit | bool
|
|
block:
|
|
- name: Commit session and write memory
|
|
arista.eos.eos_command:
|
|
commands:
|
|
- "configure session {{ session_name }} commit"
|
|
- write memory
|
|
register: commit_result
|
|
|
|
- name: Show commit result
|
|
ansible.builtin.debug:
|
|
var: commit_result.stdout_lines
|
|
|
|
- name: End play after commit
|
|
ansible.builtin.meta: end_play
|
|
|
|
# ------------------------------------------------------------------
|
|
# Pre-flight checks (always run unless commit/rollback)
|
|
# ------------------------------------------------------------------
|
|
- name: Show tunnel interface config
|
|
arista.eos.eos_command:
|
|
commands:
|
|
- "show running-config interfaces {{ tunnel_interface }}"
|
|
register: tunnel_config
|
|
tags: [preflight]
|
|
|
|
- name: Display tunnel config
|
|
ansible.builtin.debug:
|
|
var: tunnel_config.stdout_lines
|
|
tags: [preflight]
|
|
|
|
- name: Show tunnel ACL
|
|
arista.eos.eos_command:
|
|
commands:
|
|
- "show running-config | section ip access-list {{ tunnel_acl }}"
|
|
register: acl_config
|
|
tags: [preflight]
|
|
|
|
- name: Display tunnel ACL
|
|
ansible.builtin.debug:
|
|
var: acl_config.stdout_lines
|
|
tags: [preflight]
|
|
|
|
- name: Check VRF routing
|
|
arista.eos.eos_command:
|
|
commands:
|
|
- "show ip route vrf {{ tunnel_vrf }} 0.0.0.0/0"
|
|
- "show ip route vrf {{ tunnel_vrf }} {{ backbone_peer }}"
|
|
- "show ip route {{ backbone_peer }}"
|
|
- "show ip route {{ ashburn_ip }}"
|
|
register: vrf_routing
|
|
tags: [preflight]
|
|
|
|
- name: Display VRF routing check
|
|
ansible.builtin.debug:
|
|
var: vrf_routing.stdout_lines
|
|
tags: [preflight]
|
|
|
|
- name: Pre-flight summary
|
|
when: not (apply | bool)
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
=== Pre-flight complete ===
|
|
Review the output above:
|
|
1. {{ tunnel_interface }} ACL ({{ tunnel_acl }}): does it permit src {{ ashburn_ip }}?
|
|
2. {{ tunnel_vrf }} default route: does one exist?
|
|
3. Backbone nexthop {{ backbone_peer }}: reachable in default VRF?
|
|
|
|
To apply config:
|
|
ansible-playbook -i inventory/switches.yml playbooks/ashburn-relay-mia-sw01.yml \
|
|
-e apply=true
|
|
tags: [preflight]
|
|
|
|
- name: End play if not applying
|
|
when: not (apply | bool)
|
|
ansible.builtin.meta: end_play
|
|
|
|
# ------------------------------------------------------------------
|
|
# Apply config via session with 5-minute auto-revert
|
|
# ------------------------------------------------------------------
|
|
- 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 }}"
|
|
# Permit Ashburn IP through the tunnel ACL (insert before deny)
|
|
- command: "ip access-list {{ tunnel_acl }}"
|
|
- command: "45 permit ip host {{ ashburn_ip }} any"
|
|
- command: exit
|
|
# Default route in vrf1 via backbone to was-sw01 (egress-vrf default)
|
|
# Safe because per-tunnel ACLs already restrict what enters vrf1
|
|
- command: "ip route vrf {{ tunnel_vrf }} 0.0.0.0/0 egress-vrf default {{ backbone_interface }} {{ backbone_peer }}"
|
|
# Inbound: route traffic for ashburn IP from default VRF to biscayne via tunnel.
|
|
# Without this, mia-sw01 sends 137.239.194.65 out the ISP uplink → routing loop.
|
|
# NOTE: nexthop only, no interface — EOS silently drops cross-VRF routes that
|
|
# specify a tunnel interface (accepts in config but never installs in RIB).
|
|
- command: "ip route {{ ashburn_ip }}/32 egress-vrf {{ tunnel_vrf }} {{ tunnel_nexthop }}"
|
|
|
|
- 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
|
|
|
|
- name: Commit with 5-minute auto-revert
|
|
arista.eos.eos_command:
|
|
commands:
|
|
- "configure session {{ session_name }} commit timer 00:05:00"
|
|
|
|
# ------------------------------------------------------------------
|
|
# Verify
|
|
# ------------------------------------------------------------------
|
|
- name: Verify config
|
|
arista.eos.eos_command:
|
|
commands:
|
|
- "show running-config | section ip access-list {{ tunnel_acl }}"
|
|
- "show ip route vrf {{ tunnel_vrf }} 0.0.0.0/0"
|
|
- "show ip route {{ ashburn_ip }}"
|
|
register: verify
|
|
|
|
- name: Display verification
|
|
ansible.builtin.debug:
|
|
var: verify.stdout_lines
|
|
|
|
- name: Reminder
|
|
ansible.builtin.debug:
|
|
msg: |
|
|
=== Config applied with 5-minute auto-revert ===
|
|
Session: {{ session_name }}
|
|
Checkpoint: {{ checkpoint_name }}
|
|
|
|
Changes applied:
|
|
1. ACL {{ tunnel_acl }}: added "45 permit ip host {{ ashburn_ip }} any"
|
|
2. Default route in {{ tunnel_vrf }}: 0.0.0.0/0 egress-vrf default {{ backbone_interface }} {{ backbone_peer }}
|
|
3. Inbound route: {{ ashburn_ip }}/32 egress-vrf {{ tunnel_vrf }} {{ tunnel_nexthop }}
|
|
|
|
The config will auto-revert in 5 minutes unless committed.
|
|
Verify on the switch, then commit:
|
|
configure session {{ session_name }} commit
|
|
write memory
|
|
|
|
To revert immediately:
|
|
ansible-playbook ... -e rollback=true
|