Files
PSK-Proxy-Tunnel/BUILD.md

7.6 KiB

PSK-Proxy-Tunnel Build & Usage Guide

This guide explains how to build single executable binaries and how to run the TLS-PSK tunnel with a three-tier architecture: a local SOCKS5 proxy client, a relay node, and an exit node.

Key changes:

  • The architecture is now Client -> Relay -> Exit.
  • proxy-server.js is now a relay node (psk-proxy-relay).
  • A new proxy-exit.js script acts as the exit node (psk-proxy-exit).
  • The client connects to the relay, and the relay connects to the exit node.

Prerequisites

  • Node.js: Version 18.0.0 or higher
  • npm: Usually comes with Node.js
  • Git: To clone the repository

Quick Start

1) Install dependencies

npm install

2) Build for your current platform

# macOS/Linux
./build.sh

# Windows
build.bat

Or via npm directly:

npm run build:macos   # macOS
npm run build:linux   # Linux
npm run build:windows # Windows

3) Build for all platforms

npm run build

Build Scripts

Using the build scripts

Unix/Linux/macOS:

chmod +x build.sh
./build.sh                 # current platform
./build.sh --platform macos
./build.sh --platform linux
./build.sh --platform windows
./build.sh --all           # all platforms
./build.sh --clean         # remove dist/
./build.sh --help

Windows:

build.bat                  # Windows (default)
build.bat --all            # all platforms
build.bat --clean
build.bat --help

Using npm scripts directly

npm run build:macos
npm run build:linux
npm run build:windows
npm run build              # all platforms
npm run clean              # remove dist/

Build Output

Executables are created in dist/:

dist/
├── psk-proxy-client-macos
├── psk-proxy-relay-macos
├── psk-proxy-exit-macos
├── psk-proxy-client-linux
├── psk-proxy-relay-linux
├── psk-proxy-exit-linux
├── psk-proxy-client-windows.exe
├── psk-proxy-relay-windows.exe
└── psk-proxy-exit-windows.exe

Running the Servers and Client

The PSK (pre-shared key) file must contain a hex-encoded key string used by all components.

1. Exit Node

  • Listens for a single TLS-PSK tunnel connection from the relay.
  • Performs outbound TCP connects and UDP sends on behalf of the client.

macOS/Linux:

./dist/psk-proxy-exit-macos \
  --relay-port 9000 \
  --host 0.0.0.0 \
  --psk-file /path/to/psk.hex

Windows:

.\dist\psk-proxy-exit-windows.exe ^
  --relay-port 9000 ^
  --host 0.0.0.0 ^
  --psk-file C:\path\to\psk.hex

Required options:

  • --relay-port <port>: Port for the relay to connect to.
  • --host <host>: Bind host (e.g., 0.0.0.0).
  • --psk-file <path>: File containing hex PSK.

2. Relay Node

  • Listens for the client and connects to the exit node.
  • Relays traffic between the client and the exit node.

macOS/Linux:

./dist/psk-proxy-relay-macos \
  --tunnel-port 8443 \
  --host 0.0.0.0 \
  --psk-file /path/to/psk.hex \
  --exit-host exit.node.com \
  --exit-port 9000 \
  --exit-identity relay1

Windows:

.\dist\psk-proxy-relay-windows.exe ^
  --tunnel-port 8443 ^
  --host 0.0.0.0 ^
  --psk-file C:\path\to\psk.hex ^
  --exit-host exit.node.com ^
  --exit-port 9000 ^
  --exit-identity relay1

Required options:

  • --tunnel-port <port>: Port for the client to connect to.
  • --host <host>: Bind host.
  • --psk-file <path>: File containing hex PSK.
  • --exit-host <host>: Exit node host.
  • --exit-port <port>: Exit node port.
  • --exit-identity <id>: Identity for the relay when connecting to the exit node.

3. Client (Local SOCKS5 Proxy)

  • Runs a local SOCKS5 proxy.
  • Connects to the relay node.

macOS/Linux:

./dist/psk-proxy-client-macos \
  --server-host relay.node.com \
  --server-port 8443 \
  --psk-file /path/to/psk.hex \
  --identity client1 \
  --socks-port 1080

Windows:

.\dist\psk-proxy-client-windows.exe ^
  --server-host relay.node.com ^
  --server-port 8443 ^
  --psk-file C:\path\to\psk.hex ^
  --identity client1 ^
  --socks-port 1080

