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, 09:15 UTC
httpcaddyfile: Wrap site block in subroute if host matcher used (#5130)
* httpcaddyfile: Wrap site block in subroute if host matcher used (fix #5124) * Correct boolean logic (oops)
Matt Holt committed
Oct 12, 2022 at 09:27 UTC
3e1fd2a8d4d1463574033fbbdf5c27a693f9a86c
4 files changed
+116
-81
caddyconfig/httpcaddyfile/httptype.go
+28
-4
@@ -907,11 +907,32 @@ func appendSubrouteToRouteList(routeList caddyhttp.RouteList,
907
return routeList
908
}
909
910
+ // No need to wrap the handlers in a subroute if this is the only server block
911
+ // and there is no matcher for it (doing so would produce unnecessarily nested
912
+ // JSON), *unless* there is a host matcher within this site block; if so, then
913
+ // we still need to wrap in a subroute because otherwise the host matcher from
914
+ // the inside of the site block would be a top-level host matcher, which is
915
+ // subject to auto-HTTPS (cert management), and using a host matcher within
916
+ // a site block is a valid, common pattern for excluding domains from cert
917
+ // management, leading to unexpected behavior; see issue #5124.
918
+ wrapInSubroute := true
919
if len(matcherSetsEnc) == 0 && len(p.serverBlocks) == 1 {
911
- // no need to wrap the handlers in a subroute if this is
912
- // the only server block and there is no matcher for it
913
- routeList = append(routeList, subroute.Routes...)
914
- } else {
920
+ var hasHostMatcher bool
921
+ outer:
922
+ for _, route := range subroute.Routes {
923
+ for _, ms := range route.MatcherSetsRaw {
924
+ for matcherName := range ms {
925
+ if matcherName == "host" {
926
+ hasHostMatcher = true
927
+ break outer
928
+ }
929
+ }
930
+ }
931
+ }
932
+ wrapInSubroute = hasHostMatcher
933
+ }
934
+
935
+ if wrapInSubroute {
936
route := caddyhttp.Route{
937
// the semantics of a site block in the Caddyfile dictate
938
// that only the first matching one is evaluated, since
@@ -929,7 +950,10 @@ func appendSubrouteToRouteList(routeList caddyhttp.RouteList,
950
if len(route.MatcherSetsRaw) > 0 || len(route.HandlersRaw) > 0 {
951
routeList = append(routeList, route)
952
}
953
+ } else {
954
+ routeList = append(routeList, subroute.Routes...)
955
}
956
+
957
return routeList
958
}
959
caddytest/integration/caddyfile_adapt/global_server_options_multi.txt
+2
-6
@@ -3,9 +3,7 @@
3
timeouts {
4
idle 90s
5
}
6
- protocol {
7
- strict_sni_host insecure_off
8
- }
6
+ strict_sni_host insecure_off
7
}
8
servers :80 {
9
timeouts {
@@ -16,9 +14,7 @@
14
timeouts {
15
idle 30s
16
}
19
- protocol {
20
- strict_sni_host
21
- }
17
+ strict_sni_host
18
}
19
}
20
caddytest/integration/caddyfile_adapt/php_fastcgi_matcher.txt
+85
-70
@@ -1,7 +1,12 @@
1
:8884
2
3
-@api host example.com
4
-php_fastcgi @api localhost:9000
3
+# the use of a host matcher here should cause this
4
+# site block to be wrapped in a subroute, even though
5
+# the site block does not have a hostname; this is
6
+# to prevent auto-HTTPS from picking up on this host
7
+# matcher because it is not a key on the site block
8
+@test host example.com
9
+php_fastcgi @test localhost:9000
10
----------
11
{
12
"apps": {
@@ -13,13 +18,6 @@ php_fastcgi @api localhost:9000
18
],
19
"routes": [
20
{
16
- "match": [
17
- {
18
- "host": [
19
- "example.com"
20
- ]
21
- }
22
- ],
21
"handle": [
22
{
23
"handler": "subroute",
@@ -27,82 +25,99 @@ php_fastcgi @api localhost:9000
25
{
26
"handle": [
27
{
30
- "handler": "static_response",
31
- "headers": {
32
- "Location": [
33
- "{http.request.orig_uri.path}/"
34
- ]
35
- },
36
- "status_code": 308
37
- }
38
- ],
39
- "match": [
40
- {
41
- "file": {
42
- "try_files": [
43
- "{http.request.uri.path}/index.php"
44
- ]
45
- },
46
- "not": [
28
+ "handler": "subroute",
29
+ "routes": [
30
{
48
- "path": [
49
- "*/"
31
+ "handle": [
32
+ {
33
+ "handler": "static_response",
34
+ "headers": {
35
+ "Location": [
36
+ "{http.request.orig_uri.path}/"
37
+ ]
38
+ },
39
+ "status_code": 308
40
+ }
41
+ ],
42
+ "match": [
43
+ {
44
+ "file": {
45
+ "try_files": [
46
+ "{http.request.uri.path}/index.php"
47
+ ]
48
+ },
49
+ "not": [
50
+ {
51
+ "path": [
52
+ "*/"
53
+ ]
54
+ }
55
+ ]
56
+ }
57
]
51
- }
52
- ]
53
- }
54
- ]
55
- },
56
- {
57
- "handle": [
58
- {
59
- "handler": "rewrite",
60
- "uri": "{http.matchers.file.relative}"
61
- }
62
- ],
63
- "match": [
64
- {
65
- "file": {
66
- "split_path": [
67
- ".php"
68
- ],
69
- "try_files": [
70
- "{http.request.uri.path}",
71
- "{http.request.uri.path}/index.php",
72
- "index.php"
73
- ]
74
- }
75
- }
76
- ]
77
- },
78
- {
79
- "handle": [
80
- {
81
- "handler": "reverse_proxy",
82
- "transport": {
83
- "protocol": "fastcgi",
84
- "split_path": [
85
- ".php"
86
- ]
87
- },
88
- "upstreams": [
58
+ },
59
{
90
- "dial": "localhost:9000"
60
+ "handle": [
61
+ {
62
+ "handler": "rewrite",
63
+ "uri": "{http.matchers.file.relative}"
64
+ }
65
+ ],
66
+ "match": [
67
+ {
68
+ "file": {
69
+ "split_path": [
70
+ ".php"
71
+ ],
72
+ "try_files": [
73
+ "{http.request.uri.path}",
74
+ "{http.request.uri.path}/index.php",
75
+ "index.php"
76
+ ]
77
+ }
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "handle": [
83
+ {
84
+ "handler": "reverse_proxy",
85
+ "transport": {
86
+ "protocol": "fastcgi",
87
+ "split_path": [
88
+ ".php"
89
+ ]
90
+ },
91
+ "upstreams": [
92
+ {
93
+ "dial": "localhost:9000"
94
+ }
95
+ ]
96
+ }
97
+ ],
98
+ "match": [
99
+ {
100
+ "path": [
101
+ "*.php"
102
+ ]
103
+ }
104
+ ]
105
}
106
]
107
}
108
],
109
"match": [
110
{
97
- "path": [
98
- "*.php"
111
+ "host": [
112
+ "example.com"
113
]
114
}
115
]
116
}
117
]
118
}
105
- ]
119
+ ],
120
+ "terminal": true
121
}
122
]
123
}
modules/caddyhttp/app.go
+1
-1
@@ -66,7 +66,7 @@ func init() {
66
// `{http.request.orig_uri}` | The request's original URI
67
// `{http.request.port}` | The port part of the request's Host header
68
// `{http.request.proto}` | The protocol of the request
69
-// `{http.request.remote.host}` | The host part of the remote client's address
69
+// `{http.request.remote.host}` | The host (IP) part of the remote client's address
70
// `{http.request.remote.port}` | The port part of the remote client's address
71
// `{http.request.remote}` | The address of the remote client
72
// `{http.request.scheme}` | The request scheme