add etrelay UDP relay + etmasters script + update README

This commit is contained in:
rmanach
2026-09-26 14:53:52 +02:00
parent 002289fd35
commit 6b9d14f86b
22 changed files with 1106 additions and 9 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+21
View File
@@ -0,0 +1,21 @@
@startuml
skinparam shadowing false
title After: everything goes through the front
actor Player as player
node "Master\netmaster.net:27950" as master
node "Front (74.208.250.147)" {
component "etrelay\n0.0.0.0:27960" as relay
}
node "Home" {
component "nginx stream\n10.66.0.10:27960" as nginx
component "ET server\n10.0.1.103:27960" as et
}
player <--> relay : game traffic
master <--> relay : heartbeat / getChallenge / getInfo
relay <--> nginx : WireGuard (wg0)
nginx <--> et : LAN
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+14
View File
@@ -0,0 +1,14 @@
@startuml
skinparam shadowing false
title Before: heartbeat leaves through the home box
node "Master\netmaster.net:27950" as master
node "Home box\n86.x.x.x" as box
node "Front\n74.208.250.147" as front
node "ET server\n10.0.1.103:27960" as et
et --> box : heartbeat
box --> master : heartbeat (source = home IP)
master --> box : getChallenge\n(to home IP: dropped)
front ..> et : players (DNAT + wg + nginx stream)
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+10
View File
@@ -0,0 +1,10 @@
@startuml
skinparam shadowing false
title Heartbeat decision (every 5 min)
[*] --> Down
Down --> Up : probe answers\n/ heartbeat EnemyTerritory-1
Up --> Up : probe answers\n/ heartbeat EnemyTerritory-1
Up --> Down : no answer\n/ heartbeat ETFlatline-1 (once)
Down --> Down : no answer\n/ nothing sent
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+19
View File
@@ -0,0 +1,19 @@
@startuml
skinparam shadowing false
title Player: one session per client address
actor "Player\n1.2.3.4:5555" as player
participant "etrelay\nfront :27960" as relay
participant "session task\n(ephemeral socket)" as session
participant "ET server" as et
player -> relay : getchallenge / connect / game packets
relay -> session : first packet: open session
session -> et : forward (source = ephemeral port)
et --> session : reply
session --> player : reply sent from front:27960
...packets both ways, deadline pushed back on each packet...
...2 min without any packet...
session -> session : close (socket dropped)
note over relay : next packet from 1.2.3.4:5555\nopens a new session
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

+28
View File
@@ -0,0 +1,28 @@
@startuml
skinparam shadowing false
title Master registration (every 5 min)
participant "Master\netmaster.net:27950" as master
participant "etrelay\nfront :27960" as relay
participant "ET server\n(via wg + nginx)" as et
== Liveness probe (dedicated ephemeral socket) ==
relay -> et : getinfo etrelay
et --> relay : infoResponse
note right of relay : up: send heartbeat\nno answer x3: skip (or flatline once)
== Heartbeat (public socket) ==
relay -> master : heartbeat EnemyTerritory-1\nsource = front:27960
== Master checks: handled like any client ==
master -> relay : getChallenge\nto front:27960
relay -> relay : new session for master:27950
relay -> et : getChallenge
et --> relay : challengeResponse
relay --> master : challengeResponse\nsource = front:27960
master -> relay : getInfo
relay -> et : getInfo
et --> relay : infoResponse (hostname, map, players)
relay --> master : infoResponse\nsource = front:27960
note left of master : lists 74.208.250.147:27960
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+26
View File
@@ -0,0 +1,26 @@
@startuml
skinparam shadowing false
title Tasks and data flow
rectangle "relay loop (main task)" as loop {
card "public socket\nrecv_from" as recv
card "sessions:\nHashMap<client, Sender>" as map
}
rectangle "session task (one per client)" as st {
card "mpsc Receiver\n(queue: 64)" as rx
card "upstream socket\n(connected to ET)" as up
}
rectangle "heartbeat task" as hb {
card "interval 5 min" as tick
card "probe socket" as probe
}
recv --> map : lookup client
map --> rx : try_send(packet)\n(full: drop)
rx --> up : send
up --> recv : recv, then public.send_to(client)
tick --> probe : getinfo
tick --> recv : heartbeat via public socket
@enduml