mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
The NAT lab was the last suite pinning fixed IPv4 subnets, so two overlapping runs collided on the wan and shared-lan bridges. Each run now claims a free /24 for each bridge, scanning candidates and advancing on an overlap while still failing fast on any other network-create error. The claim exports NAT_WAN_PREFIX and NAT_LAN_PREFIX, and every routable address in the compose file and the suite scripts derives from them, with defaults that render exactly what the lab used before. The router-side LANs are deliberately left pinned: they live inside per-container network namespaces, never become docker networks, and cannot collide. An external-network overlay lets the suites attach to the networks the run already claimed instead of creating their own. Two of the three suite scripts had no overlay hook, so they would have requested the claimed range a second time; both now have one. Host veth names are scoped by a short token rather than the full run id, which overruns the fifteen-character interface-name limit at the default run-id length, and the cleanup reaper's pattern is widened to match the new shape. Networks are released inline on every exit path rather than in a trap, since a trap written inside a shell function replaces the script-level handler and would disable the whole run's teardown.
166 lines
4.5 KiB
Bash
Executable File
166 lines
4.5 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
NAT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
ROOT_DIR="$(cd "$NAT_DIR/../.." && pwd)"
|
|
DERIVE_KEYS="$ROOT_DIR/testing/lib/derive_keys.py"
|
|
# Per-run, for the same reason static's and firewall's generators are: this
|
|
# directory is bind-mounted by compose and read back by the suite scripts
|
|
# AFTER the containers are up, so a shared path lets a second run's generator
|
|
# overwrite the npubs a first run is about to ping. Empty suffix renders
|
|
# today's plain path, so a bare invocation is unchanged.
|
|
OUTPUT_DIR="$NAT_DIR/generated-configs${FIPS_CI_NAME_SUFFIX:-}"
|
|
SCENARIO="${1:?usage: generate-configs.sh <cone|symmetric|lan> [mesh-name]}"
|
|
MESH_NAME="${2:-nat-lab-$(date +%s)-$$}"
|
|
|
|
case "$SCENARIO" in
|
|
cone|symmetric|lan|nostr-publish-consume|stun-faults) ;;
|
|
*)
|
|
echo "Unknown scenario: $SCENARIO" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
mkdir -p "$OUTPUT_DIR/$SCENARIO"
|
|
|
|
keys_a="$(python3 "$DERIVE_KEYS" "$MESH_NAME" "a")"
|
|
keys_b="$(python3 "$DERIVE_KEYS" "$MESH_NAME" "b")"
|
|
|
|
nsec_a="$(echo "$keys_a" | awk -F= '/^nsec=/{print $2}')"
|
|
npub_a="$(echo "$keys_a" | awk -F= '/^npub=/{print $2}')"
|
|
nsec_b="$(echo "$keys_b" | awk -F= '/^nsec=/{print $2}')"
|
|
npub_b="$(echo "$keys_b" | awk -F= '/^npub=/{print $2}')"
|
|
|
|
# The two lab bridges. ci-local.sh claims a free /24 for each per run and
|
|
# exports these; unset renders the addresses the lab has always used, so a
|
|
# bare invocation and the GitHub matrix are unaffected.
|
|
wan="${NAT_WAN_PREFIX:-172.31.254}"
|
|
lan="${NAT_LAN_PREFIX:-172.31.10}"
|
|
|
|
relay_addr="ws://${wan}.30:7777"
|
|
stun_addr="stun:${wan}.40:3478"
|
|
if [ "$SCENARIO" = "lan" ] || [ "$SCENARIO" = "nostr-publish-consume" ] \
|
|
|| [ "$SCENARIO" = "stun-faults" ]; then
|
|
relay_addr="ws://${lan}.30:7777"
|
|
stun_addr="stun:${lan}.40:3478"
|
|
fi
|
|
|
|
peer_block_a=$(cat <<EOF
|
|
- npub: "$npub_b"
|
|
alias: "node-b"
|
|
addresses:
|
|
- transport: udp
|
|
addr: "nat"
|
|
priority: 1
|
|
EOF
|
|
)
|
|
|
|
peer_block_b=$(cat <<EOF
|
|
- npub: "$npub_a"
|
|
alias: "node-a"
|
|
addresses:
|
|
- transport: udp
|
|
addr: "nat"
|
|
priority: 1
|
|
EOF
|
|
)
|
|
|
|
if [ "$SCENARIO" = "symmetric" ]; then
|
|
peer_block_a="$peer_block_a"$'\n'" - transport: tcp
|
|
addr: \"${wan}.11:8443\"
|
|
priority: 20"
|
|
peer_block_b="$peer_block_b"$'\n'" - transport: tcp
|
|
addr: \"${wan}.10:8443\"
|
|
priority: 20"
|
|
fi
|
|
|
|
write_config() {
|
|
local output_file="$1"
|
|
local nsec="$2"
|
|
local peer_block="$3"
|
|
|
|
cat > "$output_file" <<EOF
|
|
node:
|
|
identity:
|
|
nsec: "$nsec"
|
|
retry:
|
|
max_retries: 3
|
|
base_interval_secs: 2
|
|
max_backoff_secs: 8
|
|
discovery:
|
|
nostr:
|
|
enabled: true
|
|
advertise: true
|
|
app: "fips.nat.lab.v1"
|
|
advert_relays:
|
|
- "$relay_addr"
|
|
dm_relays:
|
|
- "$relay_addr"
|
|
stun_servers:
|
|
- "$stun_addr"
|
|
signal_ttl_secs: 30
|
|
attempt_timeout_secs: 6
|
|
replay_window_secs: 60
|
|
punch_start_delay_ms: 500
|
|
punch_interval_ms: 100
|
|
punch_duration_ms: 2500
|
|
advert_ttl_secs: 60
|
|
advert_refresh_secs: 20
|
|
|
|
tun:
|
|
enabled: true
|
|
name: fips0
|
|
mtu: 1280
|
|
|
|
dns:
|
|
enabled: true
|
|
port: 5354
|
|
|
|
transports:
|
|
udp:
|
|
bind_addr: "0.0.0.0:2121"
|
|
mtu: 1472
|
|
advertise_on_nostr: true
|
|
public: false
|
|
tcp:
|
|
bind_addr: "0.0.0.0:8443"
|
|
|
|
peers:
|
|
$peer_block
|
|
connect_policy: auto_connect
|
|
auto_reconnect: true
|
|
EOF
|
|
}
|
|
|
|
write_config "$OUTPUT_DIR/$SCENARIO/node-a.yaml" "$nsec_a" "$peer_block_a"
|
|
write_config "$OUTPUT_DIR/$SCENARIO/node-b.yaml" "$nsec_b" "$peer_block_b"
|
|
|
|
# stun-faults runs two real FIPS daemons:
|
|
# stun-fault-node (key "a") — target of tc/iptables faults via the shim
|
|
# stun-fault-peer (key "b") — fault-free peer that publishes a valid
|
|
# overlay advert so the fault-node's
|
|
# traversal actually invokes the STUN client
|
|
# Mutual peering ensures both sides advertise; without a real advert the
|
|
# fault-node would abort at "no overlay advert" and never generate STUN
|
|
# egress. The shim's netem/iptables rules can then meaningfully drop
|
|
# the STUN UDP traffic during Phase 1.
|
|
if [ "$SCENARIO" = "stun-faults" ]; then
|
|
write_config "$OUTPUT_DIR/$SCENARIO/stun-fault-node.yaml" \
|
|
"$nsec_a" "$peer_block_a"
|
|
write_config "$OUTPUT_DIR/$SCENARIO/stun-fault-peer.yaml" \
|
|
"$nsec_b" "$peer_block_b"
|
|
fi
|
|
|
|
cat > "$OUTPUT_DIR/$SCENARIO/npubs.env" <<EOF
|
|
NPUB_A=$npub_a
|
|
NPUB_B=$npub_b
|
|
MESH_NAME=$MESH_NAME
|
|
SCENARIO=$SCENARIO
|
|
EOF
|
|
|
|
echo "Generated NAT lab configs for scenario=$SCENARIO mesh=$MESH_NAME"
|
|
echo "NPUB_A=$npub_a"
|
|
echo "NPUB_B=$npub_b"
|