diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a7aa22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +mdm.xml +docker-compose.local.yml diff --git a/Dockerfile b/Dockerfile index 7333a04..1818742 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,7 @@ ARG DEBIAN_RELEASE=bullseye -ARG LICENSE='' FROM docker.io/debian:$DEBIAN_RELEASE-slim ARG DEBIAN_RELEASE -COPY entrypoint.sh / ENV DEBIAN_FRONTEND=noninteractive -ENV LICENSE=${LICENSE} RUN true && \ apt update && \ @@ -16,6 +13,8 @@ RUN curl https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor --out apt update && \ apt install cloudflare-warp -y --no-install-recommends +COPY entrypoint.sh / + RUN apt remove -y curl && \ apt clean -y && \ rm -rf /var/lib/apt/lists/* && \ diff --git a/README.md b/README.md index 641caf4..c411c07 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,9 @@ docker run -d -p 40000:40000 --restart unless-stopped seiry/cloudflare-warp-prox docker run -d -p 40000:40000 --restart unless-stopped ghcr.io/seiry/cloudflare-warp-proxy ``` -SOCKS5 proxy server will be listening at port 40000. +A **SOCKS5** proxy will be listening at port 40000 (this is WARP's proxy mode, +exposed via `socat`). The same port also accepts HTTP `CONNECT`, so you can point +either a `socks5h://` / `socks5://` or an `http://` client at it — see [test](#test). ### docker-compose @@ -31,7 +33,10 @@ services: restart: unless-stopped environment: # use your own wrap+ key or zero trust key. - - LICENSE='' + - LICENSE= + # to enroll into a Zero Trust org, mount a full MDM config — see "managed deployment" below + # volumes: + # - ./mdm.xml:/var/lib/cloudflare-warp/mdm.xml:ro logging: driver: json-file options: @@ -39,18 +44,95 @@ services: ``` +## managed deployment (Zero Trust) + +To join a Cloudflare Zero Trust organization — e.g. to route through a China local-network +partner or third-party network partner — mount a full [MDM config](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/deployment/mdm-deployment/parameters/) +at `/var/lib/cloudflare-warp/mdm.xml`. `warp-svc` reads it on startup and enrolls the device +using a **service token**. The same file pins the partner's endpoint overrides +(`override_warp_endpoint`, etc.) and puts the client into proxy mode. + + +### 1. create a service token with enrollment permission + +- **Access controls → Service credentials → Service Tokens → Create Service Token** — copy the + Client ID (ends in `.access`) and Client Secret (shown only once). +- **Team & Resources → Devices → Management → Device enrollment permissions → Manage → Policies + → Create policy**, set **Action = `Service Auth`** (not `Allow` — `Allow` does not work for + service tokens), Selector = your token, then add the policy to the enrollment permissions and + **Save**. + + doc: https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/deployment/device-enrollment/#check-for-service-token + +### 2. write `mdm.xml` + +```xml + + + override_api_endpoint + 1.1.1.1 + override_doh_endpoint + 1.1.1.1 + override_warp_endpoint + 1.1.1.1:443 + + + organization + your-team-name + auth_client_id + xxxxxxxx.access + auth_client_secret + xxxxxxxxxxxxxxxx + + + warp_tunnel_protocol + masque + + + service_mode + proxy + proxy_port + 40001 + onboarding + + +``` + +`service_mode`/`proxy_port` put the client into proxy mode locally. The Cloudflare One +Client gives precedence to local settings, so this overrides the org's device profile — +keep `proxy_port` at `40001` to match the `socat` forward (`40000 → 40001`) in the container. + +### 3. run with the file mounted + +``` +docker run -d -p 40000:40000 --restart unless-stopped \ + -v ./mdm.xml:/var/lib/cloudflare-warp/mdm.xml:ro \ + seiry/cloudflare-warp-proxy +``` + +A service-token enrolled device shows up under **My Team → Devices** with email +`non_identity@.cloudflareaccess.com`. + +### 4. (optional) set proxy mode in the dashboard instead + +Instead of `service_mode`/`proxy_port` in `mdm.xml` above, you can manage the mode centrally: +in **Settings → WARP Client → Device settings**, use a profile that targets this device (match +e.g. its `non_identity@…` email so you don't change other users) and set **Service mode = Proxy +mode, port `40001`**. + + ## test ```bash -curl https://www.cloudflare.com/cdn-cgi/trace/ -x socks5h://127.1:40000 # remote dns mode +curl https://www.cloudflare.com/cdn-cgi/trace -x socks5h://127.1:40000 # remote dns mode # or -curl https://www.cloudflare.com/cdn-cgi/trace/ -x socks5://127.1:40000 # local dns mode +curl https://www.cloudflare.com/cdn-cgi/trace -x socks5://127.1:40000 # local dns mode # or -curl https://www.cloudflare.com/cdn-cgi/trace/ -x http://127.1:40000 # http mode +curl https://www.cloudflare.com/cdn-cgi/trace -x http://127.1:40000 # http mode ``` @@ -68,3 +150,6 @@ gateway=off * new version of cloudflare warp (rust version), now only allow using `MASQUE` protocol in proxy mode. With this error message if you try to use `WireGuard` > `Connection error error=InvalidKey("Proxy mode only supports MASQUE")` + + per Cloudflare's [Set up local proxy mode](https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/cloudflare-one-client/configure/modes/#set-up-local-proxy-mode) docs: + > Ensure the Device tunnel protocol is set to MASQUE. diff --git a/docker-compose.yml b/docker-compose.yml index 08ad485..54988aa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,8 +6,13 @@ services: ports: - 40000:40000 restart: unless-stopped - environment: - - LICENSE='' # use your own key, for example zero trust or warp+ + # environment: + # - LICENSE= # use your own key, for warp+ + + # to enroll into a Zero Trust org, mount a full MDM + # config. see README "managed deployment (Zero Trust)" + # volumes: + # - ./mdm.xml:/var/lib/cloudflare-warp/mdm.xml:ro logging: driver: json-file options: diff --git a/entrypoint.sh b/entrypoint.sh index 0c0383d..589c986 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,15 +1,45 @@ #!/bin/bash +MDM_FILE=/var/lib/cloudflare-warp/mdm.xml + ( -while ! warp-cli --accept-tos registration new; do - sleep 1 - >&2 echo "Awaiting warp-svc become online..." -done -warp-cli --accept-tos mode proxy -warp-cli --accept-tos proxy port 40001 +if grep -q 'organization' "$MDM_FILE" 2>/dev/null; then + # Managed deployment: a mounted mdm.xml enrolls the device into a Zero Trust + # organization (via a service token). warp-svc auto-enrolls on startup, so we just + # wait for the daemon to come online instead of creating our own registration. + >&2 echo "mdm.xml with organization found — using managed (Zero Trust) enrollment" + until warp-cli --accept-tos status >/dev/null 2>&1; do + sleep 1 + >&2 echo "Awaiting warp-svc become online..." + done +else + # Consumer deployment: create a free registration. Newer clients auto-register on + # startup and the registration persists across restarts, so "registration new" can + # fail with "Old registration is still around" — treat that as success instead of + # looping forever (otherwise socat below never starts). + while true; do + if out="$(warp-cli --accept-tos registration new 2>&1)"; then + break + fi + echo "$out" | grep -q "Old registration is still around" && break + sleep 1 + >&2 echo "Awaiting warp-svc become online..." + done +fi + +# Proxy mode. On consumer accounts we set it here. On managed (Team/Zero Trust) accounts +# the mode is dictated by the org device profile and these calls return "Invalid setting +# for this account type" — in that case set the profile's service mode to "Proxy mode" +# (port 40001) in the Zero Trust dashboard, and ignore the errors below. +warp-cli --accept-tos mode proxy 2>/dev/null || >&2 echo "mode set by org profile, skipping local mode/port" +warp-cli --accept-tos proxy port 40001 2>/dev/null || true +# docker-compose's `- LICENSE='...'` keeps the surrounding quotes as part of the value, +# which makes warp-cli reject the key — strip a single pair of leading/trailing quotes. +LICENSE="${LICENSE#[\"\']}" +LICENSE="${LICENSE%[\"\']}" if [ "$LICENSE" != "" ]; then - warp-cli --accept-tos registration license "$LICENSE" + warp-cli --accept-tos registration license "$LICENSE" || true fi warp-cli --accept-tos connect @@ -17,5 +47,3 @@ socat TCP-LISTEN:40000,fork TCP:localhost:40001 # socat is used to redirect tra ) & exec warp-svc - - diff --git a/mdm.example.xml b/mdm.example.xml new file mode 100644 index 0000000..0a70b61 --- /dev/null +++ b/mdm.example.xml @@ -0,0 +1,29 @@ + + + override_api_endpoint + 1.1.1.1 + override_doh_endpoint + 1.1.1.1 + override_warp_endpoint + 1.1.1.1:443 + + + organization + your_organization + auth_client_id + your_client_id.access + auth_client_secret + your_client_secret + + + warp_tunnel_protocol + masque + + + service_mode + proxy + proxy_port + 40001 + onboarding + +