Skip to content

Commit 6f4f9ec

Browse files
authored
Merge pull request nginx-proxy#1927 from rhansen/untrusted-headers
feat: Option to not trust `X-Forwarded-*` headers from clients
2 parents 7c0d38c + 8aa00fc commit 6f4f9ec

File tree

11 files changed

+243
-6
lines changed

11 files changed

+243
-6
lines changed

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ You can also use wildcards at the beginning and the end of host name, like `*.ba
122122
You can have multiple containers proxied by the same `VIRTUAL_HOST` by adding a `VIRTUAL_PATH` environment variable containing the absolute path to where the container should be mounted. For example with `VIRTUAL_HOST=foo.example.com` and `VIRTUAL_PATH=/api/v2/service`, then requests to http://foo.example.com/api/v2/service will be routed to the container. If you wish to have a container serve the root while other containers serve other paths, give the root container a `VIRTUAL_PATH` of `/`. Unmatched paths will be served by the container at `/` or will return the default nginx error page if no container has been assigned `/`.
123123
It is also possible to specify multiple paths with regex locations like `VIRTUAL_PATH=~^/(app1|alternative1)/`. For further details see the nginx documentation on location blocks. This is not compatible with `VIRTUAL_DEST`.
124124

125-
The full request URI will be forwarded to the serving container in the `X-Forwarded-Path` header.
125+
The full request URI will be forwarded to the serving container in the `X-Original-URI` header.
126126

127127
**NOTE**: Your application needs to be able to generate links starting with `VIRTUAL_PATH`. This can be achieved by it being natively on this path or having an option to prepend this path. The application does not need to expect this path in the request.
128128

@@ -361,6 +361,28 @@ docker run -d -p 80:80 -p 443:443 \
361361

362362
You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html)
363363

364+
### Headers
365+
366+
By default, `nginx-proxy` forwards all incoming request headers from the client to the backend server unmodified, with the following exceptions:
367+
368+
* `Connection`: Set to `upgrade` if the client sets the `Upgrade` header, otherwise set to `close`. (Keep-alive between `nginx-proxy` and the backend server is not supported.)
369+
* `Proxy`: Always removed if present. This prevents attackers from using the so-called [httpoxy attack](http://httpoxy.org). There is no legitimate reason for a client to send this header, and there are many vulnerable languages / platforms (`CVE-2016-5385`, `CVE-2016-5386`, `CVE-2016-5387`, `CVE-2016-5388`, `CVE-2016-1000109`, `CVE-2016-1000110`, `CERT-VU#797896`).
370+
* `X-Real-IP`: Set to the client's IP address.
371+
* `X-Forwarded-For`: The client's IP address is appended to the value provided by the client. (If the client did not provide this header, it is set to the client's IP address.)
372+
* `X-Forwarded-Proto`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to `http` for plain HTTP connections and `https` for TLS connections. Otherwise, the header is forwarded to the backend server unmodified.
373+
* `X-Forwarded-Ssl`: Set to `on` if the `X-Forwarded-Proto` header sent to the backend server is `https`, otherwise set to `off`.
374+
* `X-Forwarded-Port`: If the client did not provide this header or if the `TRUST_DOWNSTREAM_PROXY` environment variable is set to `false` (see below), this is set to the port of the server that accepted the client's request. Otherwise, the header is forwarded to the backend server unmodified.
375+
* `X-Original-URI`: Set to the original request URI.
376+
377+
#### Trusting Downstream Proxy Headers
378+
379+
For legacy compatibility reasons, `nginx-proxy` forwards any client-supplied `X-Forwarded-Proto` (which affects the value of `X-Forwarded-Ssl`) and `X-Forwarded-Port` headers unchecked and unmodified. To prevent malicious clients from spoofing the protocol or port that is perceived by your backend server, you are encouraged to set the `TRUST_DOWNSTREAM_PROXY` value to `false` if:
380+
381+
* you do not operate a second reverse proxy downstream of `nginx-proxy`, or
382+
* you do operate a second reverse proxy downstream of `nginx-proxy` but that proxy forwards those headers unchecked from untrusted clients.
383+
384+
The default for `TRUST_DOWNSTREAM_PROXY` may change to `false` in a future version of `nginx-proxy`. If you require it to be enabled, you are encouraged to explicitly set it to `true` to avoid compatibility problems when upgrading.
385+
364386
### Custom Nginx Configuration
365387

366388
If you need to configure Nginx beyond what is possible using environment variables, you can provide custom configuration files on either a proxy-wide or per-`VIRTUAL_HOST` basis.
@@ -381,16 +403,14 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
381403
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
382404
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
383405
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
384-
proxy_set_header X-Forwarded-Path $request_uri;
406+
proxy_set_header X-Original-URI $request_uri;
385407
386408
# Mitigate httpoxy attack (see README for details)
387409
proxy_set_header Proxy "";
388410
```
389411

390412
***NOTE***: If you provide this file it will replace the defaults; you may want to check the .tmpl file to make sure you have all of the needed options.
391413

392-
***NOTE***: The default configuration blocks the `Proxy` HTTP request header from being sent to downstream servers. This prevents attackers from using the so-called [httpoxy attack](http://httpoxy.org). There is no legitimate reason for a client to send this header, and there are many vulnerable languages / platforms (`CVE-2016-5385`, `CVE-2016-5386`, `CVE-2016-5387`, `CVE-2016-5388`, `CVE-2016-1000109`, `CVE-2016-1000110`, `CERT-VU#797896`).
393-
394414
#### Proxy-wide
395415

396416
To add settings on a proxy-wide basis, add your configuration file under `/etc/nginx/conf.d` using a name ending in `.conf`.

app/docker-entrypoint.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ if [[ $* == 'forego start -r' ]]; then
109109
_resolvers
110110

111111
_setup_dhparam
112+
113+
if [ -z "${TRUST_DOWNSTREAM_PROXY}" ]; then
114+
cat >&2 <<-EOT
115+
Warning: TRUST_DOWNSTREAM_PROXY is not set; defaulting to "true". For security, you should explicitly set TRUST_DOWNSTREAM_PROXY to "false" if there is not a trusted reverse proxy in front of this proxy.
116+
Warning: The default value of TRUST_DOWNSTREAM_PROXY might change to "false" in a future version of nginx-proxy. If you require TRUST_DOWNSTREAM_PROXY to be enabled, explicitly set it to "true".
117+
EOT
118+
fi
112119
fi
113120

114121
exec "$@"

nginx.tmpl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
{{ $debug_all := $.Env.DEBUG }}
77
{{ $sha1_upstream_name := parseBool (coalesce $.Env.SHA1_UPSTREAM_NAME "false") }}
88
{{ $default_root_response := coalesce $.Env.DEFAULT_ROOT "404" }}
9+
{{ $trust_downstream_proxy := parseBool (coalesce $.Env.TRUST_DOWNSTREAM_PROXY "true") }}
910

1011
{{ define "ssl_policy" }}
1112
{{ if eq .ssl_policy "Mozilla-Modern" }}
@@ -150,14 +151,14 @@ upstream {{ .Upstream }} {
150151
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
151152
# scheme used to connect to this server
152153
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
153-
default $http_x_forwarded_proto;
154+
default {{ if $trust_downstream_proxy }}$http_x_forwarded_proto{{ else }}$scheme{{ end }};
154155
'' $scheme;
155156
}
156157

