瀏覽代碼

feat: Replace generated DH params with RFC 7919 standardized DHE groups

- While the anonymous VOLUME can be dropped from Dockerfile, the path needs to be valid at run-time, might as well ensure it's available by creating the dhparam folder at build.

- Generation logic no longer necessary, dropped. 

- Standardized RFC 7919 groups added (2048, 3072, 4096), with 4096-bit remaining the default size. The DH logic can live in the entrypoint script as well. 

- Third-party supplied pre-generated DH params removed as they're not considered trustworthy compared to RFC 7919 groups.
polarathene 3 年之前
父節點
當前提交
ac066a73e4
共有 9 個文件被更改,包括 75 次插入78 次删除
  1. 3 2
      Dockerfile
  2. 3 2
      Dockerfile.alpine
  3. 5 11
      README.md
  4. 0 8
      dhparam.pem.default
  5. 8 0
      dhparam/ffdhe2048.pem
  6. 11 0
      dhparam/ffdhe3072.pem
  7. 13 0
      dhparam/ffdhe4096.pem
  8. 32 2
      docker-entrypoint.sh
  9. 0 53
      generate-dhparam.sh

+ 3 - 2
Dockerfile

@@ -51,7 +51,8 @@ RUN apt-get update \
 # Configure Nginx and apply fix for very long server names
 RUN echo "daemon off;" >> /etc/nginx/nginx.conf \
    && sed -i 's/worker_processes  1/worker_processes  auto/' /etc/nginx/nginx.conf \
-   && sed -i 's/worker_connections  1024/worker_connections  10240/' /etc/nginx/nginx.conf
+   && sed -i 's/worker_connections  1024/worker_connections  10240/' /etc/nginx/nginx.conf \
+   && mkdir -p '/etc/nginx/dhparam'
 
 # Install Forego + docker-gen
 COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego
@@ -69,7 +70,7 @@ WORKDIR /app/
 
 ENV DOCKER_HOST unix:///tmp/docker.sock
 
-VOLUME ["/etc/nginx/certs", "/etc/nginx/dhparam"]
+VOLUME ["/etc/nginx/certs"]
 
 ENTRYPOINT ["/app/docker-entrypoint.sh"]
 CMD ["forego", "start", "-r"]

+ 3 - 2
Dockerfile.alpine

@@ -48,7 +48,8 @@ RUN apk add --no-cache --virtual .run-deps \
 # Configure Nginx and apply fix for very long server names
 RUN echo "daemon off;" >> /etc/nginx/nginx.conf \
    && sed -i 's/worker_processes  1/worker_processes  auto/' /etc/nginx/nginx.conf \
-   && sed -i 's/worker_connections  1024/worker_connections  10240/' /etc/nginx/nginx.conf
+   && sed -i 's/worker_connections  1024/worker_connections  10240/' /etc/nginx/nginx.conf \
+   && mkdir -p '/etc/nginx/dhparam'
 
 # Install Forego + docker-gen
 COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego
@@ -66,7 +67,7 @@ WORKDIR /app/
 
 ENV DOCKER_HOST unix:///tmp/docker.sock
 
-VOLUME ["/etc/nginx/certs", "/etc/nginx/dhparam"]
+VOLUME ["/etc/nginx/certs"]
 
 ENTRYPOINT ["/app/docker-entrypoint.sh"]
 CMD ["forego", "start", "-r"]

+ 5 - 11
README.md

