Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions docker-compose.hole-punch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Local reproduction of the libp2p/unified-testing hole-punch topology:
# two peers on isolated LANs, two Linux NAT routers, one WAN relay and Redis
# coordination on a separate network.
#
# Usage: docker compose -f docker-compose.hole-punch.yml up --build \
# --exit-code-from hs-hp-dialer
x-hs-env: &hs-env
REDIS_ADDR: "redis:6379"
TEST_KEY: "cafe0131"
TRANSPORT: tcp
SECURE_CHANNEL: noise
MUXER: yamux

x-router: &router
build:
context: .
dockerfile: interop/hole-punch/router/Dockerfile
cap_add: [NET_ADMIN]
sysctls:
net.ipv4.ip_forward: 1
net.ipv4.conf.all.forwarding: 1
net.ipv4.conf.default.forwarding: 1
net.ipv4.conf.all.rp_filter: 0
net.ipv4.conf.default.rp_filter: 0

networks:
wan:
ipam:
config: [{subnet: 10.131.49.64/27}]
lan-dialer:
ipam:
config: [{subnet: 10.131.49.96/27}]
lan-listener:
ipam:
config: [{subnet: 10.131.49.128/27}]
coordination: {}

services:
redis:
image: redis:7-alpine
command: ["redis-server", "--save", "", "--appendonly", "no"]
networks:
- coordination
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 30

hs-hp-relay:
build:
context: .
dockerfile: interop/hole-punch/Dockerfile
depends_on:
redis:
condition: service_healthy
cap_add: [NET_ADMIN]
networks:
wan:
ipv4_address: 10.131.49.68
interface_name: wan0
coordination:
interface_name: redis0
environment:
<<: *hs-env
RELAY_IP: "10.131.49.68"
DIALER_LAN_SUBNET: "10.131.49.96/27"
DIALER_ROUTER_IP: "10.131.49.66"
LISTENER_LAN_SUBNET: "10.131.49.128/27"
LISTENER_ROUTER_IP: "10.131.49.67"

dialer-router:
<<: *router
networks:
wan:
ipv4_address: 10.131.49.66
interface_name: wan0
lan-dialer:
ipv4_address: 10.131.49.98
interface_name: lan0
environment:
WAN_IP: "10.131.49.66"
WAN_SUBNET: "10.131.49.64/27"
LAN_IP: "10.131.49.98"
LAN_SUBNET: "10.131.49.96/27"

listener-router:
<<: *router
networks:
wan:
ipv4_address: 10.131.49.67
interface_name: wan0
lan-listener:
ipv4_address: 10.131.49.130
interface_name: lan0
environment:
WAN_IP: "10.131.49.67"
WAN_SUBNET: "10.131.49.64/27"
LAN_IP: "10.131.49.130"
LAN_SUBNET: "10.131.49.128/27"

hs-hp-listener:
build:
context: .
dockerfile: interop/hole-punch/Dockerfile
depends_on: [redis, hs-hp-relay, listener-router]
cap_add: [NET_ADMIN]
networks:
lan-listener:
ipv4_address: 10.131.49.131
interface_name: lan0
coordination:
interface_name: redis0
environment:
<<: *hs-env
IS_DIALER: "false"
LISTENER_IP: "10.131.49.131"
WAN_SUBNET: "10.131.49.64/27"
WAN_ROUTER_IP: "10.131.49.130"

hs-hp-dialer:
build:
context: .
dockerfile: interop/hole-punch/Dockerfile
depends_on: [redis, hs-hp-relay, dialer-router, hs-hp-listener]
cap_add: [NET_ADMIN]
networks:
lan-dialer:
ipv4_address: 10.131.49.99
interface_name: lan0
coordination:
interface_name: redis0
environment:
<<: *hs-env
IS_DIALER: "true"
DIALER_IP: "10.131.49.99"
WAN_SUBNET: "10.131.49.64/27"
WAN_ROUTER_IP: "10.131.49.98"
9 changes: 8 additions & 1 deletion interop/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ IMAGE_NAME := libp2p-hs-interop

.PHONY: build image self-test cross-test-go-listener cross-test-hs-listener \
cross-gossipsub-rust-listener cross-gossipsub-hs-listener cross-gossipsub kad-dht \
perf-self-test perf-cross-nim-listener perf-cross-hs-listener perf-cross nim-libp2p
perf-self-test perf-cross-nim-listener perf-cross-hs-listener perf-cross nim-libp2p \
hole-punch-self-test

# nim-libp2p commit pinned by unified-testing perf/images.yaml (nim-v1.15).
NIM_LIBP2P_COMMIT := 1bdf2f67971529e8bee01252230bdb00ab785ef7
Expand Down Expand Up @@ -63,3 +64,9 @@ perf-cross-hs-listener: nim-libp2p

# Perf cross-test: both directions
perf-cross: perf-cross-nim-listener perf-cross-hs-listener

# Hole-punch self-test: hs peers behind separate NAT routers with a WAN relay
hole-punch-self-test:
cd .. && docker compose -f docker-compose.hole-punch.yml up --build \
--exit-code-from hs-hp-dialer redis dialer-router listener-router \
hs-hp-relay hs-hp-listener hs-hp-dialer
40 changes: 40 additions & 0 deletions interop/hole-punch/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Multi-stage build for the libp2p-hs hole-punch test daemon.
# Used by the libp2p/unified-testing hole-punch framework; build context
# is the repository root.

# Stage 1: Build with GHC 9.10
FROM haskell:9.10-slim-bookworm AS builder

WORKDIR /app

COPY libp2p-hs.cabal cabal.project ./

# Fix ppad-sha256 ARM SHA2 intrinsic compilation on Docker (GCC 12).
RUN if [ "$(uname -m)" = "aarch64" ]; then \
echo 'package ppad-sha256' >> cabal.project && \
echo ' ghc-options: -optc-march=armv8-a+crypto' >> cabal.project; \
fi

RUN cabal update && cabal build --only-dependencies lib:libp2p-hs

COPY src/ src/
COPY interop/ interop/
RUN cabal build libp2p-hole-punch \
&& cp "$(cabal list-bin libp2p-hole-punch)" /app/libp2p-hole-punch \
&& strip /app/libp2p-hole-punch

# Stage 2: Minimal runtime image
FROM debian:bookworm-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libgmp10 \
ca-certificates \
iproute2 \
&& rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/libp2p-hole-punch /usr/local/bin/libp2p-hole-punch
COPY interop/hole-punch/entrypoint.sh /usr/local/bin/hole-punch-entrypoint
RUN chmod +x /usr/local/bin/hole-punch-entrypoint

ENTRYPOINT ["/usr/local/bin/hole-punch-entrypoint"]
Loading
Loading