#!/bin/sh # proxyrun: run a command behind a local SOCKS5->HTTP forward proxy. # # The build container cannot reach the internet directly, but can reach a # SOCKS5 endpoint. apt/pip/urllib/urllib3 all natively honour an HTTP forward # proxy (http://host:port) but not a raw socks5:// URL, so this starts the # socks2http bridge on loopback, points the *_proxy vars at it, runs the # command, then stops the bridge. # # usage: # sh proxyrun.sh -- [args...] # sh proxyrun.sh "" -- # upstream empty: run directly (no proxy) set -eu UP="${1:-}"; shift [ "${1:-}" = "--" ] && shift PORT="${PROXYRUN_PORT:-12808}" LOG=/tmp/socks2http.$$.log # No proxy needed: run the command directly. if [ -z "$UP" ]; then "$@" exit $? fi # Start the bridge (output to a file so it does not hold the RUN's stdout pipe). The bridge script sits # beside this one (both at the build-context root, so /src/socks2http.py in the image). BRIDGE="$(dirname "$0")/socks2http.py" python3 "$BRIDGE" --listen "127.0.0.1:$PORT" --upstream "$UP" >"$LOG" 2>&1 & SPID=$! # Wait for it to accept connections (up to ~15 s). i=0 while ! python3 -c "import socket,sys; socket.create_connection(('127.0.0.1',$PORT),1).close()" 2>/dev/null; do i=$((i+1)) if [ "$i" -ge 30 ]; then echo "proxyrun: socks2http did not start; log:" >&2 cat "$LOG" >&2 || true kill "$SPID" 2>/dev/null || true exit 1 fi sleep 0.5 done export http_proxy="http://127.0.0.1:$PORT" export https_proxy="http://127.0.0.1:$PORT" export HTTP_PROXY="$http_proxy" export HTTPS_PROXY="$https_proxy" export no_proxy="127.0.0.1,localhost" export NO_PROXY="127.0.0.1,localhost" rc=0 "$@" || rc=$? kill "$SPID" 2>/dev/null || true wait "$SPID" 2>/dev/null || true rm -f "$LOG" exit "$rc"