Sign inSign up

kavenzero/kaven-relay-proxy

By kavenzero

•Updated about 1 month ago

Image
0

778

kavenzero/kaven-relay-proxy repository overview

⁠kaven-relay-proxy

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.

⁠Relay process

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.

⁠Run a 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.

⁠Run a proxy origin

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.

⁠Run a proxy target

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

⁠Fixed TCP port forwarding

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

⁠Custom configuration path

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

⁠Security

  • Keep TLS enabled and restrict inbound access to relay port 8558.
  • Treat the generated CA and client private keys as secrets.
  • Bind proxy and forwarded ports to trusted interfaces only.
  • The relay is intended for trusted clients; it is not a multi-tenant authorization boundary.

⁠24/7 operation

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 CLI

The 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.

Tag summary

Content type

Image

Digest

sha256:a4ba75562…

Size

86 MB

Last updated

about 1 month ago

docker pull kavenzero/kaven-relay-proxy