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
}