Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 14, 05:15 UTC
httpcaddyfile: Skip TLS APs for HTTP-only hosts (fix #3977)
This is probably an invasive change, but existing tests continue to pass. It seems to make sense this way. There is likely an edge case I haven't considered.
Matthew Holt committed
Jan 19, 2021 at 14:16 UTC
d68cff8eb6211be10fc79d3e8d469562420b78cd
3 files changed
+88
-10
caddyconfig/httpcaddyfile/httptype.go
+34
-10
@@ -409,7 +409,7 @@ func (st *ServerType) serversFromPairings(
409
var iLongestHost, jLongestHost string
410
var iWildcardHost, jWildcardHost bool
411
for _, addr := range p.serverBlocks[i].keys {
412
- if strings.Contains(addr.Host, "*.") {
412
+ if strings.Contains(addr.Host, "*") {
413
iWildcardHost = true
414
}
415
if specificity(addr.Host) > specificity(iLongestHost) {
@@ -420,7 +420,7 @@ func (st *ServerType) serversFromPairings(
420
}
421
}
422
for _, addr := range p.serverBlocks[j].keys {
423
- if strings.Contains(addr.Host, "*.") {
423
+ if strings.Contains(addr.Host, "*") {
424
jWildcardHost = true
425
}
426
if specificity(addr.Host) > specificity(jLongestHost) {
@@ -500,16 +500,20 @@ func (st *ServerType) serversFromPairings(
500
}
501
502
for _, addr := range sblock.keys {
503
- // exclude any hosts that were defined explicitly with "http://"
504
- // in the key from automated cert management (issue #2998)
505
- if addr.Scheme == "http" && addr.Host != "" {
506
- if srv.AutoHTTPS == nil {
507
- srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
508
- }
509
- if !sliceContains(srv.AutoHTTPS.Skip, addr.Host) {
510
- srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, addr.Host)
503
+ // if server only uses HTTPS port, auto-HTTPS will not apply
504
+ if listenersUseAnyPortOtherThan(srv.Listen, httpPort) {
505
+ // exclude any hosts that were defined explicitly with "http://"
506
+ // in the key from automated cert management (issue #2998)
507
+ if addr.Scheme == "http" && addr.Host != "" {
508
+ if srv.AutoHTTPS == nil {
509
+ srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
510
+ }
511
+ if !sliceContains(srv.AutoHTTPS.Skip, addr.Host) {
512
+ srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, addr.Host)
513
+ }
514
}
515
}
516
+
517
// we'll need to remember if the address qualifies for auto-HTTPS, so we
518
// can add a TLS conn policy if necessary
519
if addr.Scheme == "https" ||
@@ -1183,6 +1187,26 @@ func sliceContains(haystack []string, needle string) bool {
1187
return false
1188
}
1189
1190
+// listenersUseAnyPortOtherThan returns true if there are any
1191
+// listeners in addresses that use a port which is not otherPort.
1192
+// Mostly borrowed from unexported method in caddyhttp package.
1193
+func listenersUseAnyPortOtherThan(addresses []string, otherPort string) bool {
1194
+ otherPortInt, err := strconv.Atoi(otherPort)
1195
+ if err != nil {
1196
+ return false
1197
+ }
1198
+ for _, lnAddr := range addresses {
1199
+ laddrs, err := caddy.ParseNetworkAddress(lnAddr)
1200
+ if err != nil {
1201
+ continue
1202
+ }
1203
+ if uint(otherPortInt) > laddrs.EndPort || uint(otherPortInt) < laddrs.StartPort {
1204
+ return true
1205
+ }
1206
+ }
1207
+ return false
1208
+}
1209
+
1210
// specificity returns len(s) minus any wildcards (*) and
1211
// placeholders ({...}). Basically, it's a length count
1212
// that penalizes the use of wildcards and placeholders.
caddyconfig/httpcaddyfile/tlsapp.go
+9
@@ -40,6 +40,10 @@ func (st ServerType) buildTLSApp(
40
tlsApp := &caddytls.TLS{CertificatesRaw: make(caddy.ModuleMap)}
41
var certLoaders []caddytls.CertificateLoader
42
43
+ httpPort := strconv.Itoa(caddyhttp.DefaultHTTPPort)
44
+ if hp, ok := options["http_port"].(int); ok {
45
+ httpPort = strconv.Itoa(hp)
46
+ }
47
httpsPort := strconv.Itoa(caddyhttp.DefaultHTTPSPort)
48
if hsp, ok := options["https_port"].(int); ok {
49
httpsPort = strconv.Itoa(hsp)
@@ -91,6 +95,11 @@ func (st ServerType) buildTLSApp(
95
}
96
97
for _, p := range pairings {
98
+ // avoid setting up TLS automation policies for a server that is HTTP-only
99
+ if !listenersUseAnyPortOtherThan(p.addresses, httpPort) {
100
+ continue
101
+ }
102
+
103
for _, sblock := range p.serverBlocks {
104
// get values that populate an automation policy for this block
105
ap, err := newBaseAutomationPolicy(options, warnings, true)
caddytest/integration/caddyfile_adapt/http_only_hostnames.txt
new
+45
@@ -0,0 +1,45 @@
1
+# https://github.com/caddyserver/caddy/issues/3977
2
+http://* {
3
+ respond "Hello, world!"
4
+}
5
+----------
6
+{
7
+ "apps": {
8
+ "http": {
9
+ "servers": {
10
+ "srv0": {
11
+ "listen": [
12
+ ":80"
13
+ ],
14
+ "routes": [
15
+ {
16
+ "match": [
17
+ {
18
+ "host": [
19
+ "*"
20
+ ]
21
+ }
22
+ ],
23
+ "handle": [
24
+ {
25
+ "handler": "subroute",
26
+ "routes": [
27
+ {
28
+ "handle": [
29
+ {
30
+ "body": "Hello, world!",
31
+ "handler": "static_response"
32
+ }
33
+ ]
34
+ }
35
+ ]
36
+ }
37
+ ],
38
+ "terminal": true
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ }
44
+ }
45
+}
\ No newline at end of file