Skip to content

Commit fac59c5

Browse files
authored
Merge pull request #579 from AkihiroSuda/fix-TestTCPTransparent
testsuite: use non-loopback IP in TestTCPTransparent
2 parents e638572 + 1a1ecf2 commit fac59c5

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ COPY --from=cross /go/src/github.com/rootless-containers/rootlesskit/_artifact/*
2626

2727
# `go test -race` requires non-Alpine
2828
FROM golang:${GO_VERSION} AS test-unit
29-
RUN apt-get update && apt-get install -y git iproute2 netcat-openbsd
29+
# iptables: used for source-ip-transparent
30+
RUN apt-get update && apt-get install -y git iproute2 netcat-openbsd iptables
3031
ADD . /go/src/github.com/rootless-containers/rootlesskit
3132
WORKDIR /go/src/github.com/rootless-containers/rootlesskit
3233
RUN go mod verify && go vet ./...
@@ -64,7 +65,7 @@ FROM ubuntu:${UBUNTU_VERSION} AS test-integration
6465
# libcap2-bin and curl: used by the RUN instructions in this Dockerfile.
6566
# bind9-dnsutils: for `nslookup` command used by integration-net.sh
6667
# systemd and uuid-runtime: for systemd-socket-activate used by integration-systemd-socket.sh
67-
# iptables: for Docker
68+
# iptables: for source-ip-transparent. Also for Docker.
6869
RUN apt-get update && apt-get install -y iproute2 liblxc-common lxc-utils iperf3 busybox sudo libcap2-bin curl bind9-dnsutils systemd uuid-runtime iptables
6970
COPY --from=idmap /usr/bin/newuidmap /usr/bin/newuidmap
7071
COPY --from=idmap /usr/bin/newgidmap /usr/bin/newgidmap

pkg/port/testsuite/testsuite.go

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,33 @@ func (w *tLogWriter) Write(p []byte) (int, error) {
331331
return len(p), nil
332332
}
333333

334+
// nonLoopbackIPv4 returns the first non-loopback IPv4 address found on the host.
335+
func nonLoopbackIPv4() (string, error) {
336+
ifaces, err := net.Interfaces()
337+
if err != nil {
338+
return "", err
339+
}
340+
for _, iface := range ifaces {
341+
if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
342+
continue
343+
}
344+
addrs, err := iface.Addrs()
345+
if err != nil {
346+
continue
347+
}
348+
for _, addr := range addrs {
349+
ipNet, ok := addr.(*net.IPNet)
350+
if !ok {
351+
continue
352+
}
353+
if ip4 := ipNet.IP.To4(); ip4 != nil {
354+
return ip4.String(), nil
355+
}
356+
}
357+
}
358+
return "", fmt.Errorf("no non-loopback IPv4 address found")
359+
}
360+
334361
func allocateAvailablePort(proto string) (int, error) {
335362
const loopback = "127.0.0.1:0"
336363
switch proto {
@@ -452,6 +479,12 @@ func testTCPTransparentWithPID(t *testing.T, d port.ParentDriver, childPID int)
452479
ensureDeps(t, "nsenter")
453480
const childPort = 80
454481

482+
parentIP, err := nonLoopbackIPv4()
483+
if err != nil {
484+
t.Skip("no non-loopback IPv4 address available: ", err)
485+
}
486+
t.Logf("using non-loopback parent IP: %s", parentIP)
487+
455488
// Start parent driver
456489
initComplete := make(chan struct{})
457490
quit := make(chan struct{})
@@ -524,7 +557,7 @@ func testTCPTransparentWithPID(t *testing.T, d port.ParentDriver, childPID int)
524557
portStatus, err = d.AddPort(context.TODO(),
525558
port.Spec{
526559
Proto: "tcp",
527-
ParentIP: "127.0.0.1",
560+
ParentIP: parentIP,
528561
ParentPort: parentPort,
529562
ChildPort: childPort,
530563
})
@@ -545,7 +578,7 @@ func testTCPTransparentWithPID(t *testing.T, d port.ParentDriver, childPID int)
545578
var conn net.Conn
546579
for i := 0; i < 5; i++ {
547580
var dialer net.Dialer
548-
conn, err = dialer.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", parentPort))
581+
conn, err = dialer.Dial("tcp", net.JoinHostPort(parentIP, strconv.Itoa(parentPort)))
549582
if err == nil {
550583
break
551584
}
@@ -577,10 +610,8 @@ func testTCPTransparentWithPID(t *testing.T, d port.ParentDriver, childPID int)
577610
conn.Close()
578611
echoCmd.Wait()
579612

580-
// Parse and verify: the echo server should see the client's IP.
581-
// Port preservation only works with non-loopback source IPs (via IP_TRANSPARENT),
582-
// so we only verify the IP here. With loopback, transparent dial is skipped
583-
// (martian filtering blocks 127.0.0.1 arriving on non-loopback interfaces).
613+
// Parse and verify: the echo server should see the client's non-loopback IP,
614+
// not 127.0.0.1 or a hard-coded router address.
584615
clientHost, _, err := net.SplitHostPort(clientAddr)
585616
if err != nil {
586617
t.Fatalf("failed to parse client address %q: %v", clientAddr, err)

0 commit comments

Comments
 (0)