A Docker container that bundles Shadowsocks server and Slipstream server into a single DNS tunnel solution. Features an interactive setup wizard that guides you through configuration and outputs a ready-to-use ss:// URL for the Android Shadowsocks app with the slipstream plugin.
# Clone with submodules
git clone --recurse-submodules https://github.com/dalisyron/slipstream-docker
cd slipstream-docker
# Build the container (BuildKit required for cache mounts)
DOCKER_BUILDKIT=1 docker build -t slipstream-ss .
# Run interactively (wizard guides you through setup)
docker run -it -p 53:53/udp -v slipstream-data:/data slipstream-ssThe interactive wizard will prompt you for:
- Your DNS tunnel domain
- Connection mode (recursive or authoritative)
- Shadowsocks password (auto-generate or custom)
After setup, copy the displayed ss:// URL to your Android Shadowsocks app.
Client (Android SS app + slipstream plugin)
|
v (DNS queries over UDP port 53)
Docker Container:
slipstream-server (port 53/udp)
|
v (decapsulated TCP)
ssserver (127.0.0.1:7749)
|
v
Internet
Run with -it flag for the interactive setup wizard:
docker run -it -p 53:53/udp -v slipstream-data:/data slipstream-ssSet environment variables to skip prompts (useful for automation):
docker run -d --name slipstream-ss \
-p 53:53/udp \
-v slipstream-data:/data \
-e DOMAIN=tunnel.example.com \
-e MODE=recursive \
-e RESOLVER=8.8.8.8 \
-e NON_INTERACTIVE=true \
slipstream-ss| Variable | Required | Default | Description |
|---|---|---|---|
DOMAIN |
Yes* | - | DNS tunnel domain |
MODE |
No | recursive |
recursive or authoritative |
RESOLVER |
No | 8.8.8.8 |
DNS resolver for recursive mode |
SERVER_IP |
If auth | - | Server IP for authoritative mode |
SS_PASSWORD |
No | (auto-generated) | Shadowsocks password |
SS_METHOD |
No | chacha20-ietf-poly1305 |
Encryption method |
CERT_PATH |
No | /data/config/cert.pem |
TLS cert path for slipstream-server (auto-generated if missing) |
KEY_PATH |
No | /data/config/key.pem |
TLS key path for slipstream-server (auto-generated if missing) |
RESET_SEED_PATH |
No | /data/config/reset-seed |
Persisted stateless reset seed (auto-generated if missing) |
EXPECTED_PUBLIC_IP |
No | - | Used for DNS preflight (recursive mode) to warn if domain resolves elsewhere |
SKIP_DNS_CHECK |
No | false |
Skip DNS preflight in recursive mode |
FORCE_RECONFIGURE |
No | false |
Ignore existing /data/config/settings.env and re-run setup |
NON_INTERACTIVE |
No | false |
Set true to skip all prompts |
SETUP_ONLY |
No | false |
Exit after saving config (used by install.sh for setup-then-detach flow) |
*Required in non-interactive mode; prompted in interactive mode
Clients query a public DNS resolver (e.g., 8.8.8.8) which resolves your domain. This mode:
- Works behind most firewalls
- More stealthy
- Requires your domain's DNS records to point to the server
Tip: set
EXPECTED_PUBLIC_IPto your server IP to get a DNS preflight warning if the domain doesn't resolve correctly (or setSKIP_DNS_CHECK=trueto disable).
Clients connect directly to your server's IP address. This mode:
- Higher performance with pacing-based polling
- Uses BBR congestion control
- Best when you control both endpoints
- Requires clients can reach port 53 directly
# Build (BuildKit required for cache mounts)
DOCKER_BUILDKIT=1 docker build -t slipstream-ss .
# Run interactively
docker run -it --name slipstream-ss \
-p 53:53/udp \
-v slipstream-data:/data \
slipstream-ss# Container remembers config from first run
docker start -ai slipstream-ss
# Or retrieve saved config
docker exec slipstream-ss cat /data/config/client-config.txt# Interactive mode (wizard)
docker compose --profile interactive up
# Non-interactive mode (uses .env)
cp .env.example .env
$EDITOR .env
docker compose --profile non-interactive up -dYou can override the host UDP port with HOST_DNS_PORT in .env (for example, 5353).
If docker compose is unavailable, install the Compose plugin or run the container directly (docker run ...).
make build
make run # interactive wizard
make run-noninteractive
make logs
make ssurldocker run -d --name slipstream-ss \
-p 53:53/udp \
-v slipstream-data:/data \
-e DOMAIN=tunnel.example.com \
-e MODE=recursive \
-e RESOLVER=8.8.8.8 \
-e NON_INTERACTIVE=true \
slipstream-ss
# Get config from logs
docker logs slipstream-ssAfter setup, the client configuration (including the ss:// URL) is saved to /data/config/client-config.txt:
# View saved configuration
docker exec slipstream-ss cat /data/config/client-config.txt
# Or from logs
docker logs slipstream-ss | grep -A5 "ss://"- Install the Shadowsocks app from Play Store
- Install the slipstream plugin APK (from the
cert-sha256-pluginbranch build) - In the Shadowsocks app:
- Tap + to add a new profile
- Choose Scan QR Code or paste the
ss://URL
- Select slipstream as the plugin
- Connect and verify traffic flows through the tunnel
Make sure to run with -it flags for interactive mode:
docker run -it -p 53:53/udp slipstream-ssStop any existing DNS services:
# On Linux with systemd-resolved
sudo systemctl stop systemd-resolved
# Or use a different host port
docker run -it -p 5353:53/udp slipstream-ss- Verify the container is running:
docker ps - Check firewall allows UDP port 53
- Verify DNS records point to your server (recursive mode)
- Ensure the domain in client config matches your setup
docker logs slipstream-ssRemove the data volume to start fresh:
docker volume rm slipstream-dataThe Dockerfile uses a multi-stage build:
- Stage 1: Builds slipstream-server from the local submodule
- Stage 2: Downloads the shadowsocks-rust v1.21.2 release binary for your architecture
- Stage 3: Creates a minimal runtime image
Builds use BuildKit cache mounts; if you see an error about --mount, enable BuildKit (DOCKER_BUILDKIT=1).
# Ensure submodules are initialized
git submodule update --init --recursive
# Build (BuildKit required for cache mounts)
DOCKER_BUILDKIT=1 docker build -t slipstream-ss .
# Optional: override toolchain or shadowsocks version
DOCKER_BUILDKIT=1 docker build -t slipstream-ss \
--build-arg RUST_IMAGE=rust:1.93-bookworm \
--build-arg SHADOWSOCKS_VERSION=1.21.2 .This project bundles:
- slipstream-rust - DNS tunnel implementation
- shadowsocks-rust - Shadowsocks implementation
See individual projects for their respective licenses.