Skip to content

ParseTCPAddr drops the %25 escape on IPv6 zones, so -H can't reach a link-local daemon #7432

Open

Description

@Yeagerist0

Description

docker -H can't connect to a daemon on a link-local IPv6 address. A link-local address needs a zone, and every way of writing the zone fails.

url.Parse only accepts the zone percent-encoded (%25), so tcp://[fe80::1%lo]:2375 is rejected as input. tcp://[fe80::1%25lo]:2375 gets through, but ParseTCPAddr builds its result with fmt.Sprintf("tcp://%s%s", net.JoinHostPort(host, port), u.Path) (opts/hosts.go). u.Hostname() has already decoded %25 to %, so the output is tcp://[fe80::1%lo]:2375, and parsing that again fails.

This was found by @by-ae while reviewing #7401. It also happens on master without that PR.

Reproduce

$ docker -H 'tcp://[fe80::1%25lo]:2375' version
Failed to initialize: parse "tcp://[fe80::1%lo]:2375": invalid URL escape "%lo"

$ docker -H 'tcp://[fe80::1]:2375' version
...
error during connect: Get "http://[fe80::1]:2375/v1.51/version": dial tcp [fe80::1]:2375: connect: invalid argument

At the function level, on master (52a2671):

ParseTCPAddr("tcp://[fe80::1%25eth0]:5555", "tcp://127.0.0.1:2375")
  -> "tcp://[fe80::1%eth0]:5555", nil
url.Parse("tcp://[fe80::1%eth0]:5555")
  -> invalid URL escape "%et"

Expected behavior

-H 'tcp://[fe80::1%25lo]:2375' connects. ParseTCPAddr should return a URL that parses again.

docker version

Client: 28.5.2+dfsg4 (Debian). Same code path on master 52a2671.

docker info

Not relevant: the error comes from client-side flag parsing, before any request is sent.

Additional Info

Re-escaping % as %25 in the output isn't enough by itself. swarm.NodeAddrOption uses the same function and strips tcp:// (cli/command/swarm/opts.go), so --listen-addr / --advertise-addr depend on the raw [fe80::1%eth0]:5555 form, which net.Listen expects. That's why I'm opening an issue first: should the two callers get different output, or should NodeAddrOption.Value() unescape?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions