浏览代码

Make server_tokens configurable per virtual-host

Laurynas Alekna 4 年之前
父节点
当前提交
fb7a11212f

+ 4 - 0
README.md

@@ -421,6 +421,10 @@ If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=e
 If you want most of your virtual hosts to use a default single `location` block configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default_location` file. This file
 If you want most of your virtual hosts to use a default single `location` block configuration and then override on a few specific ones, add those settings to the `/etc/nginx/vhost.d/default_location` file. This file
 will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}_location` file associated with it.
 will be used on any virtual host which does not have a `/etc/nginx/vhost.d/{VIRTUAL_HOST}_location` file associated with it.
 
 
+#### Per-VIRTUAL_HOST `server_tokens` configuration
+Per virtual-host `servers_tokens` directive can be configured by passing appropriate value to the `SERVER_TOKENS` environment variable. Please see the [nginx http_core module configuration](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) for more details.
+
+
 ### Contributing
 ### Contributing
 
 
 Before submitting pull requests or issues, please check github to make sure an existing issue or pull request is not already open.
 Before submitting pull requests or issues, please check github to make sure an existing issue or pull request is not already open.

+ 17 - 0
nginx.tmpl

@@ -143,6 +143,7 @@ proxy_set_header Proxy "";
 {{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
 {{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
 server {
 server {
 	server_name _; # This is just an invalid value which will never trigger on a real hostname.
 	server_name _; # This is just an invalid value which will never trigger on a real hostname.
+	server_tokens off;
 	listen {{ $external_http_port }};
 	listen {{ $external_http_port }};
 	{{ if $enable_ipv6 }}
 	{{ if $enable_ipv6 }}
 	listen [::]:{{ $external_http_port }};
 	listen [::]:{{ $external_http_port }};
@@ -154,6 +155,7 @@ server {
 {{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
 {{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
 server {
 server {
 	server_name _; # This is just an invalid value which will never trigger on a real hostname.
 	server_name _; # This is just an invalid value which will never trigger on a real hostname.
+	server_tokens off;
 	listen {{ $external_https_port }} ssl http2;
 	listen {{ $external_https_port }} ssl http2;
 	{{ if $enable_ipv6 }}
 	{{ if $enable_ipv6 }}
 	listen [::]:{{ $external_https_port }} ssl http2;
 	listen [::]:{{ $external_https_port }} ssl http2;
@@ -210,6 +212,9 @@ upstream {{ $upstream_name }} {
 {{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
 {{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
 {{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }}
 {{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }}
 
 
+{{/* Get the SERVER_TOKENS defined by containers w/ the same vhost, falling back to "" */}}
+{{ $server_tokens := trim (or (first (groupByKeys $containers "Env.SERVER_TOKENS")) "") }}
+
 {{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}}
 {{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}}
 {{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }}
 {{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }}
 
 
@@ -246,6 +251,9 @@ upstream {{ $upstream_name }} {
 {{ if eq $https_method "redirect" }}
 {{ if eq $https_method "redirect" }}
 server {
 server {
 	server_name {{ $host }};
 	server_name {{ $host }};
+	{{ if $server_tokens }}
+	server_tokens {{ $server_tokens }};
+	{{ end }}
 	listen {{ $external_http_port }} {{ $default_server }};
 	listen {{ $external_http_port }} {{ $default_server }};
 	{{ if $enable_ipv6 }}
 	{{ if $enable_ipv6 }}
 	listen [::]:{{ $external_http_port }} {{ $default_server }};
 	listen [::]:{{ $external_http_port }} {{ $default_server }};
@@ -270,6 +278,9 @@ server {
 
 
 server {
 server {
 	server_name {{ $host }};
 	server_name {{ $host }};
+	{{ if $server_tokens }}
+	server_tokens {{ $server_tokens }};
+	{{ end }}
 	listen {{ $external_https_port }} ssl http2 {{ $default_server }};
 	listen {{ $external_https_port }} ssl http2 {{ $default_server }};
 	{{ if $enable_ipv6 }}
 	{{ if $enable_ipv6 }}
 	listen [::]:{{ $external_https_port }} ssl http2 {{ $default_server }};
 	listen [::]:{{ $external_https_port }} ssl http2 {{ $default_server }};
@@ -342,6 +353,9 @@ server {
 
 
 server {
 server {
 	server_name {{ $host }};
 	server_name {{ $host }};
+	{{ if $server_tokens }}
+	server_tokens {{ $server_tokens }};
+	{{ end }}
 	listen {{ $external_http_port }} {{ $default_server }};
 	listen {{ $external_http_port }} {{ $default_server }};
 	{{ if $enable_ipv6 }}
 	{{ if $enable_ipv6 }}
 	listen [::]:80 {{ $default_server }};
 	listen [::]:80 {{ $default_server }};
@@ -387,6 +401,9 @@ server {
 {{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
 {{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
 server {
 server {
 	server_name {{ $host }};
 	server_name {{ $host }};
+	{{ if $server_tokens }}
+	server_tokens {{ $server_tokens }};
+	{{ end }}
 	listen {{ $external_https_port }} ssl http2 {{ $default_server }};
 	listen {{ $external_https_port }} ssl http2 {{ $default_server }};
 	{{ if $enable_ipv6 }}
 	{{ if $enable_ipv6 }}
 	listen [::]:{{ $external_https_port }} ssl http2 {{ $default_server }};
 	listen [::]:{{ $external_https_port }} ssl http2 {{ $default_server }};

+ 21 - 4
test/conftest.py

@@ -1,17 +1,19 @@
 import contextlib
 import contextlib
 import logging
 import logging
 import os
 import os
+import re
 import shlex
 import shlex
 import socket
 import socket
 import subprocess
 import subprocess
 import time
 import time
-import re
+from typing import List
 
 
 import backoff
 import backoff
 import docker
 import docker
 import pytest
 import pytest
 import requests
 import requests
 from _pytest._code.code import ReprExceptionInfo
 from _pytest._code.code import ReprExceptionInfo
+from docker.models.containers import Container
 from requests.packages.urllib3.util.connection import HAS_IPV6
 from requests.packages.urllib3.util.connection import HAS_IPV6
 
 
 logging.basicConfig(level=logging.INFO)
 logging.basicConfig(level=logging.INFO)
@@ -63,17 +65,32 @@ class requests_for_docker(object):
         if os.path.isfile(CA_ROOT_CERTIFICATE):
         if os.path.isfile(CA_ROOT_CERTIFICATE):
             self.session.verify = CA_ROOT_CERTIFICATE
             self.session.verify = CA_ROOT_CERTIFICATE
 
 
-    def get_conf(self):
+    @staticmethod
+    def get_nginx_proxy_containers() -> List[Container]:
         """
         """
-        Return the nginx config file
+        Return list of containers
         """
         """
         nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"})
         nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"})
         if len(nginx_proxy_containers) > 1:
         if len(nginx_proxy_containers) > 1:
             pytest.fail("Too many running nginxproxy/nginx-proxy:test containers", pytrace=False)
             pytest.fail("Too many running nginxproxy/nginx-proxy:test containers", pytrace=False)
         elif len(nginx_proxy_containers) == 0:
         elif len(nginx_proxy_containers) == 0:
             pytest.fail("No running nginxproxy/nginx-proxy:test container", pytrace=False)
             pytest.fail("No running nginxproxy/nginx-proxy:test container", pytrace=False)
+        return nginx_proxy_containers
+
+    def get_conf(self):
+        """
+        Return the nginx config file
+        """
+        nginx_proxy_containers = self.get_nginx_proxy_containers()
         return get_nginx_conf_from_container(nginx_proxy_containers[0])
         return get_nginx_conf_from_container(nginx_proxy_containers[0])
 
 
+    def get_ip(self) -> str:
+        """
+        Return the nginx container ip address
+        """
+        nginx_proxy_containers = self.get_nginx_proxy_containers()
+        return container_ip(nginx_proxy_containers[0])
+
     def get(self, *args, **kwargs):
     def get(self, *args, **kwargs):
         with ipv6(kwargs.pop('ipv6', False)):
         with ipv6(kwargs.pop('ipv6', False)):
             @backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
             @backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
@@ -120,7 +137,7 @@ class requests_for_docker(object):
         return getattr(requests, name)
         return getattr(requests, name)
 
 
 
 
-def container_ip(container):
+def container_ip(container: Container):
     """
     """
     return the IP address of a container.
     return the IP address of a container.
 
 

+ 71 - 0
test/test_headers/certs/web-server-tokens-off.nginx-proxy.tld.crt

@@ -0,0 +1,71 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4096 (0x1000)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: O=nginx-proxy test suite, CN=www.nginx-proxy.tld
+        Validity
+            Not Before: May 11 18:25:49 2021 GMT
+            Not After : Sep 26 18:25:49 2048 GMT
+        Subject: CN=web-server-tokens-off.nginx-proxy.tld
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (2048 bit)
+                Modulus:
+                    00:b4:fa:9d:8a:74:3f:17:ea:99:1c:45:71:18:90:
+                    eb:92:35:38:d7:90:21:81:0a:91:05:41:cf:b5:87:
+                    34:bd:d8:7b:7f:7d:06:33:f8:94:67:8e:e4:07:54:
+                    7f:b7:62:c5:76:6c:7f:7c:19:25:19:2c:36:9a:26:
+                    54:8e:2d:97:02:78:31:c6:13:d3:ad:f3:31:62:e6:
+                    cf:96:ae:63:37:dd:bd:73:cb:4e:fb:3f:9b:65:67:
+                    97:d8:5a:5d:0e:72:b1:11:ab:0e:d7:23:a9:b7:22:
+                    de:23:74:7e:88:7c:28:98:a9:6e:00:f4:be:8c:69:
+                    ea:3f:33:8b:19:97:da:1b:a6:65:b5:5a:92:01:3c:
+                    3a:13:6b:00:02:e1:98:78:d3:da:ea:a6:9c:33:b0:
+                    1d:9f:02:c4:f1:d0:d6:de:7a:f7:42:12:4b:31:fb:
+                    ed:e9:d7:d8:15:e8:4e:18:91:7c:9d:bf:0f:b0:12:
+                    d6:e2:80:8b:7a:ef:17:70:51:f4:3c:b7:43:cb:56:
+                    61:af:61:7a:4e:9d:6c:5e:d8:27:0c:3b:d7:a4:1d:
+                    2f:0d:a0:99:8f:b5:71:93:21:b4:87:be:b4:1c:77:
+                    a0:b9:cd:91:bd:9c:d0:b9:81:50:12:63:d2:0a:a9:
+                    61:05:91:19:27:f7:ea:9d:8e:48:65:2e:1a:e7:fd:
+                    f1:b7
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Alternative Name:
+                DNS:web-server-tokens-off.nginx-proxy.tld
+    Signature Algorithm: sha256WithRSAEncryption
+         5b:b7:74:ad:07:08:65:3c:8e:02:50:a9:b6:f4:8d:47:95:6f:
+         e0:ba:5a:8c:ae:5c:32:88:8b:45:04:48:ce:3d:72:45:d7:7e:
+         1e:d7:75:17:30:98:90:21:4c:67:e2:57:1d:c9:fa:03:f4:81:
+         64:cf:d2:b3:85:71:be:53:b9:2a:fd:89:04:a6:b1:88:0a:0a:
+         f1:5c:93:9b:fb:4f:86:0e:c5:4d:6a:ff:54:7b:07:f1:7e:d1:
+         8a:6b:fa:3b:f3:5c:d2:1b:2c:86:05:4c:e0:b4:04:0d:c7:db:
+         0b:89:b4:33:09:b6:1a:f0:cb:d4:ae:2c:05:63:a4:18:19:52:
+         c7:15:21:ac:ae:9e:15:b9:b0:58:0c:96:df:7b:77:46:ef:59:
+         a7:96:56:da:f6:f6:81:9f:10:7d:5a:48:68:0c:28:02:5d:7b:
+         69:4d:89:41:e2:88:6d:c6:22:45:6a:34:1b:ba:9b:6f:d6:2d:
+         c2:55:b1:73:b4:bb:f5:06:d6:5f:ed:01:d1:3c:51:8b:e2:6c:
+         31:d7:6b:a5:bd:05:e3:9a:97:15:40:bf:bb:8f:81:e5:bf:bc:
+         06:66:47:84:fe:f7:06:fb:5d:35:9e:04:26:0d:aa:3d:b5:92:
+         6b:90:c2:1c:17:ac:c1:95:d9:6b:f1:5d:0a:09:9f:a7:a6:ca:
+         3b:45:a4:59
+-----BEGIN CERTIFICATE-----
+MIIDHzCCAgegAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzEfMB0GA1UECgwWbmdp
+bngtcHJveHkgdGVzdCBzdWl0ZTEcMBoGA1UEAwwTd3d3Lm5naW54LXByb3h5LnRs
+ZDAeFw0yMTA1MTExODI1NDlaFw00ODA5MjYxODI1NDlaMDAxLjAsBgNVBAMMJXdl
+Yi1zZXJ2ZXItdG9rZW5zLW9mZi5uZ2lueC1wcm94eS50bGQwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC0+p2KdD8X6pkcRXEYkOuSNTjXkCGBCpEFQc+1
+hzS92Ht/fQYz+JRnjuQHVH+3YsV2bH98GSUZLDaaJlSOLZcCeDHGE9Ot8zFi5s+W
+rmM33b1zy077P5tlZ5fYWl0OcrERqw7XI6m3It4jdH6IfCiYqW4A9L6Maeo/M4sZ
+l9obpmW1WpIBPDoTawAC4Zh409rqppwzsB2fAsTx0NbeevdCEksx++3p19gV6E4Y
+kXydvw+wEtbigIt67xdwUfQ8t0PLVmGvYXpOnWxe2CcMO9ekHS8NoJmPtXGTIbSH
+vrQcd6C5zZG9nNC5gVASY9IKqWEFkRkn9+qdjkhlLhrn/fG3AgMBAAGjNDAyMDAG
+A1UdEQQpMCeCJXdlYi1zZXJ2ZXItdG9rZW5zLW9mZi5uZ2lueC1wcm94eS50bGQw
+DQYJKoZIhvcNAQELBQADggEBAFu3dK0HCGU8jgJQqbb0jUeVb+C6WoyuXDKIi0UE
+SM49ckXXfh7XdRcwmJAhTGfiVx3J+gP0gWTP0rOFcb5TuSr9iQSmsYgKCvFck5v7
+T4YOxU1q/1R7B/F+0Ypr+jvzXNIbLIYFTOC0BA3H2wuJtDMJthrwy9SuLAVjpBgZ
+UscVIayunhW5sFgMlt97d0bvWaeWVtr29oGfEH1aSGgMKAJde2lNiUHiiG3GIkVq
+NBu6m2/WLcJVsXO0u/UG1l/tAdE8UYvibDHXa6W9BeOalxVAv7uPgeW/vAZmR4T+
+9wb7XTWeBCYNqj21kmuQwhwXrMGV2WvxXQoJn6emyjtFpFk=
+-----END CERTIFICATE-----

+ 27 - 0
test/test_headers/certs/web-server-tokens-off.nginx-proxy.tld.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAtPqdinQ/F+qZHEVxGJDrkjU415AhgQqRBUHPtYc0vdh7f30G
+M/iUZ47kB1R/t2LFdmx/fBklGSw2miZUji2XAngxxhPTrfMxYubPlq5jN929c8tO
++z+bZWeX2FpdDnKxEasO1yOptyLeI3R+iHwomKluAPS+jGnqPzOLGZfaG6ZltVqS
+ATw6E2sAAuGYeNPa6qacM7AdnwLE8dDW3nr3QhJLMfvt6dfYFehOGJF8nb8PsBLW
+4oCLeu8XcFH0PLdDy1Zhr2F6Tp1sXtgnDDvXpB0vDaCZj7VxkyG0h760HHeguc2R
+vZzQuYFQEmPSCqlhBZEZJ/fqnY5IZS4a5/3xtwIDAQABAoIBAAaBi/BSRYJimKZ/
+iJVNgGp9J1H4iHvPGW+K8iCgf7Dje20V3Yc4xH0EkgYBb6X0Ew0y0VJwxPimsj/Q
+aPHDic446/Em/VEfkQLxMT1Ff6OegRUMlgZKPxfiJX9NoFLIpLzx3VK2oX9H7Zxw
+r6vQatUyIhY+tiruE9G51KJS5zBfN388ErfRUI8ByBaDGH0huA6kTBcNffhCfZr5
+9naWSIIcuBe8v7z6nAaeYL00q1q3vuWPmuQduSgsmef7QuN71CIxuOAqXTJl8koS
+LYNbj8yvIy3nOF90D+uZD/Pa2Y0kB6aum09hbUP15K0QFKulbKLRQ60IuvRcw3Qv
+MM177OECgYEA5Rw3qUcoTDfsx+nu2BxECj62uyNVZfX/QMf7dvzCqjXuOhij+KBB
+U9xnNfuLc4HfCXx/rMg5dGExEBbD2iHAo0nvnCSxzLJmF6i66Uves0VWISXcv2Au
+L0TWMhhsbDFoqkWuxXr69oNwKyl9yFRFWEY3p3G+aBAEqWZ1lOkU8O0CgYEAyjhC
+bN4mJJYhvX+cXhv+89Z+JIDAvtvQ5Vy7kxvhQUTx2By6rWKKrBPdTnzsxBGKqQwv
+lXzfgj/MlIr6A6QDReGwU3ZXTJqSGEuT8Ra9SbjczQgaGOrPCrWhnbeZ18iM67pJ
+LPfLgdRdkh3XgbOOKcDhpg2KybbbyXx6Q2xb7LMCgYEAzKHKWUh0BreApgIcUSvV
+3ayr+zOQ5/Oy24KC6IDTwcFPmNY/RiakkqluCfo1UKKzuj5XrtRa9MaGUs9yeJbi
+/zVfbQAdSi4hH4qV/x/Dtiz8w7iUlN3sAk4iXjYQSQZMbKC2fC3ej2VQP0zcypvy
+H+j/dnASV9HOyBr6dFlGWfUCgYB3gfYntsXd+2fnQOJdb7glzM5xrjG62dfDpSEp
+mGFwHFm8+YWNcF45weeZOhUG7sL+krgQZWMF68RwyQ1mV2ijxPRa7uY63GKYvxmo
+cmLdjcXX2gDqVuKTFrJzrgzaTKiTq10RmUQI70N5Ve+FtGLA5D+2zewGt+1+TvVG
+oWRWJwKBgAUpJ/NXOB82ie9RtwfAeuiD0yDPM3gNFVe0udAyG/71nXyHiW5aHn/w
+H+QSliw7gqir4u6bcrprFQMcwiowtCfeDkcXoQCOBx6TvL2zZTrG7J/68yDHfHGg
+w3eFN7ac8FsliRpT+UVKM97zJXcWFkai5Q+R7oKsWXRVXQUZZxg9
+-----END RSA PRIVATE KEY-----

+ 21 - 3
test/test_headers/test_http.py

@@ -1,5 +1,3 @@
-import pytest
-
 def test_arbitrary_headers_are_passed_on(docker_compose, nginxproxy):
 def test_arbitrary_headers_are_passed_on(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'})
     r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'})
     assert r.status_code == 200
     assert r.status_code == 200
@@ -78,4 +76,24 @@ def test_httpoxy_safe(docker_compose, nginxproxy):
     r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Proxy': 'tcp://some.hacker.com'})
     r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Proxy': 'tcp://some.hacker.com'})
     assert r.status_code == 200
     assert r.status_code == 200
     assert "Proxy:" not in r.text
     assert "Proxy:" not in r.text
-    
+
+
+def test_no_host_server_tokens_off(docker_compose, nginxproxy):
+    ip = nginxproxy.get_ip()
+    r = nginxproxy.get(f"http://{ip}/headers")
+    assert r.status_code == 503
+    assert r.headers["Server"] == "nginx"
+
+
+def test_server_tokens_on(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://web.nginx-proxy.tld/headers")
+    assert r.status_code == 200
+    assert "Host: web.nginx-proxy.tld" in r.text
+    assert r.headers["Server"].startswith("nginx/")
+
+
+def test_server_tokens_off(docker_compose, nginxproxy):
+    r = nginxproxy.get("http://web-server-tokens-off.nginx-proxy.tld/headers")
+    assert r.status_code == 200
+    assert "Host: web-server-tokens-off.nginx-proxy.tld" in r.text
+    assert r.headers["Server"] == "nginx"

+ 9 - 0
test/test_headers/test_http.yml

@@ -6,6 +6,15 @@ web:
     WEB_PORTS: 80
     WEB_PORTS: 80
     VIRTUAL_HOST: web.nginx-proxy.tld
     VIRTUAL_HOST: web.nginx-proxy.tld
 
 
+web-server-tokens-off:
+  image: web
+  expose:
+    - "80"
+  environment:
+    WEB_PORTS: 80
+    VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld
+    SERVER_TOKENS: "off"
+
 
 
 sut:
 sut:
   image: nginxproxy/nginx-proxy:test
   image: nginxproxy/nginx-proxy:test

+ 21 - 4
test/test_headers/test_https.py

@@ -1,6 +1,3 @@
-import pytest
-
-
 def test_arbitrary_headers_are_passed_on(docker_compose, nginxproxy):
 def test_arbitrary_headers_are_passed_on(docker_compose, nginxproxy):
     r = nginxproxy.get("https://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'})
     r = nginxproxy.get("https://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'})
     assert r.status_code == 200
     assert r.status_code == 200
@@ -79,4 +76,24 @@ def test_httpoxy_safe(docker_compose, nginxproxy):
     r = nginxproxy.get("https://web.nginx-proxy.tld/headers", headers={'Proxy': 'tcp://some.hacker.com'})
     r = nginxproxy.get("https://web.nginx-proxy.tld/headers", headers={'Proxy': 'tcp://some.hacker.com'})
     assert r.status_code == 200
     assert r.status_code == 200
     assert "Proxy:" not in r.text
     assert "Proxy:" not in r.text
-    
+
+
+def test_no_host_server_tokens_off(docker_compose, nginxproxy):
+    ip = nginxproxy.get_ip()
+    r = nginxproxy.get(f"https://{ip}/headers", verify=False)
+    assert r.status_code == 503
+    assert r.headers["Server"] == "nginx"
+
+
+def test_server_tokens_on(docker_compose, nginxproxy):
+    r = nginxproxy.get("https://web.nginx-proxy.tld/headers", verify=False)
+    assert r.status_code == 200
+    assert "Host: web.nginx-proxy.tld" in r.text
+    assert r.headers["Server"].startswith("nginx/")
+
+
+def test_server_tokens_off(docker_compose, nginxproxy):
+    r = nginxproxy.get("https://web-server-tokens-off.nginx-proxy.tld/headers")
+    assert r.status_code == 200
+    assert "Host: web-server-tokens-off.nginx-proxy.tld" in r.text
+    assert r.headers["Server"] == "nginx"

+ 13 - 0
test/test_headers/test_https.yml

@@ -6,11 +6,24 @@ web:
     WEB_PORTS: 80
     WEB_PORTS: 80
     VIRTUAL_HOST: web.nginx-proxy.tld
     VIRTUAL_HOST: web.nginx-proxy.tld
 
 
+web-server-tokens-off:
+  image: web
+  expose:
+    - "80"
+  environment:
+    WEB_PORTS: 80
+    VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld
+    SERVER_TOKENS: "off"
+
 
 
 sut:
 sut:
   image: nginxproxy/nginx-proxy:test
   image: nginxproxy/nginx-proxy:test
   volumes:
   volumes:
     - /var/run/docker.sock:/tmp/docker.sock:ro
     - /var/run/docker.sock:/tmp/docker.sock:ro
+    - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/default.crt:ro
+    - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/default.key:ro
     - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro
     - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro
     - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro
     - ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro
+    - ./certs/web-server-tokens-off.nginx-proxy.tld.crt:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.crt:ro
+    - ./certs/web-server-tokens-off.nginx-proxy.tld.key:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.key:ro
     - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro
     - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro