diff --git a/serverless-fleets/README.md b/serverless-fleets/README.md index 7562c023..5c24794f 100644 --- a/serverless-fleets/README.md +++ b/serverless-fleets/README.md @@ -529,6 +529,10 @@ Download the results from the output COS bucket to `./data/output` In order to control/monitor/capture HTTP egress traffic on your tasks for which security group based network controls are not sufficient i.e. hostname based controls: you can use after startup hooks to deploy a HTTP proxy on each worker node that intercepts all HTTP traffic of the tasks running on that worker node. An example using squid proxy to allowlist only traffic to a single domain can be found in `run_hook_squid_http_proxy`. +### HTTPS egress control + +If you simply want to access control HTTPS egress traffic on your tasks for which security group based network controls are not sufficient i.e. hostname based controls: you can use after startup hooks in conjunction with a gateway/HTTPS proxy on each worker node that is able to drop HTTPS traffic of the tasks running on that worker node based on SNI header sniffing. The proxy may close connections for non-allowlisted traffic and passthrough everything else. +An example using mitm proxy to allowlist only traffic to a single domain can be found in `run_hook_mitm_https_proxy`. ## HowTo diff --git a/serverless-fleets/run_hook_mitm_https_proxy b/serverless-fleets/run_hook_mitm_https_proxy new file mode 100644 index 00000000..6b70dad0 --- /dev/null +++ b/serverless-fleets/run_hook_mitm_https_proxy @@ -0,0 +1,90 @@ +uuid=$(uuidgen | tr '[:upper:]' '[:lower:]' | awk -F- '{print $1}') + +PREHOOK=$(cat <<'OUTER' +#!/usr/bin/env bash +set -Eeuo pipefail + +### ===== User-tunable variables ===== + +export NETWORK_NAME="podman" +export SUBNET_CIDR="10.88.0.0/16" +export GATEWAY_IP="10.88.0.1" + +export MITM_IMAGE="docker.io/mitmproxy/mitmproxy:latest" +export MITM_PORT="8080" +export MITM_CONTAINER="https-proxy" + +export WORKDIR="$PWD/podman-transparent-proxy-lab" + +### ===== Derived variables ===== + +MITM_DIR="$WORKDIR/mitmproxy" +CERTS_DIR="$WORKDIR/certs" + +mkdir -p "$MITM_DIR" "$CERTS_DIR" + +echo "==> Checking dependencies" +command -v podman >/dev/null +command -v sudo >/dev/null +command -v iptables >/dev/null + +cat > "${MITM_DIR}/sni_allowlist.py" < Creating Podman network if needed" +if ! podman network exists "${NETWORK_NAME}"; then + podman network create \ + --subnet "${SUBNET_CIDR}" \ + --gateway "${GATEWAY_IP}" \ + "${NETWORK_NAME}" +fi + +echo "==> Removing old containers if present" +podman rm -f "${MITM_CONTAINER}" 2>/dev/null || true + +echo "==> Starting mitmproxy HTTPS transparent proxy" +podman run -d \ + --name "${MITM_CONTAINER}" \ + --network host \ + -v "${MITM_DIR}:/home/mitmproxy/.mitmproxy:Z" \ + "${MITM_IMAGE}" \ + mitmdump -s /home/mitmproxy/.mitmproxy/sni_allowlist.py --mode transparent --showhost --listen-host 0.0.0.0 --listen-port "${MITM_PORT}" --ignore-hosts 'example.com' + +echo "==> Enabling IPv4 forwarding on host" +sudo sysctl -w net.ipv4.ip_forward=1 >/dev/null + +echo "==> Preparing iptables chain" +sudo iptables -t nat -N MITM_PROXY 2>/dev/null || true +sudo iptables -t nat -F MITM_PROXY + +sudo iptables -t nat -A MITM_PROXY -d 127.0.0.0/8 -j RETURN +sudo iptables -t nat -A MITM_PROXY -d ${SUBNET_CIDR} -j RETURN +sudo iptables -t nat -A MITM_PROXY -p tcp --dport 443 -j REDIRECT --to-ports 8080 + +sudo iptables -t nat -A PREROUTING -s ${SUBNET_CIDR} -p tcp -j MITM_PROXY +OUTER +) + +ibmcloud ce fleet create --name "fleet-${uuid}" \ + --tasks-state-store fleet-task-store \ + --image registry.access.redhat.com/ubi10/ubi-minimal \ + --cpu "2" \ + --memory "4G" \ + --tasks-from-local-file run_hook_mitm_https_proxy_commands.jsonl \ + --max-scale 2 \ + --retrylimit 0 \ + --subnetpool-name fleet-subnetpool \ + --env __CE_INTERNAL_HOOK_AFTER_STARTUP="${PREHOOK}" \ No newline at end of file diff --git a/serverless-fleets/run_hook_mitm_https_proxy_commands.jsonl b/serverless-fleets/run_hook_mitm_https_proxy_commands.jsonl new file mode 100644 index 00000000..998a2ccc --- /dev/null +++ b/serverless-fleets/run_hook_mitm_https_proxy_commands.jsonl @@ -0,0 +1,2 @@ +{ "cmds": ["curl", "--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "https://example.com"]} +{ "cmds": ["/bin/bash", "-c", "curl --silent --write-out \"%{url} %{http_code}\" --output /dev/null https://google.com || true"]} \ No newline at end of file diff --git a/serverless-fleets/run_hook_squid_http_proxy_commands.jsonl b/serverless-fleets/run_hook_squid_http_proxy_commands.jsonl index a54e7897..18bf28df 100644 --- a/serverless-fleets/run_hook_squid_http_proxy_commands.jsonl +++ b/serverless-fleets/run_hook_squid_http_proxy_commands.jsonl @@ -1,2 +1,2 @@ -{ "command":"curl", "args": ["--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://example.com"]} -{ "command":"curl", "args": ["--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://google.com"]} +{ "cmds": ["curl", "--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://example.com"]} +{ "cmds": ["curl", "--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://google.com"]}