Run Cloudflare WARP in Docker
Cloudflare WARP is a free VPN service provided by Cloudflare. As most service providers consider its exit IP as a reputable residential broadband IP, many people use it for accessing websites that have strict risk control policies, especially when their server’s IP address is not clean. However, when we use it on our own servers, we may encounter the following issues:
- The official WARP client, in the default mode
220.127.116.11 with WARP, blocks all inbound connections, which means that websites and services on servers cannot be accessed.
- Although the official WARP client in
Local Proxymode does not have the problem of blocking inbound connections, the HTTPS/SOCKS5 proxy it provides cannot transmit UDP packets.
- In order to prevent abuse, Cloudflare blocks third-party clients (such as wgcf) from accessing WARP services in some regions, and it is currently unknown whether this measure will be extended to other regions.
This article will run the official WARP client in Docker to solve the above problem.
To run the WARP client in Docker, just write the following content to
docker-compose.yml and run
docker-compose up -d.
Try it out to see if it works:
If the output contains
warp=plus, the container is working properly. If the output contains
warp=off, it means that the container failed to connect to the WARP service.
You can configure the container through the following environment variables:
WARP_SLEEP: The time to wait for the WARP daemon to start, in seconds. The default is 2 seconds. If the time is too short, it may cause the WARP daemon to not start before using the proxy, resulting in the proxy not working properly. If the time is too long, it may cause the container to take too long to start. If your server has poor performance, you can increase this value appropriately.
WARP_LICENSE_KEY: The license key of the WARP client, which is optional. If you have subscribed to WARP+ service, you can fill in the key in this environment variable. If you have not subscribed to WARP+ service, you can ignore this environment variable.
Data persistence: Use the host volume
./data to persist the data of the WARP client. You can change the location of this directory or use other types of volumes. If you modify the
WARP_LICENSE_KEY, please delete the
./data directory so that the client can detect and register again.
The container uses GOST to provide proxy, where the environment variable
GOST_ARGS is used to pass parameters to GOST. The default is
-L :1080, that is, to listen on port 1080 in the container at the same time through HTTP and SOCKS5 protocols. If you want to have UDP support or use advanced features provided by other protocols, you can modify this parameter. For more information, refer to GOST documentation.
If you modify the port number, you may also need to modify the port mapping in the
The health check of the container will verify if the WARP client inside the container is working properly. If the check fails, the container will automatically restart. Specifically, 15 seconds after starting, a check will be performed every 15 seconds. If the inspection fails for 3 consecutive times, the container will be marked as unhealthy and trigger an automatic restart.
If you don't want the container to restart automatically, you can remove
restart: always from the
docker-compose.yml. You can also modify the parameters of the health check through the
This image includes two components, Cloudflare WARP and GOST. The WARP client is used to connect to the WARP service, and GOST is used to provide a proxy. Its inspiration initially came from a post on hostloc (in chinese). This post was the earliest attempt (that I could find) to run WARP in a container, and provided a lot of useful information, but had the following shortcomings:
- Still using the third-party client WGCF, which may result in being banned by Cloudflare.
- Requires interactive operations, which is inconvenient for deployment.
Based on this, I have made a series of modifications and uploaded the code to GitHub.
The process of downloading and installing the official WARP client is well described in the WARP documentation. Here, we focus on how to run it in a containerized environment, which involves three parts:
- Creating a TUN device, which is not available by default in a container.
- Starting the WARP daemon. Normally, the WARP installation process writes the relevant configurations for the daemon into
systemdor a similar tool, which allows it to start automatically at boot time. However, in a container environment, we need to start it manually.
- Granting sufficient permissions.
The first two issues are addressed in
It should be noted that:
- The creation of TUN device cannot be placed in the Dockerfile because
/devis mounted as
tmpfs, which is not in the file system
- We need to wait for the daemon to start before using the
warp-clicommand. Currently, we use a pre-configured wait time. If you have a better method, please feel free to suggest it.
The permission issue can be resolved in the
This gives containers enough, but not excessive, privileges.
I have a strong aversion to containers that require
--privileged=true, because that means the container gains complete root access to the host machine, which is extremely dangerous. Even if we trust the developers, there may still be security vulnerabilities in the services running inside the container, and once an attacker gains access to the container, they can directly obtain full control over the host machine. In most cases, containers do not need such high privileges, and this requirement is often a lazy behavior of developers who do not want to confirm the necessary permissions, but seriously endangers users' security.
GOST is a very powerful proxy software. In this container, I use it to provide proxy services and configure the proxy type through the
GOST_ARGS environment variable.
Docker officially does not recommend running multiple processes in one container, partly because the crash of a subprocess may not be detected. However, in this particular container, I avoided this issue. The container runs the WARP daemon process and GOST proxy. If the GOST proxy crashes, it will cause the main process (
entrypoint.sh) to exit, triggering an automatic restart. If the WARP daemon process crashes, it will cause the health check to fail, also triggering an automatic restart. This achieves detection of subprocess crashes.
- Hostloc forum - inspiration (in chinese)
- StackOverFlow - How to create tun interface inside Docker container image?
- Cloudflare WARP docs
- GOST docs
- Docker docs - Run multiple services in a container
This article does not have comments enabled. Please submit an issue in the Github repository.
Run Cloudflare WARP in Docker