diff --git a/tests/transparent-setup/3proxy-Dockerfile-full b/tests/transparent-setup/3proxy-Dockerfile-full index 73f5776..b240875 100644 --- a/tests/transparent-setup/3proxy-Dockerfile-full +++ b/tests/transparent-setup/3proxy-Dockerfile-full @@ -1,24 +1,4 @@ -# 3proxy.full is fully functional 3proxy build based on busibox:glibc -# -#to build: -# docker build -f Dockerfile.full -t 3proxy.full . -#to run: -# by default 3proxy uses safe chroot environment with chroot to /usr/local/3proxy with uid/gid 65535/65535 and expects -# configuration file to be placed in /usr/local/etc/3proxy. -# Paths in configuration file must be relative to /usr/local/3proxy, that is use /logs instead of -# /usr/local/3proxy/logs. nserver in chroot is required for DNS resolution. An example: -# -# echo nserver 8.8.8.8 >/path/to/local/config/directory/3proxy.cfg -# echo proxy -p3129 >>/path/to/local/config/directory/3proxy.cfg -# docker run -p 3129:3129 -v /path/to/local/config/directory:/usr/local/3proxy/conf -name 3proxy.full 3proxy.full -# -# /path/to/local/config/directory in this example must conrain 3proxy.cfg -# if you need 3proxy to be executed without chroot with root permissions, replace /etc/3proxy/3proxy.cfg by e.g. mounting config -# dir to /etc/3proxy ot by providing config file /etc/3proxy/3proxy.cfg -# docker run -p 3129:3129 -v /path/to/local/config/directory:/etc/3proxy -name 3proxy.full 3proxy.full -# -# use "log" without pathname in config to log to stdout. -# plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config). +# modified version of dockerfile from github.com/3proxy/3proxy that works with ubuntu 20.04 docker hosts and installs iptables and ipset # switched to ubuntu:20.04 to not have problems with apt install on docker hosts with ubuntu 20.04 FROM ubuntu:20.04 AS buildenv diff --git a/tests/transparent-setup/add-cert-pre-entrypoint.sh b/tests/transparent-setup/add-cert-pre-entrypoint.sh new file mode 100644 index 0000000..7896838 --- /dev/null +++ b/tests/transparent-setup/add-cert-pre-entrypoint.sh @@ -0,0 +1,166 @@ +#!/bin/sh +set -e + +# Path to the custom root certificate (assumed to be mounted into the container) +CUSTOM_CERT_PATH="/certs/custom_root.crt" + +# Function to check if a command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Install certificate utilities if not present +install_cert_utilities() { + echo "Checking for certificate utilities and package manager..." + + if command_exists apk; then + PM="apk" + INSTALL_CMD="apk add --no-cache" + CERT_PACKAGE="ca-certificates ca-certificates-bundle openssl" + + echo "Using apk package manager." + # Install ca-certificates package if not already installed + $INSTALL_CMD $CERT_PACKAGE + + elif command_exists apt-get; then + PM="apt-get" + CERT_PACKAGE="ca-certificates openssl" + + echo "Using apt-get package manager." + # Update package lists + apt-get update + # Install ca-certificates + apt-get install -y $CERT_PACKAGE + + elif command_exists yum; then + PM="yum" + INSTALL_CMD="yum install -y" + CERT_PACKAGE="ca-certificates openssl" + + echo "Using yum package manager." + # Install ca-certificates + $INSTALL_CMD $CERT_PACKAGE + + elif command_exists dnf; then + PM="dnf" + INSTALL_CMD="dnf install -y" + CERT_PACKAGE="ca-certificates openssl" + + echo "Using dnf package manager." + $INSTALL_CMD $CERT_PACKAGE + + elif command_exists zypper; then + PM="zypper" + INSTALL_CMD="zypper install -y" + CERT_PACKAGE="ca-certificates openssl" + + echo "Using zypper package manager." + $INSTALL_CMD $CERT_PACKAGE + + else + echo "No supported package manager found. Cannot install certificate utilities." + exit 1 + fi +} + +# Install certificate utilities if not already installed +if ! command_exists update-ca-certificates && ! command_exists update-ca-trust; then + install_cert_utilities +else + echo "Certificate utilities already installed." +fi + +# Copy the custom certificate into the appropriate directory and update trust store +update_trust_store() { + echo "Updating trust store with custom certificate..." + + if [ -f /etc/alpine-release ]; then + # Alpine Linux + echo "Detected Alpine Linux." + cp "$CUSTOM_CERT_PATH" /usr/local/share/ca-certificates/custom_root.crt + update-ca-certificates + + elif [ -f /etc/debian_version ]; then + # Debian/Ubuntu + echo "Detected Debian/Ubuntu." + cp "$CUSTOM_CERT_PATH" /usr/local/share/ca-certificates/custom_root.crt + update-ca-certificates + + elif [ -f /etc/redhat-release ] || [ -f /etc/centos-release ]; then + # RedHat/CentOS/Fedora + echo "Detected RedHat/CentOS/Fedora." + cp "$CUSTOM_CERT_PATH" /etc/pki/ca-trust/source/anchors/custom_root.crt + update-ca-trust extract + + elif [ -f /etc/os-release ]; then + OS_ID=$(grep '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') + case "$OS_ID" in + sles|opensuse*) + echo "Detected SUSE Linux." + cp "$CUSTOM_CERT_PATH" /etc/pki/trust/anchors/custom_root.crt + update-ca-certificates + ;; + *) + echo "Unsupported OS detected." + exit 1 + ;; + esac + else + echo "Cannot detect OS type. Exiting." + exit 1 + fi +} + +# Update the trust store +update_trust_store + +# Check for common runtimes and configure them if needed + +configure_java() { + if command_exists java; then + echo "Java runtime detected. Importing custom certificate into Java truststore." + + JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))) + JAVA_CACERTS_PATH="$JAVA_HOME/lib/security/cacerts" + if [ ! -f "$JAVA_CACERTS_PATH" ]; then + echo "Java cacerts file not found at $JAVA_CACERTS_PATH. Skipping Java truststore update." + return + fi + + echo "Importing custom certificate into Java cacerts at $JAVA_CACERTS_PATH." + yes | keytool -importcert -trustcacerts -alias custom_root -file "$CUSTOM_CERT_PATH" -keystore "$JAVA_CACERTS_PATH" -storepass changeit || true + fi +} + +configure_nodejs() { + if command_exists node; then + echo "Node.js runtime detected. Setting NODE_EXTRA_CA_CERTS environment variable." + export NODE_EXTRA_CA_CERTS="$CUSTOM_CERT_PATH" + fi +} + +configure_python() { + if command_exists python || command_exists python3; then + echo "Python runtime detected. Setting SSL_CERT_FILE and REQUESTS_CA_BUNDLE environment variables." + export SSL_CERT_FILE="$CUSTOM_CERT_PATH" + export REQUESTS_CA_BUNDLE="$CUSTOM_CERT_PATH" + fi +} + +# Configure runtimes +configure_java +configure_nodejs +configure_python + +# Ensure all environment variables are exported +export NODE_EXTRA_CA_CERTS +export SSL_CERT_FILE +export REQUESTS_CA_BUNDLE + +# Log environment variables for debugging (optional) +echo "Environment variables set:" +#env | grep -E 'NODE_EXTRA_CA_CERTS|SSL_CERT_FILE|REQUESTS_CA_BUNDLE' + +# Execute the original command +echo "Executing original command: $@" +exec "$@" diff --git a/tests/transparent-setup/docker-compose.yml b/tests/transparent-setup/docker-compose.yml index ec4c404..c690053 100644 --- a/tests/transparent-setup/docker-compose.yml +++ b/tests/transparent-setup/docker-compose.yml @@ -1,4 +1,4 @@ -version: '2.4' #starting from version 3.4, docker-compose supports healthcheck startperiod but only 2.x supports condition: service_healthy +version: '2.4' # only 2.x supports condition: service_health #starting from version 3.4, docker-compose supports healthcheck startperiod services: # Example/demo service for which http (port 80) and https (port 443) traffic will be routed transparently through the proxy @@ -8,7 +8,12 @@ services: transparent-proxy: condition: service_healthy # Ensures transparent-proxy is started and transparent setup via time-machine is working - RECOMMENDED network_mode: "service:transparent-proxy" # Uses the same network (namespace) of the transparent proxy container to route traffic through it - REQUIRED - entrypoint: ["sh", "-c", " + # template to try to automatically add time-machine CA root certificate to the app container for well-known base images with package managers + volumes: + - ../../ca-cert.pem:/certs/custom_root.crt:ro + - ./add-cert-pre-entrypoint.sh:/usr/local/bin/entrypoint.sh:ro + entrypoint: ["/bin/sh", "/usr/local/bin/entrypoint.sh"] + command: ["sh", "-c", "echo 'Running main application command...' && \ apt-get update && \ apt-get install -y curl raptor2-utils openssl socat && \ curl -I http://example.org && \ @@ -44,14 +49,17 @@ services: - my_network healthcheck: # test: ["CMD", "sh", "-c", "sleep 3 && curl -If http://1.1.1.1 && curl -Ikf https://1.1.1.1 && sleep 30"] # && curl -x localhost:8011 -If http://1.1.1.1 - # test: ["CMD", "sh", "-c", "sleep 5 && curl -If http://1.1.1.1 && curl -Ikf https://1.1.1.1 && ( [ -f /tmp/healthcheck_flag ] && sleep 60 || touch /tmp/healthcheck_flag )"] - test: ["CMD", "sh", "-c", "sleep 5 && curl -If http://1.1.1.1 && curl -Ikf https://1.1.1.1 && ( [ -f /dev/shm/healthcheck_flag ] && sleep 60 || touch /dev/shm/healthcheck_flag )"] + test: ["CMD", "sh", "-c", "sleep 5 && curl -If http://1.1.1.1 && curl -Ikf https://1.1.1.1 && curl -x localhost:8011 -If http://1.1.1.1 && ( [ -f /dev/shm/healthcheck_flag ] && sleep 60 || touch /dev/shm/healthcheck_flag )"] interval: 1s # in compose 2.4 the first health check waits for the interval time -> make that short and add long sleep to the test command at the end that is only executed after the first health check timeout: 80s # retries: 3 # start_period: 5s # Only available in docker-compose version 3.4 and above -> add sleep in front to test cmd instead entrypoint: ["sh", "-c", " set -x && \ + echo starting 3proxy instance for HTTP_to_HTTP-proxied && \ + (/usr/bin/3proxy /etc/3proxy/3proxy-HTTP.cfg &) && \ + echo starting 3proxy instance for TLS_to_HTTP-CONNECT-tunnelled && \ + (/usr/bin/3proxy /etc/3proxy/3proxy-TLS.cfg &) && \ echo applying iptable transparent redirection rules && \ `# Create an ipset named 'private_ips' for private IP ranges` \ ipset create private_ips hash:net && \ @@ -64,10 +72,6 @@ services: `# Redirect HTTPS traffic (port 443) to port 8012, but exclude private IP ranges using ipset` \ iptables -t nat -A OUTPUT -p tcp --dport 443 -m set ! --match-set private_ips dst -j REDIRECT --to-port 8012 && \ iptables -t nat -L -v -n && \ - echo starting 3proxy instance for HTTP_to_HTTP-proxied && \ - (/usr/bin/3proxy /etc/3proxy/3proxy-HTTP.cfg &) && \ - echo starting 3proxy instance for TLS_to_HTTP-CONNECT-tunnelled && \ - (/usr/bin/3proxy /etc/3proxy/3proxy-TLS.cfg &) && \ sleep inf"] networks: