Skip to content

Commit 31218db

Browse files
committed
test(mesh): assert host_network nodes advertise only addresses of their own VM
assert_direct_paths checked the path tailscale ping settled on, which depends on latency measured during the run. It now also checks that every endpoint each node advertises for itself is an address of its own VM's interfaces, so an endpoint learnt over STUN, which can carry a path through the runner's NAT, fails the scenario on every run that has one rather than on the runs where it happens to win. The bridge addresses its Docker and k3s create are interface addresses of the VM too, so they are allowed.
1 parent 0a766d4 commit 31218db

1 file changed

Lines changed: 10 additions & 1 deletion

File tree

‎tests/mesh/run.sh‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ write_host_network_inventory() {
566566

567567
# With host networking, every node's Tailscale client must reach every other node directly at that node's daemon's own address (its stand-in LAN address), not through a relay, and the node container must publish no port.
568568
assert_direct_paths() {
569-
local index other status deadline
569+
local index other status deadline own outside
570570
for index in $(seq 1 "$node_count"); do
571571
[ "$(docker_on "$index" inspect --format '{{.HostConfig.NetworkMode}}' "$(container "$index")")" = host ] || fail "$(container "$index") is not on the host network"
572572
[ -z "$(docker_on "$index" port "$(container "$index")")" ] || fail "$(container "$index") publishes ports: $(docker_on "$index" port "$(container "$index")")"
@@ -581,6 +581,15 @@ assert_direct_paths() {
581581
echo " $(node_name "$index") -> $(node_name "$other"): $(echo "$status" | tail -n 1)"
582582
done
583583
done
584+
# Every endpoint each node advertises for itself is an address of its own VM's interfaces (the test network address, and the bridges its Docker and k3s create): none is an address learnt over STUN, which belongs to the runner's NAT and would let its peers pick a path through it instead (see start_vms). tailscale status lists a node's own endpoints under Self.Addrs, and none for its peers (UpdateStatus in wgengine/magicsock/magicsock.go of the pinned Tailscale fills Self only). The node container is on its VM's host network, so the VM's interfaces are the node's.
585+
for index in $(seq 1 "$node_count"); do
586+
own=$(docker exec "$(vm "$index")" ip -o addr show | awk '{ split($4, parts, "/"); print parts[1] }')
587+
status=$(docker_on "$index" exec "$(container "$index")" tailscale status --json </dev/null)
588+
outside=$(echo "$status" | python3 -c 'import json, sys
589+
own = set(sys.argv[1].split())
590+
print(" ".join(addr for addr in json.load(sys.stdin)["Self"]["Addrs"] if addr.rsplit(":", 1)[0].strip("[]") not in own))' "$own")
591+
[ -z "$outside" ] || fail "$(node_name "$index") advertises endpoints that are not its own VM's addresses: ${outside}"
592+
done
584593
log "Every node reaches every other directly at its daemon's address"
585594
}
586595

0 commit comments

Comments
 (0)