IPv6 - agent.auto_config: error splitting host address into IP and port: address=X error="address X too many colons in address"

I have a consul cluster using IPv6, in server mode nodes connect, but when I try to add an agent I get this error only in the agents:

agent.auto_config: error splitting host address into IP and port: address=2001::1 error="address 2001:1 too many colons in address"

This is the configuration I am using:

advertise_addr          = "2001:xxx::4"
bind_addr               = "::"
data_dir                = "/opt/consul"
datacenter              = "dc1"
encrypt                 = "yyy"
retry_join =  [
  "2001:xxxx::1",
  "2001:xxxx::2",
  "2001:xxxx::3"]

auto_encrypt = {
  tls = true
}


tls {
  defaults {
    verify_incoming = true
    verify_outgoing = true
    ca_file = "/etc/consul.d/ssl/consul-ca.crt"
  }
}

acl = {
  enabled        = true
  default_policy = "allow"
  tokens = {
    default = "xxxx"
  }
}

log_file  = "/var/log/consul/"
log_level = "WARN"

IPv6 working in server mode but wondering how to make it work for the agents, any ideas?

I don’t use IPv6 yet myself, but I understand it is pretty standard to write IPv6 addresses enclosed in square brackets, if they appear in any context that might plausibly support being followed by a port number.

The Consul documentation is not entirely clear on which options might or might not be interpreted that way, but there’s an easy way around that - just enclose every IPv6 address in square brackets, unless doing so actually triggers an error (in which case take the square brackets back out, only in those cases that require them not to be there).

Although, doing a quick GitHub search for "error splitting host address into IP and port" org:hashicorp brings up consul auto-encryption fails on IPv6-only cluster · Issue #11847 · hashicorp/consul · GitHub which indicates this is a long-time unfixed defect in Consul, such that it doesn’t fully support IPv6.

Indeed I have that issue, enclosing doesn’t help, but interesting that in server mode IPv6 works

Well, not that interesting… it seems pretty indicative that there’s a particular code path in the auto_config subsystem which is not using suitable address manipulation functions. An easy, if irritating, bug to accidentally include, if writing new code whilst not thinking about IPv6.

OK, maybe it is a bit interesting… I’ve since learned that as far as Go’s standard library is concerned, the square brackets form of IPv6 addresses is not generally supported for standalone addresses - it’s only supported specifically when splitting host:port strings.

Even the IPv6 RFCs are fairly quiet about the square brackets form.

The code in Consul handling this is a bit of a mess - there’s a function that sometimes returns host:port and sometimes only host, and the code in Consul is re-implementing the parsing of the contents of the retry_join option, which is also parsed inside the GitHub - hashicorp/memberlist: Golang package for gossip based membership and failure detection library - meaning you can currently write an IPv6 address inside square brackets in retry_join and have it accepted by one part of Consul but rejected by another! Messy…