@marcel91200 / caddy Mirror · read-only / commits / 3e1fd2a8
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, 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