157158
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
158159
# server port the client connected to
159160
map $http_x_forwarded_port $proxy_x_forwarded_port {
160-
default $http_x_forwarded_port;
161+
default {{ if $trust_downstream_proxy }}$http_x_forwarded_port{{ else }}$server_port{{ end }};
161162
'' $server_port;
162163
}
163164

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
Certificate:
2+
Data:
3+
Version: 3 (0x2)
4+
Serial Number: 4096 (0x1000)
5+
Signature Algorithm: sha256WithRSAEncryption
6+
Issuer: O=nginx-proxy test suite, CN=www.nginx-proxy.tld
7+
Validity
8+
Not Before: Jan 13 03:06:39 2017 GMT
9+
Not After : May 31 03:06:39 2044 GMT
10+
Subject: CN=web.nginx-proxy.tld
11+
Subject Public Key Info:
12+
Public Key Algorithm: rsaEncryption
13+
Public-Key: (2048 bit)
14+
Modulus:
15+
00:95:56:c7:0d:48:a5:2b:3c:65:49:3f:26:e1:38:
16+
2b:61:30:56:e4:92:d7:63:e0:eb:ad:ac:f9:33:9b:
17+
b2:31:f1:39:13:0b:e5:43:7b:c5:bd:8a:85:c8:d9:
18+
3d:d8:ac:71:ba:16:e7:81:96:b2:ab:ae:c6:c0:bd:
19+
be:a7:d1:96:8f:b2:9b:df:ba:f9:4d:a1:3b:7e:21:
20+
4a:cd:b6:45:f9:6d:79:50:bf:24:8f:c1:6b:c1:09:
21+
19:5b:62:cb:96:e8:04:14:20:e8:d4:16:62:6a:f2:
22+
37:c1:96:e2:9d:53:05:0b:52:1d:e7:68:92:db:8b:
23+
36:68:cd:8d:5b:02:ff:12:f0:ac:5d:0c:c4:e0:7a:
24+
55:a2:49:60:9f:ff:47:1f:52:73:55:4d:d4:f2:d1:
25+
62:a2:f4:50:9d:c9:f6:f1:43:b3:dc:57:e1:31:76:
26+
b4:e0:a4:69:7e:f2:6d:34:ae:b9:8d:74:26:7b:d9:
27+
f6:07:00:ef:4b:36:61:b3:ef:7a:a1:36:3a:b6:d0:
28+
9e:f8:b8:a9:0d:4c:30:a2:ed:eb:ab:6b:eb:2e:e2:
29+
0b:28:be:f7:04:b1:e9:e0:84:d6:5d:31:77:7c:dc:
30+
d2:1f:d4:1d:71:6f:6f:6c:6d:1b:bf:31:e2:5b:c3:
31+
52:d0:14:fc:8b:fb:45:ea:41:ec:ca:c7:3b:67:12:
32+
c4:df
33+
Exponent: 65537 (0x10001)
34+
X509v3 extensions:
35+
X509v3 Subject Alternative Name:
36+
DNS:web.nginx-proxy.tld
37+
Signature Algorithm: sha256WithRSAEncryption
38+
4e:48:7d:81:66:ba:2f:50:3d:24:42:61:3f:1f:de:cf:ec:1b:
39+
1b:bd:0a:67:b6:62:c8:79:9d:31:a0:fd:a9:61:ce:ff:69:bf:
40+
0e:f4:f7:e6:15:2b:b0:f0:e4:f2:f4:d2:8f:74:02:b1:1e:4a:
41+
a8:6f:26:0a:77:32:29:cf:dc:b5:61:82:3e:58:47:61:92:f0:
42+
0c:20:25:f8:41:4d:34:09:44:bc:39:9e:aa:82:06:83:13:8b:
43+
1e:2c:3d:cf:cd:1a:f7:77:39:38:e0:a3:a7:f3:09:da:02:8d:
44+
73:75:38:b4:dd:24:a7:f9:03:db:98:c6:88:54:87:dc:e0:65:
45+
4c:95:c5:39:9c:00:30:dc:f0:d3:2c:19:ca:f1:f4:6c:c6:d9:
46+
b5:c4:4a:c7:bc:a1:2e:88:7b:b5:33:d0:ff:fb:48:5e:3e:29:
47+
fa:58:e5:03:de:d8:17:de:ed:96:fc:7e:1f:fe:98:f6:be:99:
48+
38:87:51:c0:d3:b7:9a:0f:26:92:e5:53:1b:d6:25:4c:ac:48:
49+
f3:29:fc:74:64:9d:07:6a:25:57:24:aa:a7:70:fa:8f:6c:a7:
50+
2b:b7:9d:81:46:10:32:93:b9:45:6d:0f:16:18:b2:21:1f:f3:
51+
30:24:62:3f:e1:6c:07:1d:71:28:cb:4c:bb:f5:39:05:f9:b2:
52+
5b:a0:05:1b
53+
-----BEGIN CERTIFICATE-----
54+
MIIC+zCCAeOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzEfMB0GA1UECgwWbmdp
55+
bngtcHJveHkgdGVzdCBzdWl0ZTEcMBoGA1UEAwwTd3d3Lm5naW54LXByb3h5LnRs
56+
ZDAeFw0xNzAxMTMwMzA2MzlaFw00NDA1MzEwMzA2MzlaMB4xHDAaBgNVBAMME3dl
57+
Yi5uZ2lueC1wcm94eS50bGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
58+
AQCVVscNSKUrPGVJPybhOCthMFbkktdj4OutrPkzm7Ix8TkTC+VDe8W9ioXI2T3Y
59+
rHG6FueBlrKrrsbAvb6n0ZaPspvfuvlNoTt+IUrNtkX5bXlQvySPwWvBCRlbYsuW
60+
6AQUIOjUFmJq8jfBluKdUwULUh3naJLbizZozY1bAv8S8KxdDMTgelWiSWCf/0cf
61+
UnNVTdTy0WKi9FCdyfbxQ7PcV+ExdrTgpGl+8m00rrmNdCZ72fYHAO9LNmGz73qh
62+
Njq20J74uKkNTDCi7eura+su4gsovvcEsenghNZdMXd83NIf1B1xb29sbRu/MeJb
63+
w1LQFPyL+0XqQezKxztnEsTfAgMBAAGjIjAgMB4GA1UdEQQXMBWCE3dlYi5uZ2lu
64+
eC1wcm94eS50bGQwDQYJKoZIhvcNAQELBQADggEBAE5IfYFmui9QPSRCYT8f3s/s
65+
Gxu9Cme2Ysh5nTGg/alhzv9pvw709+YVK7Dw5PL00o90ArEeSqhvJgp3MinP3LVh
66+
gj5YR2GS8AwgJfhBTTQJRLw5nqqCBoMTix4sPc/NGvd3OTjgo6fzCdoCjXN1OLTd
67+
JKf5A9uYxohUh9zgZUyVxTmcADDc8NMsGcrx9GzG2bXESse8oS6Ie7Uz0P/7SF4+
68+
KfpY5QPe2Bfe7Zb8fh/+mPa+mTiHUcDTt5oPJpLlUxvWJUysSPMp/HRknQdqJVck
69+
qqdw+o9spyu3nYFGEDKTuUVtDxYYsiEf8zAkYj/hbAcdcSjLTLv1OQX5slugBRs=
70+
-----END CERTIFICATE-----
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEogIBAAKCAQEAlVbHDUilKzxlST8m4TgrYTBW5JLXY+Drraz5M5uyMfE5Ewvl
3+
Q3vFvYqFyNk92KxxuhbngZayq67GwL2+p9GWj7Kb37r5TaE7fiFKzbZF+W15UL8k
4+
j8FrwQkZW2LLlugEFCDo1BZiavI3wZbinVMFC1Id52iS24s2aM2NWwL/EvCsXQzE
5+
4HpVoklgn/9HH1JzVU3U8tFiovRQncn28UOz3FfhMXa04KRpfvJtNK65jXQme9n2
6+
BwDvSzZhs+96oTY6ttCe+LipDUwwou3rq2vrLuILKL73BLHp4ITWXTF3fNzSH9Qd
7+
cW9vbG0bvzHiW8NS0BT8i/tF6kHsysc7ZxLE3wIDAQABAoIBAEmK7IecKMq7+V0y
8+
3mC3GpXICmKR9cRX9XgX4LkLiZuSoXrBtuuevmhzGSMp6I0VjwQHV4a3wdFORs6Q
9+
Ip3eVvj5Ck4Jc9BJAFVC6+WWR6tnwACFwOmSZRAw/O3GH2B3bdrDwiT/yQPFuLN7
10+
LKoxQiCrFdLp6rh3PBosb9pMBXU7k/HUazIdgmSKg6/JIoo/4Gwyid04TF/4MI2l
11+
RscxtP5/ANtS8VgwBEqhgdafRJ4KnLEpgvswgIQvUKmduVhZQlzd0LMY8FbhKVqz
12+
Utg8gsXaTyH6df/nmgUIInxLMz/MKPnMkv99fS6Sp/hvYlGpLZFWBJ6unMq3lKEr
13+
LMbHfIECgYEAxB+5QWdVqG2r9loJlf8eeuNeMPml4P8Jmi5RKyJC7Cww6DMlMxOS
14+
78ZJfl4b3ZrWuyvhjOfX/aTq7kQaF1BI9o3KJBH8k6EtO4gI8KeNmDONyQk9zsrn
15+
ru8Zwr7hVbAo8fCXxCnmPzhDLsYg6f3BVOsQWoX2SFYKZ1GvkPfIReECgYEAwu6G
16+
qtgFb57Vim10ecfWGM6vrPxvyfqP+zlH/p4nR+aQ+2sFbt27D0B1byWBRZe4KQyw
17+
Vq6XiQ09Fk6MJr8E8iAr9GXPPHcqlYI6bbNc6YOP3jVSKut0tQdTUOHll4kYIY+h
18+
RS3VA3+BA//ADpWpywu+7RZRbaIECA+U2a224r8CgYB5PCMIixgoRaNHZeEHF+1/
19+
iY1wOOKRcxY8eOU0BLnZxHd3EiasrCzoi2pi80nGczDKAxYqRCcAZDHVl8OJJdf0
20+
kTGjmnrHx5pucmkUWn7s1vGOlGfgrQ0K1kLWX6hrj7m/1Tn7yOrLqbvd7hvqiTI5
21+
jBVP3/+eN5G2zIf61TC4AQKBgCX2Q92jojNhsF58AHHy+/vqzIWYx8CC/mVDe4TX
22+
kfjLqzJ7XhyAK/zFZdlWaX1/FYtRAEpxR+uV226rr1mgW7s3jrfS1/ADmRRyvyQ8
23+
CP0k9PCmW7EmF51lptEanRbMyRlIGnUZfuFmhF6eAO4WMXHsgKs1bHg4VCapuihG
24+
T1aLAoGACRGn1UxFuBGqtsh2zhhsBZE7GvXKJSk/eP7QJeEXUNpNjCpgm8kIZM5K
25+
GorpL7PSB8mwVlDl18TpMm3P7nz6YkJYte+HdjO7pg59H39Uvtg3tZnIrFxNxVNb
26+
YF62/yHfk2AyTgjQZQUSmDS84jq1zUK4oS90lxr+u8qwELTniMs=
27+
-----END RSA PRIVATE KEY-----
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import pytest
2+
import re
3+
4+
5+
@pytest.mark.parametrize('url,header,input,want', [
6+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', None, 'http'),
7+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', 'f00', 'f00'),
8+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', None, 'https'),
9+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', 'f00', 'f00'),
10+
11+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', None, '80'),
12+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', '1234', '1234'),
13+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', None, '443'),
14+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', '1234', '1234'),
15+
])
16+
def test_downstream_proxy_header(docker_compose, nginxproxy, url, header, input, want):
17+
kwargs = {} if input is None else {'headers': {header: input}}
18+
r = nginxproxy.get(url, **kwargs)
19+
assert r.status_code == 200
20+
assert re.search(fr'(?m)^(?i:{re.escape(header)}): {re.escape(want)}$', r.text)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
web:
2+
image: web
3+
expose:
4+
- "80"
5+
environment:
6+
WEB_PORTS: 80
7+
VIRTUAL_HOST: web.nginx-proxy.tld
8+
HTTPS_METHOD: noredirect
9+
10+
11+
sut:
12+
image: nginxproxy/nginx-proxy:test
13+
volumes:
14+
- /var/run/docker.sock:/tmp/docker.sock:ro
15+
- ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro
16+
- ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import pytest
2+
import re
3+
4+
5+
@pytest.mark.parametrize('url,header,input,want', [
6+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', None, 'http'),
7+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', 'f00', 'http'),
8+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', None, 'https'),
9+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', 'f00', 'https'),
10+
11+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', None, '80'),
12+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', '1234', '80'),
13+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', None, '443'),
14+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', '1234', '443'),
15+
])
16+
def test_downstream_proxy_header(docker_compose, nginxproxy, url, header, input, want):
17+
kwargs = {} if input is None else {'headers': {header: input}}
18+
r = nginxproxy.get(url, **kwargs)
19+
assert r.status_code == 200
20+
assert re.search(fr'(?m)^(?i:{re.escape(header)}): {re.escape(want)}$', r.text)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
web:
2+
image: web
3+
expose:
4+
- "80"
5+
environment:
6+
WEB_PORTS: 80
7+
VIRTUAL_HOST: web.nginx-proxy.tld
8+
HTTPS_METHOD: noredirect
9+
10+
11+
sut:
12+
image: nginxproxy/nginx-proxy:test
13+
environment:
14+
TRUST_DOWNSTREAM_PROXY: "false"
15+
volumes:
16+
- /var/run/docker.sock:/tmp/docker.sock:ro
17+
- ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro
18+
- ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import pytest
2+
import re
3+
4+
5+
@pytest.mark.parametrize('url,header,input,want', [
6+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', None, 'http'),
7+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', 'f00', 'f00'),
8+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', None, 'https'),
9+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Proto', 'f00', 'f00'),
10+
11+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', None, '80'),
12+
('http://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', '1234', '1234'),
13+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', None, '443'),
14+
('https://web.nginx-proxy.tld/headers', 'X-Forwarded-Port', '1234', '1234'),
15+
])
16+
def test_downstream_proxy_header(docker_compose, nginxproxy, url, header, input, want):
17+
kwargs = {} if input is None else {'headers': {header: input}}
18+
r = nginxproxy.get(url, **kwargs)
19+
assert r.status_code == 200
20+
assert re.search(fr'(?m)^(?i:{re.escape(header)}): {re.escape(want)}$', r.text)

0 commit comments

Comments
 (0)