A web page cannot open raw TCP sockets — that is a browser security boundary, and DarkRoute does not fake its way around it. The SOCKS5 handshake itself (RFC 1928 greeting, method negotiation, RFC 1929 username/password auth, CONNECT, reply decoding) runs in real byte form in JavaScript — it just travels the last hop to your proxy as bytes inside a WebSocket to a relay you control.
// relay.js — npm i ws, then: node relay.js
const { WebSocketServer } = require('ws');
const net = require('net');
new WebSocketServer({ port: 1081 }).on('connection', (ws) => {
let tcp = null;
ws.on('message', (data, isBinary) => {
if (!isBinary) {
const msg = JSON.parse(data.toString());
if (msg.cmd === 'open' && !tcp) {
tcp = net.connect(msg.port, msg.host,
() => ws.send(JSON.stringify({ cmd: 'ready' })));
tcp.on('data', (b) => ws.readyState === 1 && ws.send(b));
tcp.on('close', () => ws.close());
tcp.on('error', (e) => {
ws.send(JSON.stringify({ cmd: 'error', message: e.message }));
ws.close();
});
}
if (msg.cmd === 'close') ws.close();
} else if (tcp) tcp.write(data);
});
ws.on('close', () => tcp && tcp.destroy());
ws.on('error', () => tcp && tcp.destroy());
});
console.log('DarkRoute relay on ws://localhost:1081');
# relay.py — pip install websockets, then: python relay.py
import asyncio, json
from websockets.server import serve
async def pump(reader, ws):
try:
while True:
chunk = await reader.read(4096)
if not chunk: break
await ws.send(chunk)
finally:
await ws.close()
async def handle(ws):
writer = None
async for data in ws:
if isinstance(data, str):
msg = json.loads(data)
if msg.get('cmd') == 'open' and writer is None:
try:
reader, writer = await asyncio.open_connection(msg['host'], msg['port'])
except OSError as e:
await ws.send(json.dumps({'cmd': 'error', 'message': str(e)}))
return
await ws.send(json.dumps({'cmd': 'ready'}))
asyncio.create_task(pump(reader, ws))
else:
writer.write(data)
if writer: writer.close()
async def main():
async with serve(handle, 'localhost', 1081):
print('DarkRoute relay on ws://localhost:1081')
await asyncio.Future()
asyncio.run(main())
| part | status |
|---|---|
| SOCKS5 greeting / methods / RFC 1929 auth / CONNECT / reply codes | real bytes, real codec, RFC 1928/1929 |
| HTTP/1.1 fetching through the tunnel (status, headers, chunked, redirects) | real |
| DNS verdict (ATYP=3 domain vs literal IP) | derived from the actual CONNECT frame |
| WebRTC candidate audit | real local enumeration, no STUN, nothing sent |
| Demo mode network (nine .dr hosts, exit geo, faults) | simulated in memory — always labelled DEMO |
| Demo https | simulated TLS at the virtual exit — never claimed as real |
| Live-relay https | impossible in a raw byte tunnel — cockpit explains instead of faking |
| history / bookmarks / logs / credentials | memory only, wiped by BURN, never stored |