# SecLink Proxy Linux-hosted proxy that bridges an 86Box emulated serial port to a remote telnet BBS. The 86Box side communicates using the secLink protocol (packet framing, DH key exchange, XTEA encryption). The BBS side is plain telnet over TCP. ## Architecture ``` 86Box (DOS terminal) Remote BBS | | emulated modem telnet:23 | | TCP:2323 TCP:23 | | +--- secproxy ----------------------------------+ secLink ←→ plaintext (encrypted, reliable) ``` The proxy accepts a single TCP connection from 86Box, performs the secLink handshake (DH key exchange), then connects to the BBS. All traffic between 86Box and the proxy is encrypted via XTEA-CTR on channel 0. Traffic between the proxy and the BBS is unencrypted telnet. ## Usage ``` secproxy [listen_port] [bbs_host] [bbs_port] ``` | Argument | Default | Description | |---------------|------------------------|---------------------------------| | `listen_port` | 2323 | TCP port for 86Box connection | | `bbs_host` | bbs.duensing.digital | BBS hostname | | `bbs_port` | 23 | BBS TCP port | ``` secproxy # all defaults secproxy 5000 # listen on port 5000 secproxy 2323 bbs.example.com 23 # different BBS secproxy --help # show usage ``` ## Startup Sequence 1. Listen on the configured TCP port 2. Wait for 86Box to connect (blocks on accept) 3. Connect to the remote BBS 4. Seed the RNG from `/dev/urandom` 5. Open secLink and perform the DH handshake (blocks until the DOS side completes its handshake) 6. Enter the proxy loop ## Proxy Loop The main loop uses `poll()` with a 10ms timeout to multiplex between the two TCP connections: - **86Box → BBS**: `secLinkPoll()` reads from the 86Box socket via the socket shim, decrypts incoming packets, and the receive callback writes plaintext to the BBS socket. - **BBS → 86Box**: `read()` from the BBS socket, then `secLinkSend()` encrypts and sends to 86Box via the socket shim. - **Maintenance**: `secLinkPoll()` also handles packet-layer retransmit timers on every iteration. The proxy exits cleanly on Ctrl+C (SIGINT), SIGTERM, or when either side disconnects. ## 86Box Configuration Configure the 86Box serial port to use a telnet connection: 1. In 86Box settings, set a COM port to "TCP (server)" or "TCP (client)" mode pointing at the proxy's listen port 2. Enable "No telnet negotiation" to send raw bytes 3. The DOS terminal application running inside 86Box uses secLink over this serial port ## Socket Shim The proxy reuses the same packet, security, and secLink source code as the DOS build. A socket shim (`sockShim.h`/`sockShim.c`) provides rs232-compatible `rs232Read()`/`rs232Write()` functions backed by TCP sockets instead of UART hardware: | rs232 function | Socket shim behavior | |----------------|-----------------------------------------------| | `rs232Open()` | No-op (socket already connected) | | `rs232Close()` | Marks port closed (socket managed by caller) | | `rs232Read()` | Non-blocking `recv()` with `MSG_DONTWAIT` | | `rs232Write()` | Blocking `send()` loop with `MSG_NOSIGNAL` | The shim maps COM port indices (0-3) to socket file descriptors via `sockShimSetFd()`, which must be called before opening the secLink layer. DOS-specific headers (``, ``, ``) are replaced by minimal stubs in `stubs/` that provide no-op implementations. The security library's hardware entropy function returns zeros on Linux, which is harmless since the proxy seeds the RNG from `/dev/urandom` before the handshake. ## Building ``` make # builds ../bin/secproxy make clean # removes objects and binary ``` Objects are placed in `../obj/proxy/`, the binary in `../bin/`. Requires only a standard Linux C toolchain (gcc, libc). No external dependencies. ## Files ``` proxy/ proxy.c main proxy program sockShim.h rs232-compatible socket API (header) sockShim.c socket shim implementation Makefile Linux build stubs/ pc.h stub for DJGPP go32.h stub for DJGPP sys/ farptr.h stub for DJGPP ```