coolaj86 opened issue coolaj86/telebit.js#66

coolaj86
Sun, 26 Oct 2025 20:35:24 +0000

66#[doc] Protocol for currently deployed version#

TELEBIT_RELAY_BASE_URL="https://telebit.cloud"

1. Directives

curl --fail-with-body https://telebit.cloud/_apis/telebit.cloud/index.json

{ "terms_of_service": ":hostname/tos/"
, "api_host": "api.:hostname"
, "pair_request": {
    "method": "POST"
  , "pathname": "api/telebit.cloud/pair_request"
  }
, "tunnel": {
    "method": "wss"
  , "pathname": ""
  }
}

2. Pair Request (to directives.pair_request.pathname)

scope would be domains and ports to be requested, but that's not used

otp is generated client-side

a_email="jdoe@example.com"
b_otp="1234"
b_hostname="$(hostname)"
b_os_type="$(uname -s)"
b_os_platform="$(uname -s | tr '[:upper:]' '[:lower:]')"
b_os_release="$(uname -r)"
b_os_arch="$(uname -m)"

curl --fail-with-body https://telebit.cloud/api/telebit.cloud/pair_request \
   --dump-header ./headers.txt \
   -H 'Content-Type: application/json' \
   --data-binary '{
      "subject": "'"${a_email}"'",
      "subject_scheme": "mailto",
      "scope": "",
      "otp": "'"${b_otp}"'",
      "hostname": "'"${b_hostname}"'",
      "os_type": "'"${b_os_type}"'",
      "os_platform": "'"${b_os_platform}"'",
      "os_release": "'"${b_os_release}"'",
      "os_arch": "'"${b_os_arch}"'"
   }'

The response looks like:
(note: this should have included the connect URL... oops!)

{
  "domains": [],
  "ports": [],
  "aud": "telebit.cloud",
  "iat": 1761510171,
  "id": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "sub": "jdoe@example.com",
  "pin": "1234",
  "hostname": "telebyte",
  "os": "Linux",
  "os_type": "Linux",
  "os_platform": "linux",
  "os_release": "6.8.12-15-pve",
  "os_arch": "x86_64",
  "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZWxlYml0LmNsb3VkIiwiZG9tYWlucyI6W10sImhvc3RuYW1lIjoidGVsZWJ5dGUiLCJpYXQiOjE3NjE1MTAxNzEsImlkIjoieHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4Iiwib3MiOiJMaW51eCIsIm9zX2FyY2giOiJ4ODZfNjQiLCJvc19wbGF0Zm9ybSI6ImxpbnV4Iiwib3NfcmVsZWFzZSI6IjYuOC4xMi0xNS1wdmUiLCJvc190eXBlIjoiTGludXgiLCJwaW4iOiIwMDAwIiwicG9ydHMiOltdLCJzdWIiOiJqZG9lQGV4YW1wbGUuY29tIn0K.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

The JWT looks like:

{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "claims": {
    "aud": "telebit.cloud",
    "domains": [],
    "hostname": "telebyte",
    "iat": 1761510171,
    "id": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "os": "Linux",
    "os_arch": "x86_64",
    "os_platform": "linux",
    "os_release": "6.8.12-15-pve",
    "os_type": "Linux",
    "pin": "1234",
    "ports": [],
    "sub": "jdoe@example.com"
  },
  "signature": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}

3. Connect to websocket
note: the tunnel is constructed from the index.json tunnel and api_host
the actual protocol is described at https://git.coolaj86.com/coolaj86/proxy-packer.js

wss://api.telebit.cloud/

4. Pair State Polling (from Link or Location response header)

# ex https://mgmtjs.telebit.io/api/telebit.cloud/pair_state/xxxxxxxxxxxxxxxxxxxxxxxx
# note: you must manually remove the trailing \r of the \r\n
b_url=$(grep -i 'Location' ./headers.txt | cut -d' ' -f2 | tr -d '\r')

curl --fail-with-body "${b_url}" \
   --dump-header ./headers.txt

The status can change from pending to ready (browser sent correct otp) to complete (websocket accepted)

{
  "status": "pending"
}

5. Pair Info (requested from the web browser)

a_magic="************************"

curl --fail-with-body "https://api.telebit.cloud/api/telebit.cloud/pair_request/${a_magic}"

{
  "id": "xxxxxxxxxxxxxxxxxxxxxxxx",
  "scope": "",
  "hostname": "telebyte",
  "os_type": "Linux",
  "os_platform": "linux",
  "os_release": "6.8.12-15-pve",
  "os_arch": "x64"
}

6. Pair Code (sent by web browser)

a_magic="************************"
a_code="1234"

curl --fail-with-body https://api.telebit.cloud/api/telebit.cloud/pair_code/ \
--dump-header ./headers-pair.txt \
-H 'Content-Type: application/json' \
   --data-binary '{
      "magic": "'"${a_magic}"'",
      "pin": "'"${code}"'",
      "agree_tos": true
   }'

note: the idea of giving the token back to the browser was for an admin portal which was never built

{
   "id": "xxxxxxxxxxxxxxxxxxxxxxxx",
   "iat": 1761515714,
   "sub": "jdoe@example.com",
   "iss": "telebit.cloud",
   "aud": "telebit.cloud",
   "domains": [
      "silly-rabbit-42.telebit.io"
   ],
   "ports": [
      65535
   ],
   "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZWxlYml0LmNsb3VkIiwiZG9tYWlucyI6WyJzaWxseS1yYWJiaXQtNDIudGVsZWJpdC5pbyJdLCJpYXQiOjE3NjE1MTU3MTQsImlkIjoieHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4IiwiaXNzIjoidGVsZWJpdC5jbG91ZCIsInBvcnRzIjpbNjU1MzVdLCJzdWIiOiJqZG9lQGV4YW1wbGUuY29tIn0K.ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
}