Skip to content

Commit

Permalink
port/builtin: support v6-to-v6 forwarding
Browse files Browse the repository at this point in the history
Signed-off-by: Akihiro Suda <[email protected]>
  • Loading branch information
AkihiroSuda committed Mar 1, 2021
1 parent 0aa4165 commit f17d87b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 18 deletions.
17 changes: 9 additions & 8 deletions cmd/rootlesskit-docker-proxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func getPortDriverProtos(c client.Client) (string, map[string]struct{}, error) {

func callRootlessKitAPI(c client.Client,
hostIP string, hostPort int,
dockerProxyProto string) (func() error, error) {
dockerProxyProto, childIP string) (func() error, error) {
// dockerProxyProto is like "tcp", but we need to convert it to "tcp4" or "tcp6" explicitly
// for libnetwork >= 20201216
//
Expand Down Expand Up @@ -101,6 +101,7 @@ func callRootlessKitAPI(c client.Client,
Proto: apiProto,
ParentIP: hostIP,
ParentPort: hostPort,
ChildIP: childIP,
ChildPort: hostPort,
}
st, err := pm.AddPort(context.Background(), p)
Expand Down Expand Up @@ -134,7 +135,12 @@ func xmain(f *os.File) error {
return errors.Wrap(err, "error while connecting to RootlessKit API socket")
}

deferFunc, err := callRootlessKitAPI(c, *hostIP, *hostPort, *proto)
childIP := "127.0.0.1"
if isIPv6(*hostIP) {
childIP = "::1"
}

deferFunc, err := callRootlessKitAPI(c, *hostIP, *hostPort, *proto, childIP)
if deferFunc != nil {
defer func() {
if dErr := deferFunc(); dErr != nil {
Expand All @@ -146,15 +152,10 @@ func xmain(f *os.File) error {
return err
}

realProxyHostIP := "127.0.0.1"
if isIPv6(*hostIP) {
realProxyHostIP = "::1"
}

cmd := exec.Command(realProxy,
"-container-ip", *containerIP,
"-container-port", strconv.Itoa(*containerPort),
"-host-ip", realProxyHostIP,
"-host-ip", childIP,
"-host-port", strconv.Itoa(*hostPort),
"-proto", *proto)
cmd.Stdout = os.Stdout
Expand Down
14 changes: 13 additions & 1 deletion hack/integration-port.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,22 @@ INFO "=== protocol \"tcp4\" is strictly v4-only ==="
test_port builtin http://127.0.0.1:8080 "should success" -p 0.0.0.0:8080:80/tcp4
test_port builtin http://[::1]:8080 "should fail" -p 0.0.0.0:8080:80/tcp4

INFO "=== protocol \"tcp6\" is strictly v4-only ==="
INFO "=== protocol \"tcp6\" is strictly v6-only ==="
test_port builtin http://127.0.0.1:8080 "should fail" -p [::]:8080:80/tcp6
test_port builtin http://[::1]:8080 "should success" -p [::]:8080:80/tcp6

INFO "=== v6-to-v6 ==="
test_port builtin http://[::1]:8080 "should success" -p [::]:8080:[::1]:80/tcp6
test_port builtin http://[::1]:8080 "should success" -p [::]:8080:[::1]:80/tcp

INFO "=== v6-to-v4 ==="
test_port builtin http://[::1]:8080 "should success" -p [::]:8080:[127.0.0.1]:80/tcp6
test_port builtin http://[::1]:8080 "should success" -p [::]:8080:[127.0.0.1]:80/tcp

INFO "=== v4-to-v6 ==="
test_port builtin http://127.0.0.1:8080 "should success" -p 0.0.0.0:8080:[::1]:80/tcp4
test_port builtin http://127.0.0.1:8080 "should success" -p 0.0.0.0:8080:[::1]:80/tcp

INFO "=== \"tcp4\" and \"tcp6\" do not conflict ==="
test_port builtin http://127.0.0.1:8080 "should success" -p 0.0.0.0:8080:80/tcp4 -p [::]:8080:80/tcp6

Expand Down
12 changes: 4 additions & 8 deletions pkg/port/builtin/child/child.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package child

import (
"fmt"
"io"
"net"
"os"
"strconv"
"strings"

"github.com/pkg/errors"
Expand Down Expand Up @@ -110,8 +110,8 @@ func (d *childDriver) handleConnectRequest(c *net.UnixConn, req *msg.Request) er
default:
return errors.Errorf("unknown proto: %q", req.Proto)
}
// dialProto is always non-v6
dialProto := strings.TrimSuffix(req.Proto, "6")
// dialProto does not need "4", "6" suffix
dialProto := strings.TrimSuffix(strings.TrimSuffix(req.Proto, "6"), "4")
var dialer net.Dialer
ip := req.IP
if ip == "" {
Expand All @@ -121,13 +121,9 @@ func (d *childDriver) handleConnectRequest(c *net.UnixConn, req *msg.Request) er
if p == nil {
return errors.Errorf("invalid IP: %q", ip)
}
p = p.To4()
if p == nil {
return errors.Errorf("unsupported IP (v6?): %s", ip)
}
ip = p.String()
}
targetConn, err := dialer.Dial(dialProto, fmt.Sprintf("%s:%d", ip, req.Port))
targetConn, err := dialer.Dial(dialProto, net.JoinHostPort(ip, strconv.Itoa(req.Port)))
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/port/port.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type Spec struct {
ParentIP string `json:"parentIP,omitempty"` // IPv4 or IPv6 address. can be empty (0.0.0.0).
ParentPort int `json:"parentPort,omitempty"`
ChildPort int `json:"childPort,omitempty"`
// ChildIP is an IPv4 address.
// ChildIP is an IPv4 or IPv6 address.
// Default values:
// - builtin driver: 127.0.0.1
// - socat driver: 127.0.0.1
Expand Down

0 comments on commit f17d87b

Please sign in to comment.