From aaf7fa03083efa3febf9b85a5528cd196d687c95 Mon Sep 17 00:00:00 2001 From: Ricardo Pardini Date: Fri, 30 Oct 2020 00:20:18 +0100 Subject: [PATCH] introduce env DEBUG_HUB; to help understand #54 - injects a mitmproxy between the caching layer and DockerHub's registry-1.docker.io - it also disables VERIFY_SSL so the mitmproxy can be used; - DEBUG_HUB's mitmweb is exposed on port 8082 - both DEBUG and DEBUG_HUB can be enabled independently --- Dockerfile | 6 +++++- entrypoint.sh | 58 ++++++++++++++++++++++++++++++++++++++------------- nginx.conf | 1 + 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index efbcae1..5de0e23 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,8 +48,10 @@ RUN chmod +x /create_ca_cert.sh /entrypoint.sh # Clients should only use 3128, not anything else. EXPOSE 3128 -# In debug mode, 8081 exposes the mitmweb interface. +# In debug mode, 8081 exposes the mitmweb interface (for incoming requests from Docker clients) EXPOSE 8081 +# In debug-hub mode, 8082 exposes the mitmweb interface (for outgoing requests to DockerHub) +EXPOSE 8082 ## Default envs. # A space delimited list of registries we should proxy and cache; this is in addition to the central DockerHub. @@ -60,6 +62,8 @@ ENV AUTH_REGISTRIES="some.authenticated.registry:oneuser:onepassword another.reg ENV VERIFY_SSL="true" # Enable debugging mode; this inserts mitmproxy/mitmweb between the CONNECT proxy and the caching layer ENV DEBUG="false" +# Enable debugging mode; this inserts mitmproxy/mitmweb between the caching layer and DockerHub's registry +ENV DEBUG_HUB="false" # Enable nginx debugging mode; this uses nginx-debug binary and enabled debug logging, which is VERY verbose so separate setting ENV DEBUG_NGINX="false" diff --git a/entrypoint.sh b/entrypoint.sh index 1614ae8..585ee06 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -31,6 +31,10 @@ done export ALLDOMAINS=${ALLDOMAINS:1} # remove the first comma and export /create_ca_cert.sh # This uses ALLDOMAINS to generate the certificates. +# Target host interception. Empty by default. Used to intercept outgoing requests +# from the proxy to the registries. +echo -n "" > /etc/nginx/docker.targetHost.map + # Now handle the auth part. echo -n "" > /etc/nginx/docker.auth.map @@ -63,19 +67,6 @@ if [ "$AUTH_REGISTRIES" ]; then done fi -echo "" > /etc/nginx/docker.verify.ssl.conf -if [[ "a${VERIFY_SSL}" == "atrue" ]]; then - cat << EOD > /etc/nginx/docker.verify.ssl.conf - # We actually wanna be secure and avoid mitm attacks. - # Fitting, since this whole thing is a mitm... - # We'll accept any cert signed by a CA trusted by Mozilla (ca-certificates-bundle in alpine) - proxy_ssl_verify on; - proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; - proxy_ssl_verify_depth 2; -EOD - echo "Upstream SSL certificate verification enabled." -fi - # create default config for the caching layer to listen on 443. echo " listen 443 ssl default_server;" > /etc/nginx/caching.layer.listen echo "error_log /var/log/nginx/error.log warn;" > /etc/nginx/error.log.debug.warn @@ -99,7 +90,7 @@ if [[ "a${DEBUG}" == "atrue" ]]; then # in debug mode, change caching layer to listen on 444, so that mitmproxy can sit in the middle. echo " listen 444 ssl default_server;" > /etc/nginx/caching.layer.listen - echo "Starting in DEBUG MODE (mitmproxy)." + echo "Starting in DEBUG MODE (mitmproxy)." >&2 echo "Run mitmproxy with reverse pointing to the same certs..." mitmweb --no-web-open-browser --web-iface 0.0.0.0 --web-port 8081 \ --set keep_host_header=true --set ssl_insecure=true \ @@ -108,6 +99,28 @@ if [[ "a${DEBUG}" == "atrue" ]]; then echo "Access mitmweb via http://127.0.0.1:8081/ " fi +if [[ "a${DEBUG_HUB}" == "atrue" ]]; then + if [[ ! -f /usr/bin/mitmweb ]]; then + echo "To debug, you need the -debug version of this image, eg: :latest-debug" + exit 3 + fi + + # in debug hub mode, we remap targetHost to point to mitmproxy below + echo "\"registry-1.docker.io\" \"127.0.0.1:445\";" > /etc/nginx/docker.targetHost.map + + echo "Debugging outgoing DockerHub connections via mitmproxy on 8082." >&2 + # this one has keep_host_header=false so we don't need to modify nginx config + mitmweb --no-web-open-browser --web-iface 0.0.0.0 --web-port 8082 \ + --set keep_host_header=false --set ssl_insecure=true \ + --mode reverse:https://registry-1.docker.io --listen-host 0.0.0.0 \ + --listen-port 445 --certs /certs/fullchain_with_key.pem &> /dev/null & + + echo "Warning, DockerHub outgoing debugging disables upstream SSL verification for all upstreams." >&2 + VERIFY_SSL=false + + echo "Access mitmweb for outgoing DockerHub requests via http://127.0.0.1:8082/ " +fi + if [[ "a${DEBUG_NGINX}" == "atrue" ]]; then if [[ ! -f /usr/sbin/nginx-debug ]]; then echo "To debug, you need the -debug version of this image, eg: :latest-debug" @@ -120,6 +133,23 @@ if [[ "a${DEBUG_NGINX}" == "atrue" ]]; then NGINX_BIN="/usr/sbin/nginx-debug" fi +# Upstream SSL verification. +echo "" > /etc/nginx/docker.verify.ssl.conf +if [[ "a${VERIFY_SSL}" == "atrue" ]]; then + cat << EOD > /etc/nginx/docker.verify.ssl.conf + # We actually wanna be secure and avoid mitm attacks. + # Fitting, since this whole thing is a mitm... + # We'll accept any cert signed by a CA trusted by Mozilla (ca-certificates-bundle in alpine) + proxy_ssl_verify on; + proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; + proxy_ssl_verify_depth 2; +EOD + echo "Upstream SSL certificate verification enabled." +else + echo "Upstream SSL certificate verification is DISABLED." +fi + + echo "Testing nginx config..." ${NGINX_BIN} -t diff --git a/nginx.conf b/nginx.conf index 36132db..0183ca5 100644 --- a/nginx.conf +++ b/nginx.conf @@ -81,6 +81,7 @@ http { # Just in case you want to rewrite some hosts. Default maps directly. map $host $targetHost { hostnames; + include /etc/nginx/docker.targetHost.map; default $host; }