Sign inSign up

ulfrasark/turnable-hy2

By ulfrasark

Updated 18 days ago

All-in-one VK-call tunnel + Hysteria2 for MikroTik ROS v7.24+ containers (x86_64 / arm64 / armv7).

Image
Networking
Security
0

177

ulfrasark/turnable-hy2 repository overview

ulfrasark/turnable-hy2

All-in-one VK-call tunnel for MikroTik RouterOS containers (x86_64 / arm64 / armv7).

Tunnels traffic through a VK video call's TURN relay — disguised as call media (SRTP) — and terminates it on a Hysteria2 backend bundled in the same container (sing-box). Pairs with the WireTurn Android client. From inside Russia the transport looks like an ordinary VK call; the exit is your VPS.

Built from source. Config-file driven: drop a *.json in the mount and the container brings up a Turnable server, a sing-box Hysteria2 backend, and auto-emits the client URLs.


Image size

LayerSize
Compressed (Docker Hub)~35 MB
Unpacked (on device)~75 MB

Multi-stage build — Turnable + sing-box binaries on Alpine, no Go toolchain in the final image. Multi-arch: amd64 / arm64 / armv7.


Why this exists (vs bare upstream Turnable)

Vanilla Turnable is only a transport — it relays to a backend you host and route to separately, which on RouterOS means cross-container routing, UDP return-path asymmetry, and a second service to babysit. This image folds the whole chain into one container.

AreaBare upstreamThis image
BackendYou run + route to s-ui/3x-uising-box Hysteria2 built in, route to 127.0.0.1
protoDocs default dtlsForced to srtp — VK relay only forwards call media; dtls never completes
KeysManual, drift on restartPersistent, client pub_key always matches server priv_key
UUIDs / password / certHand-writtenAuto-generated and persisted
TLS pinnoneEmits both pinSHA256 and pinnedPeerCertSha256 (WireTurn's Xray needs hex)
Call presenceKeep a client connectedPeriodic anchor joins every 30 min, leaves cleanly
Crash handlingnoneTurnable, sing-box, anchor self-restart in-container

MikroTik settings

/interface/veth add name=veth-tb address=172.16.182.2/24 gateway=172.16.182.1
/ip/address add address=172.16.182.1/24 interface=veth-tb
/ip/firewall/nat/add chain=srcnat src-address=172.16.182.0/24 action=masquerade comment="turnable out"
/ip/firewall/nat/add chain=dstnat protocol=udp dst-port=56000 action=dst-nat to-addresses=172.16.182.2 to-ports=56000 comment="turnable listen"

Only 56000/udp is forwarded in. The Hy2 backend listens on 127.0.0.1 inside the container and is never exposed.


Mount for config + persistent keys

/container/mounts/add name=tb_config src=/usb1/turnable-confs dst=/etc/turnable

Holds your *.json config, plus auto-created .keys/ (ML-KEM keys + Hy2 cert), clients/ (the generated URLs), and singbox.log. Without this mount the keys regenerate on every restart and old client links break.


Install container

/container/add
remote-image=ulfrasark/turnable-hy2:latest
interface=veth-tb
mounts=tb_config
root-dir=/usb1/turnable
dns=8.8.8.8
start-on-boot=yes
restart-policy=on-failure
restart-interval=60s
logging=yes

RouterOS caches images by name:tag. When updating, use a NEW tag AND a NEW root-dir, or the old layer is reused.


Start

/container/start [find interface=veth-tb]


Check logs

/log print where topics~"container"

On startup the container prints the client links. Hand out two per user, both from the mount's clients/ dir:
turnable://... (transport via VK)
hysteria2://... (proxy)


Config files (place in the mount dir)

FilePurpose
server.jsonTurnable server config (an example below, renamed)
hysteria2.jsonBuilt-in Hy2 backend fields
config.shared-one-cred.example.jsonOne credential, everyone shares it
config.5users-own-creds.example.json5 users, own creds each, revocable individually
config.vless.example.jsonVLESS-over-TCP backend variant

hysteria2.json fields

{
  "listen_port": 2443,
  "password": "PUT_PASSWORD_OR_LEAVE",
  "sni": "max.ru",
  "obfs_password": "",
  "up_mbps": 0,
  "down_mbps": 0
}

listen_port must equal the Turnable route port. Leave password as PUT_* to auto-generate. up/down_mbps 0 = no brutal (a single VK allocation is already capped to ~2 Mbit flat, so shaping is usually pointless).


Minimal server config (shared model)

{
  "servers": {
    "vk": {
      "type": "relay",
      "provider": "prov",
      "platform_id": "vk.com",
      "call_id": "PUT_VK_CALL_ID",
      "public_ip": "PUT_YOUR_VPS_IP",
      "listen_addr": "0.0.0.0:56000",
      "proto": "srtp",
      "pub_key": "",
      "priv_key": ""
    }
  },
  "providers": {
    "prov": {
      "type": "raw",
      "routes": [
        { "id": "shared", "address": "127.0.0.1", "port": 2443, "socket": "udp", "transport": "none" }
      ],
      "users": [
        { "uuid": "PUT_SHARED_UUID_OR_LEAVE", "allowed_routes": ["shared"], "type": "relay", "peers": 1 }
      ]
    }
  }
}

Fill call_id (from a VK call link) and public_ip. Leave keys / UUID / password empty — they auto-generate and persist. The route port must match hysteria2.json.


Port forwarding

PortProtocolRequired
56000UDPAlways (Turnable listener; VK relay connects here)

Bandwidth and antifraud

PeersThroughputNote
1~2 Mbit flatOne allocation, VK policer, no sawtooth. Quiet.
2~3 MbitFloats; 2 participants in the call
4~5 MbitFloats more; 4 participants — higher antifraud signal

Keep peers=1 for quiet long-term use; raise only for short bursts. Each peer is another "participant" VK's antifraud can see.


How it works

phone Xray (Hy2, pinned) -> Turnable client -> VK TURN relay (SRTP) -> Turnable server :56000 -> route 127.0.0.1:2443 -> sing-box Hysteria2 -> internet

The client briefly joins the VK call to get TURN credentials, then leaves the room while the allocation stays live — traffic rides the allocation, not a visible participant, which keeps antifraud quiet.


Environment variables

KeyDefaultPurpose
TURNABLE_ANCHOR_MODEperiodicperiodic = brief visits, off = none
TURNABLE_ANCHOR_INTERVAL1800seconds between visits
TURNABLE_ANCHOR_HOLD20seconds held per visit

Credits

Transport: TheAirBlow/Turnable
Proxy core: SagerNet/sing-box
Client: WireTurn

This image packages and wires them together for RouterOS; all protocol credit is theirs.


GitHub

Source and Dockerfile: coming soon

Tag summary

Content type

Image

Digest

sha256:675ac99eb

Size

24.6 MB

Last updated

18 days ago

docker pull ulfrasark/turnable-hy2