110 lines
3.4 KiB
Bash
Executable File
110 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# End-to-end test for Ashburn validator relay
|
|
#
|
|
# Sends real packets from the kind node through the full relay path
|
|
# and waits for responses. A response proves both directions work.
|
|
#
|
|
# Outbound: kind node (172.20.0.2:8001) → biscayne mangle (fwmark 0x64)
|
|
# → policy route table ashburn → gre-ashburn → mia-sw01 Tunnel100
|
|
# (VRF relay) → egress-vrf default → backbone Et4/1 → was-sw01 Et1/1
|
|
# → internet (src 137.239.194.65)
|
|
#
|
|
# Inbound: internet → was-sw01 Et1/1 (dst 137.239.194.65) → static route
|
|
# → backbone → mia-sw01 → egress-vrf relay → Tunnel100 → biscayne
|
|
# gre-ashburn → conntrack reverse-SNAT → kind node (172.20.0.2:8001)
|
|
#
|
|
# Runs from the ansible controller host.
|
|
#
|
|
# Usage:
|
|
# ./scripts/test-ashburn-relay.sh
|
|
set -uo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
cd "$SCRIPT_DIR/.."
|
|
|
|
KIND_NODE=laconic-70ce4c4b47e23b85-control-plane
|
|
BISCAYNE_INV=inventory/biscayne.yml
|
|
GOSSIP_PORT=8001
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
|
|
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
|
|
|
|
# Copy test scripts to biscayne (once)
|
|
setup() {
|
|
for f in "$SCRIPT_DIR"/relay-test-*.py; do
|
|
ansible biscayne -i "$BISCAYNE_INV" -m ansible.builtin.copy \
|
|
-a "src=$f dest=/tmp/$(basename "$f") mode=0755" \
|
|
--become >/dev/null 2>&1
|
|
done
|
|
|
|
# Get kind node PID for nsenter (run in its network namespace,
|
|
# use biscayne's python3 since the kind node only has perl)
|
|
KIND_PID=$(ansible biscayne -i "$BISCAYNE_INV" -m ansible.builtin.shell \
|
|
-a "docker inspect --format '{{ '{{' }}.State.Pid{{ '}}' }}' $KIND_NODE" \
|
|
--become 2>&1 | grep -oP '^\d+$' || true)
|
|
|
|
if [[ -z "$KIND_PID" ]]; then
|
|
echo "FATAL: could not get kind node PID"
|
|
exit 1
|
|
fi
|
|
echo "Kind node PID: $KIND_PID"
|
|
}
|
|
|
|
# Run a test script in the kind node's network namespace
|
|
run_test() {
|
|
local name=$1
|
|
shift
|
|
ansible biscayne -i "$BISCAYNE_INV" -m ansible.builtin.shell \
|
|
-a "nsenter --net --target $KIND_PID python3 /tmp/$name $*" \
|
|
--become 2>&1 | grep -E '^OK|^TIMEOUT|^ERROR|^REFUSED|^NOTE' || echo "NO OUTPUT"
|
|
}
|
|
|
|
echo "=== Ashburn Relay End-to-End Test ==="
|
|
echo ""
|
|
|
|
setup
|
|
echo ""
|
|
|
|
# Test 1: UDP sport 8001 → DNS query to 8.8.8.8
|
|
# Triggers: mangle -p udp --sport 8001 → mark → SNAT → tunnel
|
|
echo "--- Test 1: UDP sport $GOSSIP_PORT (DNS query) ---"
|
|
result=$(run_test relay-test-udp.py "$GOSSIP_PORT")
|
|
if echo "$result" | grep -q "^OK"; then
|
|
pass "UDP sport $GOSSIP_PORT: $result"
|
|
else
|
|
fail "UDP sport $GOSSIP_PORT: $result"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 2: TCP sport 8001 → HTTP HEAD to 1.1.1.1
|
|
# Triggers: mangle -p tcp --sport 8001 → mark → SNAT → tunnel
|
|
echo "--- Test 2: TCP sport $GOSSIP_PORT (HTTP request) ---"
|
|
result=$(run_test relay-test-tcp-sport.py "$GOSSIP_PORT")
|
|
if echo "$result" | grep -q "^OK"; then
|
|
pass "TCP sport $GOSSIP_PORT: $result"
|
|
else
|
|
fail "TCP sport $GOSSIP_PORT: $result"
|
|
fi
|
|
echo ""
|
|
|
|
# Test 3: TCP dport 8001 → connect to Solana entrypoint (ip_echo)
|
|
# Triggers: mangle -p tcp --dport 8001 → mark → SNAT → tunnel
|
|
# REFUSED counts as pass — proves the round trip completed.
|
|
echo "--- Test 3: TCP dport $GOSSIP_PORT (ip_echo path) ---"
|
|
result=$(run_test relay-test-tcp-dport.py "$GOSSIP_PORT")
|
|
if echo "$result" | grep -q "^OK"; then
|
|
pass "TCP dport $GOSSIP_PORT: $result"
|
|
else
|
|
fail "TCP dport $GOSSIP_PORT: $result"
|
|
fi
|
|
echo ""
|
|
|
|
# Summary
|
|
echo "=== Results: $PASS passed, $FAIL failed ==="
|
|
if [[ $FAIL -gt 0 ]]; then
|
|
exit 1
|
|
fi
|