add mitmproxy/nginx-debug inspection capabilities

- avoid some caching for non-blob urls
pull/7/head
Ricardo Pardini 2018-11-04 11:23:52 +01:00
parent 1486d6920e
commit 8ff06e3dec
No known key found for this signature in database
GPG Key ID: 3D38CA12A66C5D02
4 changed files with 107 additions and 44 deletions

View File

@ -1,10 +1,18 @@
# We start from my nginx fork which includes the proxy-connect module from tEngine
# Source is available at https://github.com/rpardini/nginx-proxy-connect-stable-alpine
# Its equivalent to nginx:stable-alpine 1.14.0, with alpine 3.7
FROM rpardini/nginx-proxy-connect-stable-alpine:latest
FROM rpardini/nginx-proxy-connect-stable-alpine:nginx-1.14.0-alpine-3.8
# Add openssl, bash and ca-certificates, then clean apk cache -- yeah complain all you want.
RUN apk add --update openssl bash ca-certificates && rm -rf /var/cache/apk/*
# Also added deps for mitmproxy.
RUN apk add --update openssl bash ca-certificates su-exec git g++ libffi libffi-dev libstdc++ openssl openssl-dev python3 python3-dev
RUN LDFLAGS=-L/lib pip3 install mitmproxy
RUN apk del --purge git g++ libffi-dev openssl-dev python3-dev && rm -rf /var/cache/apk/* && rm -rf ~/.cache/pip
# Required for mitmproxy
ENV LANG=en_US.UTF-8
# Check the installed mitmproxy version
RUN mitmproxy --version
# Create the cache directory and CA directory
RUN mkdir -p /docker_mirror_cache /ca
@ -27,6 +35,9 @@ 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.
EXPOSE 8081
## Default envs.
# A space delimited list of registries we should proxy and cache; this is in addition to the central DockerHub.
ENV REGISTRIES="k8s.gcr.io gcr.io quay.io"
@ -34,6 +45,8 @@ ENV REGISTRIES="k8s.gcr.io gcr.io quay.io"
ENV AUTH_REGISTRIES="some.authenticated.registry:oneuser:onepassword another.registry:user:password"
# Should we verify upstream's certificates? Default to true.
ENV VERIFY_SSL="true"
# Enable debugging mode; this inserts mitmproxy/mitmweb between the CONNECT proxy and the caching layer
ENV DEBUG="true"
# Did you want a shell? Sorry. This only does one job; use exec /bin/bash if you wanna inspect stuff
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -116,3 +116,6 @@ openssl x509 -req -days 365 -in web.csr -CA ia.crt -CAkey ia.key -out web.crt -p
logInfo "Concatenating fullchain.pem..."
cat web.crt ia.crt ${CA_CRT_FILE} > fullchain.pem
logInfo "Concatenating fullchain_with_key.pem"
cat fullchain.pem web.key > fullchain_with_key.pem

View File

@ -36,7 +36,7 @@ for ONEREGISTRYIN in ${AUTH_REGISTRIES}; do
done
echo "" > /etc/nginx/docker.verify.ssl.conf
if [ "a$VERIFY_SSL" == "atrue" ]; then
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...
@ -48,9 +48,34 @@ 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
# normally use non-debug version of nginx
NGINX_BIN="nginx"
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 "error_log /var/log/nginx/error.log debug;" > /etc/nginx/error.log.debug.warn
# use debug binary
NGINX_BIN="nginx-debug"
echo "Starting in DEBUG MODE."
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 \
--mode reverse:https://127.0.0.1:444 --listen-host 0.0.0.0 \
--listen-port 443 --certs /certs/fullchain_with_key.pem \
-w /ca/outfile &
echo "Access mitmweb via http://127.0.0.1:8081/ "
fi
echo "Testing nginx config..."
nginx -t
${NGINX_BIN} -t
echo "Starting nginx! Have a nice day."
nginx -g "daemon off;"
${NGINX_BIN} -g "daemon off;"

View File

@ -1,7 +1,9 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
# error log config comes from external file created by entrypoint, to toggle debug on/off.
include /etc/nginx/error.log.debug.warn;
pid /var/run/nginx.pid;
events {
@ -19,7 +21,7 @@ http {
'"HOST: $host" "UPSTREAM: $upstream_addr" '
'"UPSTREAM-STATUS: $upstream_status" '
'"SSL-PROTO: $ssl_protocol" '
'"CONNECT-HOST: $connect_host" "CONNECT-PORT: $connect_port" "CONNECT-ADDR: $connect_addr" '
'"CONNECT-HOST: $connect_host" "CONNECT-PORT: $connect_port" "CONNECT-ADDR: $connect_addr" "INTERCEPTED: $interceptedHost" '
'"PROXY-HOST: $proxy_host" "UPSTREAM-REDIRECT: $upstream_http_location" "CACHE-STATUS: $upstream_cache_status" '
'"AUTH: $http_authorization" ' ;
@ -109,8 +111,9 @@ http {
# The caching layer
server {
# Listen on both 80 and 443, for all hostnames.
# actually could be 443 or 444, depending on debug. this is now generated by the entrypoint.
listen 80 default_server;
listen 443 ssl default_server;
include /etc/nginx/caching.layer.listen;
server_name _;
# Do some tweaked logging.
@ -176,23 +179,35 @@ http {
# don't cache mutable entity /v2/<name>/manifests/<reference> (unless the reference is a digest)
location ~ ^/v2/[^\/]+/manifests/(?![A-Fa-f0-9_+.-]+:) {
proxy_pass https://$targetHost;
add_header X-Docker-Caching-Proxy-Debug-Cache "no:manifests";
}
# don't cache mutable entity /v2/<name>/tags/list
location ~ ^/v2/[^\/]+/tags/list {
proxy_pass https://$targetHost;
proxy_cache off;
add_header X-Docker-Caching-Proxy-Debug-Cache "no:tagslist";
}
# don't cache mutable entity /v2/_catalog
location ~ ^/v2/_catalog$ {
proxy_pass https://$targetHost;
proxy_cache off;
add_header X-Docker-Caching-Proxy-Debug-Cache "no:catalog";
}
# force cache of the first hit which is always /v2/ - even for 401 unauthorized.
# dont cache the first hit which is always /v2/
location = /v2/ {
proxy_pass https://$targetHost;
proxy_cache cache;
proxy_cache_valid 200 301 302 307 401 60d;
proxy_cache off;
add_header X-Docker-Caching-Proxy-Debug-Cache "no:rootv2";
}
# dont cache /token (done against auth servers)
location = /token {
proxy_pass https://$targetHost;
proxy_cache off;
add_header X-Docker-Caching-Proxy-Debug-Cache "no:token";
}
# cache everything else
@ -208,6 +223,8 @@ http {
# We to it twice, one for http and another for https.
proxy_redirect ~^https://([^:/]+)(/.+)$ https://docker.caching.proxy.internal/forcecachesecure/$1/originalwas$2;
proxy_redirect ~^http://([^:/]+)(/.+)$ http://docker.caching.proxy.internal/forcecacheinsecure/$1/originalwas$2;
add_header X-Docker-Caching-Proxy-Debug-Cache "yes:everythingelse";
}
# handling for the redirect case explained above, with https.
@ -218,6 +235,9 @@ http {
# Change the cache key, so that we can cache signed S3 requests and such. Only host and path are considered.
proxy_cache_key $proxy_host$uri;
add_header X-Docker-Caching-Proxy-Debug-Cache "yes:forcecachesecure";
}
# handling for the redirect case explained above, with http.
@ -228,6 +248,8 @@ http {
# Change the cache key, so that we can cache signed S3 requests and such. Only host and path are considered.
proxy_cache_key $proxy_host$uri;
add_header X-Docker-Caching-Proxy-Debug-Cache "yes:forcecacheinsecure";
}
}
}