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
+
+