feat: initial etrelay UDP relay with master heartbeat
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# etrelay
|
||||
|
||||
UDP relay + master heartbeat for a Wolfenstein: Enemy Territory server reachable only through a tunnel: runs on the front server (public IP) and makes the server show up in the in-game browser.
|
||||
|
||||
```
|
||||
players / masters ──> front :27960 (etrelay) ══wg══> <wg-peer>:27960 (nginx stream) ──> ET <et-server>:27960
|
||||
```
|
||||
|
||||
- **Proxy**: one upstream socket per client address, packets forwarded as-is both ways, session dropped after 2 min of silence.
|
||||
- **Heartbeat**: every 5 min, `getinfo` to the ET server; if it answers, `heartbeat EnemyTerritory-1` to the masters **from the public socket**. When it stops answering, one `heartbeat ETFlatline-1`.
|
||||
|
||||
Masters check (`getChallenge`, `getInfo`) the address the heartbeat came from: the public `:27960`. Those packets go through the relay like any client, the ET server answers them, and the master lists the front public address.
|
||||
|
||||
How it works in detail, with diagrams: [ENGINE.md](ENGINE.md).
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
etrelay <UPSTREAM> [--listen 0.0.0.0:27960] [--master host:port]... [--debug]
|
||||
```
|
||||
|
||||
Default masters: `etmaster.idsoftware.com:27950` (id Software, the one ET 2.60b clients query) and `etmaster.net:27950` (ET: Legacy community). Passing `--master` replaces both.
|
||||
|
||||
`--debug` logs sessions (open/close, packet counts), connectionless packets by command name only (`getinfo`, `getstatus`, `connect`...: no arguments, `connect` carries the userinfo), probes and heartbeats. In-game packets are only counted.
|
||||
|
||||
```
|
||||
probe <wg-peer>:27960: up
|
||||
ET server <wg-peer>:27960 is up
|
||||
heartbeat EnemyTerritory-1 -> etmaster.net:27950 (198.51.100.10:27950)
|
||||
session + 198.51.100.10:27950 (2 active)
|
||||
198.51.100.10:27950 -> ET getChallenge (27 B)
|
||||
198.51.100.10:27950 <- ET challengeResponse (32 B)
|
||||
198.51.100.10:27950 -> ET getInfo (22 B)
|
||||
198.51.100.10:27950 <- ET infoResponse (303 B)
|
||||
session - <player>:27960: 5321 packets to ET, 4876 from ET
|
||||
```
|
||||
|
||||
As a service: add `--debug` to `ExecStart`, then `systemctl daemon-reload && systemctl restart etrelay`.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
make build # dynamic (glibc)
|
||||
make static # static (musl), runs on any x86_64 Linux
|
||||
make release # both
|
||||
```
|
||||
|
||||
Artifacts land in `dist/`, named `<name>-v<version>-<target triple>` with a `.sha256` checksum:
|
||||
|
||||
```
|
||||
dist/etrelay-v0.1.0-x86_64-unknown-linux-gnu # dynamic
|
||||
dist/etrelay-v0.1.0-x86_64-unknown-linux-musl # static
|
||||
```
|
||||
|
||||
## Run as a service
|
||||
|
||||
1. Binary and unit on the front server ([etrelay.service](etrelay.service) is a template: replace `@UPSTREAM@` with the ET server `ip:port` as seen from the front, `@ARGS@` with extra flags or nothing):
|
||||
```bash
|
||||
install -m 755 dist/etrelay-v<version>-x86_64-unknown-linux-musl /usr/local/bin/etrelay
|
||||
sed -e 's#@UPSTREAM@#<ip:port>#' -e 's#@ARGS@##' etrelay.service > /etc/systemd/system/etrelay.service
|
||||
systemctl daemon-reload && systemctl enable --now etrelay
|
||||
```
|
||||
2. Nothing else on the front may capture UDP 27960 (DNAT rule, nginx `stream`...), or players bypass the relay: `iptables -t nat -S | grep 27960` must print nothing.
|
||||
3. ET server `server.cfg`: stop its own heartbeats, they leave through the home connection with the wrong IP:
|
||||
```
|
||||
set sv_master1 ""
|
||||
set sv_master2 ""
|
||||
set sv_master3 ""
|
||||
set sv_master4 ""
|
||||
set sv_master5 ""
|
||||
```
|
||||
|
||||
## Check
|
||||
|
||||
```bash
|
||||
journalctl -u etrelay -n 50 # "ET server ... is up"
|
||||
tcpdump -ni any udp port 27950 # heartbeat out, getChallenge/getInfo in, answers out
|
||||
```
|
||||
|
||||
The server then shows up on the master (in-game server browser).
|
||||
Reference in New Issue
Block a user