Required options:

  • --server-host <host>: Relay node address.
  • --server-port <port>: Relay node port.
  • --psk-file <path>: File containing hex PSK.
  • --identity <id>: Identity string (logged on relay).
  • --socks-port <port>: Local SOCKS5 proxy port.

Optional:

  • --bind-host <host>: Local bind host (default 127.0.0.1).
  • --connect-timeout <ms>: Timeout for connection setup (default 10000).
  • --idle-timeout <ms>: Idle timeout for TCP sockets (default 60000).
  • --udp-idle-timeout <ms>: Idle timeout for UDP association (default 60000).

Protocol Summary

All multiplexed over a single TLS-PSK socket:

Header (9 bytes):

  • 1 byte type
  • 4 bytes connection id (unsigned)
  • 4 bytes payload length (unsigned)
  • payload bytes

Types:

  • TCP:
    • DATA (2): stream data
    • CLOSE (3): close stream
    • OPEN (4): payload = [2B hostLen][host][2B port]
    • OPEN_RESULT (5): payload = [1B status] (1=success, 0=failure)
  • UDP (for SOCKS5 UDP ASSOCIATE):
    • UDP_OPEN (6): payload empty
    • UDP_OPEN_RESULT (7): payload = [1B status] (1=success, 0=failure)
    • UDP_SEND (8): payload = [2B hostLen][host][2B port][2B dataLen][data]
    • UDP_RECV (9): same layout as UDP_SEND
    • UDP_CLOSE (10): payload empty

Testing

Assuming the client runs a local SOCKS5 proxy at 127.0.0.1:1080:

  • HTTP over SOCKS5 (remote DNS resolution via socks5h):

    curl -x socks5h://127.0.0.1:1080 http://example.com/
    
  • HTTPS over SOCKS5:

    curl -x socks5h://127.0.0.1:1080 https://ifconfig.me
    
  • SSH over SOCKS5 (using nc as ProxyCommand):

    ssh -o ProxyCommand="nc -x 127.0.0.1:1080 -X 5 %h %p" user@your.remote.host
    
  • Applications with SOCKS5 (TCP and UDP):

    • Many apps support SOCKS5 TCP CONNECT (browsers, package managers, etc.).
    • For UDP ASSOCIATE (e.g., some torrent clients, DNS forwarders with SOCKS5-UDP support), configure them to use 127.0.0.1:1080 SOCKS5 and enable UDP if supported. Note: many CLI tools do not implement SOCKS5 UDP.

Notes:

  • socks5h in curl ensures DNS names are resolved through the proxy.
  • UDP test coverage depends on the client application having SOCKS5 UDP support.

Troubleshooting

  1. "pkg command not found"
npm install -g pkg
# or
npx pkg proxy-server.js
  1. Build fails with permission errors
chmod +x build.sh
sudo npm run build  # if necessary
  1. Executable doesn't run on target platform
  • Ensure you built for the correct target
  • Verify executable permissions
  • Confirm compatible Node target in pkg config
  1. Tunnel connects but traffic fails
  • Confirm both server and client use the exact same hex PSK
  • Check connectivity from server to target hosts/ports (firewall, outbound rules)
  • Use --connect-timeout to tune behavior
  1. SOCKS5 UDP doesn't appear to work
  • Confirm your application actually supports SOCKS5 UDP ASSOCIATE
  • Check that the client printed "Local SOCKS5 proxy listening ..."
  • Inspect server logs for UDP_* activity

Performance Considerations

  • Single tunnel multiplexes many flows (reduced connection overhead).
  • UDP sockets are ephemeral and idle-timed to conserve resources.
  • TCP and UDP buffers are kept minimal; tune OS limits as needed.

Build Configuration

Defined in package.json under pkg:

{
  "pkg": {
    "assets": [],
    "scripts": [],
    "targets": [
      "node18-macos-x64",
      "node18-linux-x64",
      "node18-win-x64"
    ]
  }
}

Contributing

  • Keep CLI flags in proxy-client.js and proxy-server.js in sync with this document.
  • Update build scripts (build.sh, build.bat) when adding platforms.
  • Test TCP (HTTP/HTTPS/SSH) and at least one UDP-capable client where possible.