docker pull kavenzero/kaven-relay-proxy
Run a Kaven relay server, HTTP/SOCKS proxy endpoint, or fixed TCP port forwarder in a non-root Alpine Linux container.
flowchart LR
app["Application"]
origin["proxy-origin or forward-listen"]
relay["Relay server<br/>TLS port 8558"]
target["proxy-target or forward-dial"]
destination["Requested or fixed destination"]
app --> origin
origin <--> relay
relay <--> target
target --> destination
The origin and target try encrypted direct TCP transport when
TCP_HOLE_PUNCH is enabled on both sides. Any failure automatically falls
back to the relay server.
With an empty config directory, the image creates a TLS-enabled, server-only
configuration and generates certificates under ./config/generated.
The image runs as appuser. Ensure mounted directories are writable by the
container UID and GID before starting:
mkdir -p ./config ./logs
read CON_UID CON_GID <<< $(docker run --rm kavenzero/kaven-relay-proxy:latest sh -c 'echo $(id -u appuser) $(id -g appuser)')
chown -R "$CON_UID:$CON_GID" ./config ./logs
docker run --name kaven-relay-proxy \
--restart unless-stopped \
-p 8558:8558 \
-v "$(pwd)"/config:/app/config \
-v "$(pwd)"/logs:/app/logs \
-d kavenzero/kaven-relay-proxy
The generated config/generated directory contains the CA and client
certificate required by remote clients. Protect it as sensitive data and copy
the complete directory to each trusted client.
Create config/kaven-relay-proxy.config:
{
"SERVER": false,
"CLIENT": true,
"CLIENTS": [
{
"TYPE": "proxy-origin",
"CONNECT_TO_HOST": "relay.example.com",
"CONNECT_TO_PORT": 8558,
"CONNECT_TO_TLS": true,
"CERT_FILE": "./generated/cert.json",
"TCP_HOLE_PUNCH": true,
"TCP_HOLE_PUNCH_TIMEOUT": 3000,
"LOCAL_PROXY_HOST": "0.0.0.0",
"LOCAL_PROXY_PORT": 8765,
"LOCAL_PROXY_TYPE_LIST": ["http", "socks4", "socks5"],
"TARGET_ID_LIST": ["internet"]
}
]
}
Run the listener while exposing it only on the host loopback interface:
docker run --name kaven-relay-proxy-origin \
--restart unless-stopped \
-p 127.0.0.1:8765:8765 \
-v "$(pwd)"/config:/app/config \
-v "$(pwd)"/logs:/app/logs \
-d kavenzero/kaven-relay-proxy
Configure applications to use 127.0.0.1:8765 as an HTTP, SOCKS4, or SOCKS5
proxy.
Create config/kaven-relay-proxy.config:
{
"SERVER": false,
"CLIENT": true,
"CLIENTS": [
{
"TYPE": "proxy-target",
"CONNECT_TO_HOST": "relay.example.com",
"CONNECT_TO_PORT": 8558,
"CONNECT_TO_TLS": true,
"CERT_FILE": "./generated/cert.json",
"TCP_HOLE_PUNCH": true,
"TCP_HOLE_PUNCH_TIMEOUT": 3000,
"ID": "internet"
}
]
}
Host networking is recommended when the target must reach LAN-only services or when direct TCP hole punching should have the best chance of succeeding:
docker run --name kaven-relay-proxy-target \
--restart unless-stopped \
--network host \
-v "$(pwd)"/config:/app/config \
-v "$(pwd)"/logs:/app/logs \
-d kavenzero/kaven-relay-proxy
Use forward-listen on the incoming side and forward-dial on the destination
side. Publish each configured LISTEN_PORT from the listener container.
flowchart LR
app["Application"]
listener["forward-listen<br/>LISTEN_PORT"]
relay["Relay server"]
dialer["forward-dial"]
destination["DIAL_HOST:DIAL_PORT"]
app --> listener
listener <--> relay
relay <--> dialer
dialer --> destination
The default command loads /app/config. Override it with a mounted file or
directory:
docker run --rm \
-v "$(pwd)"/relay.json:/run/relay.json:ro \
kavenzero/kaven-relay-proxy \
node relay-proxy.js /run/relay.json
8558.The run examples use Docker's unless-stopped restart policy. Docker restarts
the container after an unexpected process failure or host reboot, but leaves
it stopped when an administrator explicitly stops it.
Apply the policy to existing containers:
docker update --restart unless-stopped \
kaven-relay-proxy \
kaven-relay-proxy-origin \
kaven-relay-proxy-target
Relay clients also retry indefinitely in-process. After the relay connection is lost, they reconnect with capped backoff, rediscover the configured target, and resume accepting new forwarded connections. Connections active at the moment of transport loss are closed and must be re-established by the application.
An origin remains running while its target is unavailable. Its local listener
rejects new connections until the configured target reconnects. Configuration,
certificate, and port-binding errors still require operator correction; check
the mounted logs directory and the container logs when restarts repeat.
ku CLIThe Docker image and the ku relay-proxy command use the same
kaven-relay-proxy.config format and relay implementation. Use the CLI to run
any relay role directly on a host, which is particularly useful for proxy
origins, proxy targets, and port-forwarding clients that need native LAN
access.
Install the CLI:
npm install --global kaven-utils
Start the relay proxy with a configuration directory or an explicit configuration file:
ku relay-proxy [dirOrFile] [--mkdir]
# Load ./kaven-relay-proxy.config
ku relay-proxy ./
# Load an explicit file
ku relay-proxy ./config/kaven-relay-proxy.config
# Create a missing configuration directory before starting
ku relay-proxy ./config --mkdir
When dirOrFile is omitted, ku relay-proxy uses the current working
directory. If it points to a directory, the command loads
kaven-relay-proxy.config from that directory and creates the default
configuration when the file is missing. The process stays in the foreground
until interrupted and gracefully closes its listeners and relay connections
on SIGINT or SIGTERM.
Keep the installed kaven-utils version aligned with the image version when
moving the same configuration between CLI and Docker deployments. The CLI and
container cannot bind the same host address and port at the same time.
Content type
Image
Digest
sha256:a4ba75562…
Size
86 MB
Last updated
about 1 month ago
docker pull kavenzero/kaven-relay-proxy