Skip to content

Commit 7ec4381

Browse files
committed
Add fleet mitm-proxy example
1 parent 9d4dcda commit 7ec4381

4 files changed

Lines changed: 98 additions & 2 deletions

File tree

serverless-fleets/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,10 @@ Download the results from the output COS bucket to `./data/output`
529529
530530
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`.
531531
532+
### HTTPS egress control
533+
534+
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.
535+
An example using mitm proxy to allowlist only traffic to a single domain can be found in `run_hook_mitm_https_proxy`.
532536
533537
## HowTo
534538
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
uuid=$(uuidgen | tr '[:upper:]' '[:lower:]' | awk -F- '{print $1}')
2+
3+
PREHOOK=$(cat <<'OUTER'
4+
#!/usr/bin/env bash
5+
set -Eeuo pipefail
6+
7+
### ===== User-tunable variables =====
8+
9+
export NETWORK_NAME="podman"
10+
export SUBNET_CIDR="10.88.0.0/16"
11+
export GATEWAY_IP="10.88.0.1"
12+
13+
export MITM_IMAGE="docker.io/mitmproxy/mitmproxy:latest"
14+
export MITM_PORT="8080"
15+
export MITM_CONTAINER="https-proxy"
16+
17+
export WORKDIR="$PWD/podman-transparent-proxy-lab"
18+
19+
### ===== Derived variables =====
20+
21+
MITM_DIR="$WORKDIR/mitmproxy"
22+
CERTS_DIR="$WORKDIR/certs"
23+
24+
mkdir -p "$MITM_DIR" "$CERTS_DIR"
25+
26+
echo "==> Checking dependencies"
27+
command -v podman >/dev/null
28+
command -v sudo >/dev/null
29+
command -v iptables >/dev/null
30+
31+
cat > "${MITM_DIR}/sni_allowlist.py" <<INNER
32+
from mitmproxy import connection
33+
from mitmproxy import tls
34+
35+
ALLOWED_HOSTS = ["example.com"]
36+
37+
class SniAllowList:
38+
def tls_clienthello(self, data: tls.ClientHelloData):
39+
sni = data.client_hello.sni
40+
if sni is None or sni not in ALLOWED_HOSTS:
41+
data.context.client.state = connection.ConnectionState.CLOSED
42+
43+
addons = [SniAllowList()]
44+
45+
INNER
46+
47+
echo "==> Creating Podman network if needed"
48+
if ! podman network exists "${NETWORK_NAME}"; then
49+
podman network create \
50+
--subnet "${SUBNET_CIDR}" \
51+
--gateway "${GATEWAY_IP}" \
52+
"${NETWORK_NAME}"
53+
fi
54+
55+
echo "==> Removing old containers if present"
56+
podman rm -f "${MITM_CONTAINER}" 2>/dev/null || true
57+
58+
echo "==> Starting mitmproxy HTTPS transparent proxy"
59+
podman run -d \
60+
--name "${MITM_CONTAINER}" \
61+
--network host \
62+
-v "${MITM_DIR}:/home/mitmproxy/.mitmproxy:Z" \
63+
"${MITM_IMAGE}" \
64+
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'
65+
66+
echo "==> Enabling IPv4 forwarding on host"
67+
sudo sysctl -w net.ipv4.ip_forward=1 >/dev/null
68+
69+
echo "==> Preparing iptables chain"
70+
sudo iptables -t nat -N MITM_PROXY 2>/dev/null || true
71+
sudo iptables -t nat -F MITM_PROXY
72+
73+
sudo iptables -t nat -A MITM_PROXY -d 127.0.0.0/8 -j RETURN
74+
sudo iptables -t nat -A MITM_PROXY -d ${SUBNET_CIDR} -j RETURN
75+
sudo iptables -t nat -A MITM_PROXY -p tcp --dport 443 -j REDIRECT --to-ports 8080
76+
77+
sudo iptables -t nat -A PREROUTING -s ${SUBNET_CIDR} -p tcp -j MITM_PROXY
78+
OUTER
79+
)
80+
81+
ibmcloud ce fleet create --name "fleet-${uuid}" \
82+
--tasks-state-store fleet-task-store \
83+
--image registry.access.redhat.com/ubi10/ubi-minimal \
84+
--cpu "2" \
85+
--memory "4G" \
86+
--tasks-from-local-file run_hook_mitm_https_proxy_commands.jsonl \
87+
--max-scale 2 \
88+
--retrylimit 0 \
89+
--subnetpool-name fleet-subnetpool \
90+
--env __CE_INTERNAL_HOOK_AFTER_STARTUP="${PREHOOK}"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{ "cmds": ["curl", "--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "https://example.com"]}
2+
{ "cmds": ["/bin/bash", "-c", "curl --silent --write-out \"%{url} %{http_code}\" --output /dev/null https://google.com || true"]}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
{ "command":"curl", "args": ["--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://example.com"]}
2-
{ "command":"curl", "args": ["--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://google.com"]}
1+
{ "cmds": ["curl", "--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://example.com"]}
2+
{ "cmds": ["curl", "--silent", "--write-out", "%{url} %{http_code}", "--output", "/dev/null", "http://google.com"]}

0 commit comments

Comments
 (0)