DVX_GUI/proxy/README.md

132 lines
4.5 KiB
Markdown

# 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 (`<pc.h>`, `<go32.h>`, `<sys/farptr.h>`) 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 <pc.h>
go32.h stub for DJGPP <go32.h>
sys/
farptr.h stub for DJGPP <sys/farptr.h>
```