Minimal, cross-platform Steam Datagram Relay compatibility service for SKYNET
and AppID 1422450.
Important
This project is experimental. It currently implements only the SDR
RouterPing request/reply flow used for relay discovery and latency
measurement. It does not yet forward application traffic and is not a full
implementation of Valve's Steam Datagram Relay network.
| Runtime identifier | Target |
|---|---|
win-x64 |
Windows x86-64 |
linux-x64 |
Linux x86-64 |
linux-arm64 |
64-bit ARM Linux, including Raspberry Pi with a 64-bit OS |
linux-arm |
32-bit ARM Linux where .NET 8 is supported |
Warning
Android ARM64 is experimental and is not a native supported target.
The linux-arm64 build cannot run directly on stock Android. It may run inside an ARM64 Debian or Ubuntu environment using Termux and PRoot without CPU emulation, but this configuration is not covered by automated testing. Android background execution, battery optimization and network restrictions may interrupt the relay. A dedicated Android APK and foreground service will be required for reliable native deployment.
For Raspberry Pi and other new ARM deployments, use a 64-bit operating system
and the linux-arm64 build. The ARM targets are produced automatically, but
validation on physical ARM hardware is still in progress.
The service is managed .NET code and does not use architecture-specific native
libraries. Framework-dependent builds use AnyCPU; self-contained builds
include the runtime and native launcher for the selected target.
| Environment | Runtime | Status |
|---|---|---|
| Windows x86-64 PC | win-x64 |
Tested |
| Debian 12 x86-64 in VirtualBox | linux-x64 |
Tested |
| Raspberry Pi with a 64-bit OS | linux-arm64 |
Tested on physical hardware |
| 32-bit ARM Linux device | linux-arm |
Build available, not tested on physical hardware |
| Android ARM64 with Termux/PRoot | linux-arm64 |
Not tested and not officially supported |
The linux-arm64 build has been validated on physical Raspberry Pi hardware.
The linux-arm build is produced automatically but has not yet been tested on
a physical 32-bit ARM device.
- .NET 8 Worker Service
- IPv4 UDP listener
- configurable UDP port and POP values
- SDR
RouterPingrequest handling - SDR
RouterPingReplygeneration - remote IPv4 address and UDP port reflection
- architecture-independent IPv4 byte-order handling
- self-contained builds for Windows x64, Linux x64, Linux ARM64 and Linux ARM
- automatic GitHub Actions artifacts for all supported runtime identifiers
- .NET 8 SDK when building from source, or no preinstalled runtime when using a self-contained artifact
- an open UDP port; the default is
28009/UDP - SKYNET configured to advertise the relay endpoint
-SDR-Relay/
├── .github/workflows/publish.yml
├── Generated/
├── Program.cs
├── SdrRelayService.cs
├── SDR-Relay.csproj
└── appsettings.json
Program.csstarts the .NET Worker Service.SdrRelayService.cscontains the UDP SDR implementation.Generated/contains protobuf-generated C# types.appsettings.jsonconfigures the relay process.
- Open the repository on GitHub.
- Select Actions.
- Open the latest successful Publish workflow run.
- Find Artifacts at the bottom of the run page.
- Download the artifact matching the target platform.
Available artifact names:
SDR-Relay-win-x64
SDR-Relay-linux-x64
SDR-Relay-linux-arm64
SDR-Relay-linux-arm
GitHub downloads the artifact as a ZIP archive. The ZIP contains a
SDR-Relay-<runtime-id>.tar.gz archive. Extract both layers before running the
service.
git clone https://github.com/micro-chief/-SDR-Relay.git
cd -SDR-Relay
dotnet restore
dotnet build --configuration ReleaseThe framework-dependent build is written to:
bin/Release/net8.0/
dotnet publish --configuration Release --runtime linux-arm64 --self-contained truedotnet publish --configuration Release --runtime linux-arm --self-contained truedotnet publish --configuration Release --runtime linux-x64 --self-contained truedotnet publish --configuration Release --runtime win-x64 --self-contained truePublished files are written to:
bin/Release/net8.0/<runtime-id>/publish/
dotnet runFrom the extracted linux-arm64 artifact or publish directory:
chmod +x SDR-Relay
./SDR-RelayUse the same commands with the artifact matching the target architecture:
chmod +x SDR-Relay
./SDR-Relay.\SDR-Relay.exeThe default listen endpoint is:
0.0.0.0:28009/UDP
Stop the process with Ctrl+C.
The service reads standard .NET configuration from appsettings.json, command
line arguments and environment variables.
| Key | Default | Description |
|---|---|---|
Sdr:RelayPort |
28009 |
UDP listen port |
Sdr:PopId |
sk2 |
POP code for this instance |
Sdr:PeerPopId |
sky |
peer POP returned in ping replies |
Sdr:PeerPingMs |
1 |
advertised latency to the peer POP |
Command-line example:
./SDR-Relay --Sdr:RelayPort=28010 --Sdr:PopId=armLinux environment variables:
export Sdr__RelayPort=28010
export Sdr__PopId=arm
./SDR-RelayWindows PowerShell environment variables:
$env:Sdr__RelayPort = "28010"
$env:Sdr__PopId = "arm"
.\SDR-Relay.exeExample:
[SDR]
Revision=1786739253
[Relay.sky]
Address=192.168.0.101
Port=28009
Description=SKYNET Primary
Longitude=4.90
Latitude=52.37
Partners=1
Tier=0
[Relay.arm]
Address=192.168.0.23
Port=28009
Description=SKYNET ARM64 Relay
Longitude=4.91
Latitude=52.38
Partners=1
Tier=1
[TypicalPing.sky-arm]
From=sky
To=arm
Ping=1Use an address reachable by the client. Do not advertise 127.0.0.1 for a
relay running on another host.
The relay and the primary server endpoint must not share the same effective network interface or packet path. SDR-aware clients observe the route, and collapsing both roles onto the same path can produce incorrect behaviour.
Deploy the relay as an independent endpoint, for example:
Client -> Raspberry Pi ARM64 relay -> primary server endpoint
Running multiple processes on one interface with different UDP ports can be useful for local protocol development, but it does not reproduce independent relay paths.
Allow inbound UDP traffic on the configured relay port.
sudo ufw allow 28009/udpNew-NetFirewallRule `
-DisplayName "SKYNET SDR Relay" `
-Direction Inbound `
-Protocol UDP `
-LocalPort 28009 `
-Action AllowIf the endpoint is behind NAT and must be reachable from another network, forward the same UDP port to the relay host.
- Start SDR-Relay.
- Start SKYNET.
- Start AppID
1422450. - Run the following command in the application console:
net_print_sdr_ping_times
A reachable endpoint should appear in the SDR POP list with a measured RTT.
Another process is already using the configured UDP port. Select another port:
./SDR-Relay --Sdr:RelayPort=28010Check that:
- SDR-Relay is running.
- The configured address is reachable from the client.
- The configured UDP port matches the process configuration.
- The host firewall allows inbound UDP traffic.
- NAT or port forwarding is configured when required.
- SKYNET is serving the expected SDR configuration.
Do not advertise 127.0.0.1. Use the relay host's LAN or public address and
verify the firewall and NAT configuration.
- additional SDR packet types
- application-traffic forwarding
- more complete Steam Datagram Relay protocol handling
- multi-POP configuration and diagnostics
- SKYNET GC integration
- validation on physical ARM32 hardware
This project is an independent compatibility and research project.
The MIT License applies only to the original source code authored for this repository. Third-party protocols, names, trademarks, specifications and generated definitions remain the property of their respective owners.
This project is not affiliated with, endorsed by, or sponsored by Valve Corporation.