- docker-compose.yml: run peer-a and peer-b with TS_USERSPACE=false +
/dev/net/tun device + cap_add. Pin peer-a's WG listen port to 41641
via TS_TAILSCALED_EXTRA_ARGS and publish it to the host so direct
UDP from outside docker has somewhere to land.
- run.sh: use an ephemeral pre-auth key for the test client so
Headscale auto-deletes the test node when its map stream drops
(instead of accumulating hundreds of stale entries that eventually
slow netmap propagation to a crawl). Disable shields-up on both
peers so the kernel firewall doesn't drop inbound tailnet TCP. Tweak
the JSON key extraction to handle pretty-printed output.
- integration.rs: add `test_e2e_tcp_through_tunnel` that brings up
the daemon, dials peer-a's echo server through the proxy, and
asserts the echo body comes back. Currently `#[ignore]`d — the
docker stack runs Headscale over plain HTTP, but Tailscale's client
unconditionally tries TLS to DERP relays ("tls: first record does
not look like a TLS handshake"), so peer-a can never receive
packets we forward via the relay. Unblocking needs either TLS
termination on the docker DERP or running the test inside the same
docker network as peer-a. Test stays in the tree because everything
it tests up to the read timeout is real verified behavior.
67 lines
2.7 KiB
Bash
Executable File
67 lines
2.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Integration test runner for sunbeam-net.
|
|
#
|
|
# Spins up Headscale + two Tailscale peers, creates pre-auth keys,
|
|
# runs the Rust integration tests, then tears everything down.
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
|
|
COMPOSE="docker compose -f docker-compose.yml"
|
|
cleanup() { $COMPOSE down -v 2>/dev/null; }
|
|
trap cleanup EXIT
|
|
|
|
echo "==> Starting Headscale..."
|
|
$COMPOSE up -d headscale
|
|
$COMPOSE exec -T headscale sh -c 'until headscale health 2>/dev/null; do sleep 1; done'
|
|
|
|
echo "==> Creating pre-auth keys..."
|
|
# Helper that handles both compact and pretty-printed JSON shapes from
|
|
# headscale preauthkeys create.
|
|
extract_key() {
|
|
grep -o '"key":[[:space:]]*"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/'
|
|
}
|
|
# Test client uses an ephemeral key so headscale auto-deletes the node when
|
|
# the streaming map connection drops, keeping the test database clean.
|
|
PEER_A_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | extract_key)
|
|
PEER_B_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | extract_key)
|
|
CLIENT_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --ephemeral --expiration 1h -o json | extract_key)
|
|
|
|
echo "==> Starting peers..."
|
|
PEER_A_AUTH_KEY="$PEER_A_KEY" PEER_B_AUTH_KEY="$PEER_B_KEY" $COMPOSE up -d peer-a peer-b echo
|
|
|
|
echo "==> Waiting for peers to register..."
|
|
for i in $(seq 1 30); do
|
|
NODES=$($COMPOSE exec -T headscale headscale nodes list -o json 2>/dev/null | grep -c '"id"' || true)
|
|
if [ "$NODES" -ge 2 ]; then
|
|
echo " $NODES peers registered."
|
|
break
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
# In TUN mode tailscale installs a stateful firewall that DROPs incoming
|
|
# tailnet traffic by default. Disable it on both peers so the integration
|
|
# tests can actually exchange TCP through the tunnel.
|
|
echo "==> Disabling tailscale firewall on peers..."
|
|
$COMPOSE exec -T peer-a tailscale set --shields-up=false 2>/dev/null || true
|
|
$COMPOSE exec -T peer-b tailscale set --shields-up=false 2>/dev/null || true
|
|
|
|
# Get the server's Noise public key
|
|
SERVER_KEY=$($COMPOSE exec -T headscale cat /var/lib/headscale/noise_private.key 2>/dev/null | head -1 || echo "")
|
|
|
|
echo "==> Peer A tailnet IP:"
|
|
$COMPOSE exec -T peer-a tailscale ip -4 || true
|
|
|
|
echo "==> Peer B tailnet IP:"
|
|
$COMPOSE exec -T peer-b tailscale ip -4 || true
|
|
|
|
echo "==> Running integration tests..."
|
|
cd ../..
|
|
SUNBEAM_NET_TEST_AUTH_KEY="$CLIENT_KEY" \
|
|
SUNBEAM_NET_TEST_COORD_URL="http://localhost:8080" \
|
|
SUNBEAM_NET_TEST_PEER_A_IP=$($COMPOSE -f sunbeam-net/tests/docker-compose.yml exec -T peer-a tailscale ip -4 2>/dev/null | tr -d '[:space:]') \
|
|
cargo test -p sunbeam-net --features integration --test integration -- --nocapture
|
|
|
|
echo "==> Done."
|