@marcel91200 / caddy Mirror · read-only / commits / a1ad20e4
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 13:00 UTC

httpcaddyfile: Fix bind when IPv6 is specified with network (#4950)

* fix listening on IPv6 addresses: use net.JoinHostPort Commit 1e18afb5c862d62be130d563785de5c58f08ae8e broke my caddy setup. This commit fixes it. * Refactor solution; simplify, add descriptive comment * Move network to host, not copy Co-authored-by: Matthew Holt <mholt@users.noreply.github.com>

Michael Stapelberg committed Sep 15, 2022 at 16:03 UTC a1ad20e4720391d847c58fcdcef7c8d9c287faf2
1 file changed +24 -12
caddyconfig/httpcaddyfile/addresses.go
+24 -12
@@ -36,12 +36,12 @@ import (
36 // server block that share the same address stay grouped together so the config
37 // isn't repeated unnecessarily. For example, this Caddyfile:
38 //
39 -// example.com {
40 -// bind 127.0.0.1
41 -// }
42 -// www.example.com, example.net/path, localhost:9999 {
43 -// bind 127.0.0.1 1.2.3.4
44 -// }
39 +// example.com {
40 +// bind 127.0.0.1
41 +// }
42 +// www.example.com, example.net/path, localhost:9999 {
43 +// bind 127.0.0.1 1.2.3.4
44 +// }
45 //
46 // has two server blocks to start with. But expressed in this Caddyfile are
47 // actually 4 listener addresses: 127.0.0.1:443, 1.2.3.4:443, 127.0.0.1:9999,
@@ -219,7 +219,7 @@ func (st *ServerType) listenerAddrsForServerBlockKey(sblock serverBlock, key str
219 return nil, fmt.Errorf("[%s] scheme and port violate convention", key)
220 }
221
222 - // the bind directive specifies hosts, but is optional
222 + // the bind directive specifies hosts (and potentially network), but is optional
223 lnHosts := make([]string, 0, len(sblock.pile["bind"]))
224 for _, cfgVal := range sblock.pile["bind"] {
225 lnHosts = append(lnHosts, cfgVal.Value.([]string)...)
@@ -234,11 +234,23 @@ func (st *ServerType) listenerAddrsForServerBlockKey(sblock serverBlock, key str
234
235 // use a map to prevent duplication
236 listeners := make(map[string]struct{})
237 - for _, host := range lnHosts {
238 - // host can have network + host (e.g. "tcp6/localhost") but
239 - // will/should not have port information because this usually
240 - // comes from the bind directive, so we append the port
241 - addr, err := caddy.ParseNetworkAddress(host + ":" + lnPort)
237 + for _, lnHost := range lnHosts {
238 + // normally we would simply append the port,
239 + // but if lnHost is IPv6, we need to ensure it
240 + // is enclosed in [ ]; net.JoinHostPort does
241 + // this for us, but lnHost might also have a
242 + // network type in front (e.g. "tcp/") leading
243 + // to "[tcp/::1]" which causes parsing failures
244 + // later; what we need is "tcp/[::1]", so we have
245 + // to split the network and host, then re-combine
246 + network, host, ok := strings.Cut(lnHost, "/")
247 + if !ok {
248 + host = network
249 + network = ""
250 + }
251 + host = strings.Trim(host, "[]") // IPv6
252 + networkAddr := caddy.JoinNetworkAddress(network, host, lnPort)
253 + addr, err := caddy.ParseNetworkAddress(networkAddr)
254 if err != nil {
255 return nil, fmt.Errorf("parsing network address: %v", err)
256 }