@@ -237,12 +237,6 @@ docker run -e VIRTUAL_HOST=foo.bar.com  ...
 
 [acme-companion](https://github.com/nginx-proxy/acme-companion) is a lightweight companion container for the nginx-proxy. It allows the automated creation/renewal of SSL certificates using the ACME protocol.
 
-Set `DHPARAM_GENERATION` environment variable to `false` to disable Diffie-Hellman parameters completely. This will also ignore auto-generation made by `nginx-proxy`. The default value is `true`
-
-```console
-docker run -e DHPARAM_GENERATION=false ....
-```
-
 ### SSL Support
 
 SSL is supported using single host, wildcard and SNI certificates using naming conventions for certificates or optionally specifying a cert name (for SNI) as an environment variable.
@@ -259,13 +253,13 @@ If you are running the container in a virtualized environment (Hyper-V, VirtualB
 
 #### Diffie-Hellman Groups
 
-Diffie-Hellman groups are enabled by default, with a pregenerated key in `/etc/nginx/dhparam/dhparam.pem`. You can mount a different `dhparam.pem` file at that location to override the default cert. To use custom `dhparam.pem` files per-virtual-host, the files should be named after the virtual host with a `dhparam` suffix and `.pem` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a `foo.bar.com.dhparam.pem` file in the `/etc/nginx/certs` directory.
+[RFC7919 groups](https://datatracker.ietf.org/doc/html/rfc7919#appendix-A) with key lengths of 2048, 3072, and 4096 bits are [provided by `nginx-proxy`](https://github.com/nginx-proxy/nginx-proxy/dhparam). The ENV `DHPARAM_BITS` can be set to `2048` or `3072` to change from the default 4096-bit key. The DH key file will be located in the container at `/etc/nginx/dhparam/dhparam.pem`. Mounting a different `dhparam.pem` file at that location will override the RFC7919 key.
 
-> NOTE: If you don't mount a `dhparam.pem` file at `/etc/nginx/dhparam/dhparam.pem`, one will be generated at startup.  Since it can take minutes to generate a new `dhparam.pem`, it is done at low priority in the background. Once generation is complete, the `dhparam.pem` is saved on a persistent volume and nginx is reloaded. This generation process only occurs the first time you start `nginx-proxy`.
+To use custom `dhparam.pem` files per-virtual-host, the files should be named after the virtual host with a `dhparam` suffix and `.pem` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a `foo.bar.com.dhparam.pem` file in the `/etc/nginx/certs` directory.
 
-> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 4096 bits for A+ security. Some older clients (like Java 6 and 7) do not support DH keys with over 1024 bits. In order to support these clients, you must either provide your own `dhparam.pem`, or tell `nginx-proxy` to generate a 1024-bit key on startup by passing `-e DHPARAM_BITS=1024`.
+> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 4096 bits for A+ security. Some older clients (like Java 6 and 7) do not support DH keys with over 1024 bits. In order to support these clients, you must either provide your own `dhparam.pem`.
 
-In the separate container setup, no pregenerated key will be available and neither the [jwilder/docker-gen](https://hub.docker.com/r/jwilder/docker-gen) image nor the offical [nginx](https://registry.hub.docker.com/_/nginx/) image will generate one. If you still want A+ security in a separate container setup, you'll have to generate a 2048 or 4096 bits DH key file manually and mount it on the nginx container, at `/etc/nginx/dhparam/dhparam.pem`.
+In the separate container setup, no pre-generated key will be available and neither the [jwilder/docker-gen](https://hub.docker.com/r/jwilder/docker-gen) image, nor the offical [nginx](https://registry.hub.docker.com/_/nginx/) image will provide one. If you still want A+ security in a separate container setup, you should mount an RFC7919 DH key file to the nginx container at `/etc/nginx/dhparam/dhparam.pem`.
 
 #### Wildcard Certificates
 
@@ -287,7 +281,7 @@ If you don't require backward compatibility, you can use the [Mozilla modern pro
 
 Other policies available through the `SSL_POLICY` environment variable are [`Mozilla-Old`](https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility) and the [AWS ELB Security Policies](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html) `AWS-TLS-1-2-2017-01`, `AWS-TLS-1-1-2017-01`, `AWS-2016-08`, `AWS-2015-05`, `AWS-2015-03` and `AWS-2015-02`.
 
-Note that the `Mozilla-Old` policy should use a 1024 bits DH key for compatibility but this container generates a 4096 bits key. The [Diffie-Hellman Groups](#diffie-hellman-groups) section details different methods of bypassing this, either globally or per virtual-host.
+Note that the `Mozilla-Old` policy should use a 1024 bits DH key for compatibility but this container provides a 4096 bits key. The [Diffie-Hellman Groups](#diffie-hellman-groups) section details different methods of bypassing this, either globally or per virtual-host.
 
 The default behavior for the proxy when port 80 and 443 are exposed is as follows:
 

+ 0 - 8
dhparam.pem.default

@@ -1,8 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEAzB2nIGzpVq7afJnKBm1X0d64avwOlP2oneiKwxRHdDI/5+6TpH1P
-F8ipodGuZBUMmupoB3D34pu2Qq5boNW983sm18ww9LMz2i/pxhSdB+mYAew+A6h6
-ltQ5pNtyn4NaKw1SDFkqvde3GNPhaWoPDbZDJhpHGblR3w1b/ag+lTLZUvVwcD8L
-jYS9f9YWAC6T7WxAxh4zvu1Z0I1EKde8KYBxrreZNheXpXHqMNyJYZCaY2Hb/4oI
-EL65qZq1GCWezpWMjhk6pOnV5gbvqfhoazCv/4OdRv6RoWOIYBNs9BmGho4AtXqV
-FYLdYDhOvN4aVs9Ir+G8ouwiRnix24+UewIBAg==
------END DH PARAMETERS-----

+ 8 - 0
dhparam/ffdhe2048.pem

@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
+-----END DH PARAMETERS-----

+ 11 - 0
dhparam/ffdhe3072.pem

@@ -0,0 +1,11 @@
+-----BEGIN DH PARAMETERS-----
+MIIBiAKCAYEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
+7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
+nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZsYu
+N///////////AgEC
+-----END DH PARAMETERS-----

+ 13 - 0
dhparam/ffdhe4096.pem

@@ -0,0 +1,13 @@
+-----BEGIN DH PARAMETERS-----
+MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3
+7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32
+nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e
+8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx
+iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K
+zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=
+-----END DH PARAMETERS-----

+ 32 - 2
docker-entrypoint.sh

@@ -1,6 +1,37 @@
 #!/bin/bash
 set -e
 
+function _setup_dhparam() {
+	echo 'Setting up DH Parameters..'
+
+	# DH params will be supplied for nginx here:
+	DHPARAM_FILE='/etc/nginx/dhparam/dhparam.pem'
+
+	# DH params may be provided by the user (rarely necessary),
+	# or use an existing pre-generated group from RFC7919, defaulting to 4096-bit:
+	if [[ -f ${DHPARAM_FILE} ]]
+	then
+		echo 'Warning: A custom dhparam.pem file was provided. Best practice is to use standardized RFC7919 DHE groups instead.' >&2
+	else
+		# ENV DHPARAM_BITS - Defines which RFC7919 DHE group to use (default: 4096-bit):
+		local FFDHE_GROUP="${DHPARAM_BITS:-4096}"
+		# RFC7919 groups are defined here:
+		# https://datatracker.ietf.org/doc/html/rfc7919#appendix-A
+		local RFC7919_DHPARAM_FILE="/app/dhparam/ffdhe${FFDHE_GROUP}.pem"
+
+		# Only the following pre-generated sizes are supported,
+		# emit an error and kill the container if provided an invalid value:
+		if [[ ! ${DHPARAM_BITS} =~ ^(2048|3072|4096)$ ]]
+		then
+			echo "ERROR: Unsupported DHPARAM_BITS size: ${DHPARAM_BITS}, use 2048, 3072, or 4096 (default)." >&2
+			exit 1
+		fi
+
+		# Provide the DH params file to nginx:
+		cp "${RFC7919_DHPARAM_FILE}" "${DHPARAM_FILE}"
+	fi
+}
+
 # Warn if the DOCKER_HOST socket does not exist
 if [[ $DOCKER_HOST = unix://* ]]; then
 	socket_file=${DOCKER_HOST#unix://}
@@ -14,8 +45,7 @@ if [[ $DOCKER_HOST = unix://* ]]; then
 	fi
 fi
 
-# Generate dhparam file if required
-/app/generate-dhparam.sh
+_setup_dhparam
 
 # Compute the DNS resolvers for use in the templates - if the IP contains ":", it's IPv6 and must be enclosed in []
 RESOLVERS=$(awk '$1 == "nameserver" {print ($2 ~ ":")? "["$2"]": $2}' ORS=' ' /etc/resolv.conf | sed 's/ *$//g'); export RESOLVERS

+ 0 - 53
generate-dhparam.sh

@@ -1,53 +0,0 @@
-#!/bin/bash -e
-
-# DHPARAM_BITS is the bit depth of the dhparam, or 4096 if unspecified
-DHPARAM_BITS=${DHPARAM_BITS:-4096}
-# DHPARAM_GENERATION=false skips dhparam generation
-DHPARAM_GENERATION=${DHPARAM_GENERATION:-true}
-
-# If a dhparam file is not available, use the pre-generated one and generate a new one in the background.
-# Note that /etc/nginx/dhparam is a volume, so this dhparam will persist restarts.
-PREGEN_DHPARAM_FILE="/app/dhparam.pem.default"
-DHPARAM_FILE="/etc/nginx/dhparam/dhparam.pem"
-GEN_LOCKFILE="/tmp/dhparam_generating.lock"
-
-# The hash of the pregenerated dhparam file is used to check if the pregen dhparam is already in use
-PREGEN_HASH=$(md5sum $PREGEN_DHPARAM_FILE | cut -d" " -f1)
-if [[ -f $DHPARAM_FILE ]]; then
-    CURRENT_HASH=$(md5sum $DHPARAM_FILE | cut -d" " -f1)
-    if [[ $PREGEN_HASH != "$CURRENT_HASH" ]]; then
-        # There is already a dhparam, and it's not the default
-        echo "Custom dhparam.pem file found, generation skipped"
-        exit 0
-    fi
-
-    if [[ -f $GEN_LOCKFILE ]]; then
-        # Generation is already in progress
-        exit 0
-    fi
-fi
-
-if [[ $DHPARAM_GENERATION =~ ^[Ff][Aa][Ll][Ss][Ee]$ ]]; then
-    echo "Skipping Diffie-Hellman parameters generation and Ignoring pre-generated dhparam.pem"
-    exit 0
-fi
-
-cat >&2 <<-EOT
-WARNING: $DHPARAM_FILE was not found. A pre-generated dhparam.pem will be used for now while a new one
-is being generated in the background.  Once the new dhparam.pem is in place, nginx will be reloaded.
-EOT
-
-# Put the default dhparam file in place so we can start immediately
-cp $PREGEN_DHPARAM_FILE $DHPARAM_FILE
-touch $GEN_LOCKFILE
-
-# Generate a new dhparam in the background in a low priority and reload nginx when finished (grep removes the progress indicator).
-(
-    (
-        nice -n +5 openssl dhparam -dsaparam -out $DHPARAM_FILE.tmp "$DHPARAM_BITS" 2>&1 \
-        && mv $DHPARAM_FILE.tmp $DHPARAM_FILE \
-        && echo "dhparam generation complete, reloading nginx" \
-        && nginx -s reload
-    ) | grep -vE '^[\.+]+'
-    rm $GEN_LOCKFILE
-) & disown