Files
fips/testing/static/docker-compose.yml
T
Johnathan Corgan b643eb3a89 testing: port admission-cap integration test to the Noise XX handshake
The admission-cap suite asserted IK wire sizes (inbound Msg1 len 84,
outbound Msg2 len 104) to verify the inbound max_peers cap. On the XX
handshake those sizes differ and Msg2 is always sent before identity is
known, so the IK discriminator matched nothing and the suite failed
despite the cap working correctly.

Replace the wire-size discriminator with a protocol-agnostic cap-holds
invariant: each denied peer must keep re-initiating handshakes
(sustained inbound, size-agnostic), no denied peer may be promoted to an
active session, the node must log cap-enforcement events, and the capped
node must hold exactly max_peers. Raise node-c's handshake logging to
debug in the mesh profile so the early-gate drop is visible alongside the
late-check rejection.

Also record in the changelog that for peers the node also dials, the cap
is enforced by the retained late check rather than the early msg3 drop.
2026-05-29 00:20:29 +00:00

628 lines
18 KiB
YAML

networks:
fips-net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/24
gateway-lan:
driver: bridge
enable_ipv6: true
ipam:
config:
- subnet: 172.20.1.0/24
- subnet: fd02::/64
x-fips-common: &fips-common
image: ${FIPS_TEST_IMAGE:-fips-test:latest}
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
restart: "no"
env_file:
- ./generated-configs/npubs.env
environment:
- RUST_LOG=info
# Passthrough for A/B benchmarking — set on the host shell before
# `docker compose up` to override the worker-pool defaults.
- FIPS_ENCRYPT_WORKERS=${FIPS_ENCRYPT_WORKERS:-}
- FIPS_DECRYPT_WORKERS=${FIPS_DECRYPT_WORKERS:-}
- FIPS_PERF=${FIPS_PERF:-0}
- FIPS_PERF_INTERVAL_SECS=${FIPS_PERF_INTERVAL_SECS:-5}
services:
# ── Mesh topology ──────────────────────────────────────────────
node-a:
<<: *fips-common
profiles: ["mesh"]
container_name: fips-node-a
hostname: node-a
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
node-b:
<<: *fips-common
profiles: ["mesh"]
container_name: fips-node-b
hostname: node-b
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
node-c:
<<: *fips-common
profiles: ["mesh"]
container_name: fips-node-c
hostname: node-c
environment:
- RUST_LOG=info,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
node-d:
<<: *fips-common
profiles: ["mesh"]
container_name: fips-node-d
hostname: node-d
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
node-e:
<<: *fips-common
profiles: ["mesh"]
container_name: fips-node-e
hostname: node-e
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh/node-e.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.14
# ── Mesh-public topology (mesh + external public node) ────────
pub-a:
<<: *fips-common
profiles: ["mesh-public"]
container_name: fips-node-a
hostname: node-a
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh-public/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
pub-b:
<<: *fips-common
profiles: ["mesh-public"]
container_name: fips-node-b
hostname: node-b
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh-public/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
pub-c:
<<: *fips-common
profiles: ["mesh-public"]
container_name: fips-node-c
hostname: node-c
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh-public/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
pub-d:
<<: *fips-common
profiles: ["mesh-public"]
container_name: fips-node-d
hostname: node-d
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh-public/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
pub-e:
<<: *fips-common
profiles: ["mesh-public"]
container_name: fips-node-e
hostname: node-e
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mesh-public/node-e.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.14
# ── Chain topology (A-B-C-D-E) ────────────────────────────────
chain-a:
<<: *fips-common
profiles: ["chain"]
container_name: fips-node-a
hostname: node-a
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/chain/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
chain-b:
<<: *fips-common
profiles: ["chain"]
container_name: fips-node-b
hostname: node-b
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/chain/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
chain-c:
<<: *fips-common
profiles: ["chain"]
container_name: fips-node-c
hostname: node-c
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/chain/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
chain-d:
<<: *fips-common
profiles: ["chain"]
container_name: fips-node-d
hostname: node-d
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/chain/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
chain-e:
<<: *fips-common
profiles: ["chain"]
container_name: fips-node-e
hostname: node-e
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/chain/node-e.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.14
# ── Rekey integration test (mesh + aggressive rekey timers) ──
rekey-a:
<<: *fips-common
profiles: ["rekey"]
container_name: fips-node-a
hostname: node-a
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
rekey-b:
<<: *fips-common
profiles: ["rekey"]
container_name: fips-node-b
hostname: node-b
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
rekey-c:
<<: *fips-common
profiles: ["rekey"]
container_name: fips-node-c
hostname: node-c
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
rekey-d:
<<: *fips-common
profiles: ["rekey"]
container_name: fips-node-d
hostname: node-d
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
rekey-e:
<<: *fips-common
profiles: ["rekey"]
container_name: fips-node-e
hostname: node-e
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey/node-e.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.14
# ── Rekey + accept_connections=false on node b ──────────────────
# Exercises the auto_connect-initiator-with-accept-off regression
# class. Same 5-node mesh, but node b's generated config has
# `transports.udp.accept_connections: false` (injected by
# rekey-test.sh's inject-config when REKEY_ACCEPT_OFF_NODES=b).
rekey-accept-off-a:
<<: *fips-common
profiles: ["rekey-accept-off"]
container_name: fips-node-a
hostname: node-a
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-accept-off/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
rekey-accept-off-b:
<<: *fips-common
profiles: ["rekey-accept-off"]
container_name: fips-node-b
hostname: node-b
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-accept-off/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
rekey-accept-off-c:
<<: *fips-common
profiles: ["rekey-accept-off"]
container_name: fips-node-c
hostname: node-c
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-accept-off/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
rekey-accept-off-d:
<<: *fips-common
profiles: ["rekey-accept-off"]
container_name: fips-node-d
hostname: node-d
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-accept-off/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
rekey-accept-off-e:
<<: *fips-common
profiles: ["rekey-accept-off"]
container_name: fips-node-e
hostname: node-e
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-accept-off/node-e.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.14
# ── Rekey topology with udp.outbound_only=true on node b ────
# Exercises the udp.outbound_only rekey-msg1 admission regression
# observed in production 2026-04-30. Same 5-node mesh as
# rekey-accept-off, but node-b's generated config has
# `transports.udp.outbound_only: true` (forces ephemeral bind +
# accept_connections false) AND node-b's peer-c address is
# rewritten to the docker hostname (`node-c:2121`) so the
# `addr_to_link` lookup misses on the inbound numeric source addr.
# Injected by rekey-test.sh's inject-config when
# REKEY_OUTBOUND_ONLY_NODES=b.
rekey-outbound-only-a:
<<: *fips-common
profiles: ["rekey-outbound-only"]
container_name: fips-node-a
hostname: node-a
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-outbound-only/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
rekey-outbound-only-b:
<<: *fips-common
profiles: ["rekey-outbound-only"]
container_name: fips-node-b
hostname: node-b
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-outbound-only/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
rekey-outbound-only-c:
<<: *fips-common
profiles: ["rekey-outbound-only"]
container_name: fips-node-c
hostname: node-c
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-outbound-only/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
rekey-outbound-only-d:
<<: *fips-common
profiles: ["rekey-outbound-only"]
container_name: fips-node-d
hostname: node-d
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-outbound-only/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
rekey-outbound-only-e:
<<: *fips-common
profiles: ["rekey-outbound-only"]
container_name: fips-node-e
hostname: node-e
environment:
- RUST_LOG=info,fips::node::handlers::rekey=debug,fips::node::handlers::handshake=debug
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/rekey-outbound-only/node-e.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.14
# ── TCP chain topology (A-B-C) ───────────────────────────────
tcp-a:
<<: *fips-common
profiles: ["tcp-chain"]
container_name: fips-node-a
hostname: node-a
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/tcp-chain/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
tcp-b:
<<: *fips-common
profiles: ["tcp-chain"]
container_name: fips-node-b
hostname: node-b
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/tcp-chain/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
tcp-c:
<<: *fips-common
profiles: ["tcp-chain"]
container_name: fips-node-c
hostname: node-c
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/tcp-chain/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
# ── Mixed-profile topology ─────────────────────────────────────────
# A (Full) + B (Full) + C (NonRouting) + D (Leaf)
mixed-a:
<<: *fips-common
profiles: ["mixed-profile"]
container_name: fips-node-a
hostname: node-a
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mixed-profile/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
mixed-b:
<<: *fips-common
profiles: ["mixed-profile"]
container_name: fips-node-b
hostname: node-b
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mixed-profile/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
mixed-c:
<<: *fips-common
profiles: ["mixed-profile"]
container_name: fips-node-c
hostname: node-c
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mixed-profile/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
mixed-d:
<<: *fips-common
profiles: ["mixed-profile"]
container_name: fips-node-d
hostname: node-d
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/mixed-profile/node-d.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.13
# ── Gateway integration test (gateway + server + non-FIPS client) ─
gw-gateway:
<<: *fips-common
profiles: ["gateway"]
container_name: fips-gw-gateway
hostname: gw-gateway
# Privileged required: gateway must enable IPv6 on eth1 (second network,
# attached after container start) and manage nftables NAT rules.
privileged: true
environment:
- RUST_LOG=info
- FIPS_TEST_MODE=gateway
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.default.disable_ipv6=0
- net.ipv6.conf.all.forwarding=1
- net.ipv6.conf.all.proxy_ndp=1
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/gateway/node-a.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.10
gateway-lan:
ipv4_address: 172.20.1.10
ipv6_address: fd02::10
gw-server:
<<: *fips-common
profiles: ["gateway"]
container_name: fips-gw-server
hostname: gw-server
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/gateway/node-b.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.11
# Second mesh destination — gives gw-client-2 a distinct npub to target
# so the gateway allocates a separate virtual-IP mapping per LAN client.
# Mirrors gw-server; not on gateway-lan.
gw-server-2:
<<: *fips-common
profiles: ["gateway"]
container_name: fips-gw-server-2
hostname: gw-server-2
volumes:
- ../docker/resolv.conf:/etc/resolv.conf:ro
- ./generated-configs/gateway/node-c.yaml:/etc/fips/fips.yaml:ro
networks:
fips-net:
ipv4_address: 172.20.0.12
gw-client:
image: fips-test-app:latest
profiles: ["gateway"]
container_name: fips-gw-client
hostname: gw-client
cap_add:
- NET_ADMIN
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
volumes:
- ./configs/gateway-resolv.conf:/etc/resolv.conf:ro
networks:
gateway-lan:
ipv4_address: 172.20.1.20
ipv6_address: fd02::20
restart: "no"
env_file:
- ./generated-configs/npubs.env
# Second LAN client — exercises concurrent multi-client mappings.
# Same image and gateway-lan attachment as
# gw-client; the gateway must allocate a distinct virtual IP for it.
gw-client-2:
image: fips-test-app:latest
profiles: ["gateway"]
container_name: fips-gw-client-2
hostname: gw-client-2
cap_add:
- NET_ADMIN
sysctls:
- net.ipv6.conf.all.disable_ipv6=0
volumes:
- ./configs/gateway-resolv.conf:/etc/resolv.conf:ro
networks:
gateway-lan:
ipv4_address: 172.20.1.21
ipv6_address: fd02::21
restart: "no"
env_file:
- ./generated-configs/npubs.env