Bridge UDP broadcasts across network boundaries. Catch UDP broadcast (or unicast) messages on one LAN and relay them — in both directions — to an application on a different network.
Built and maintained by Allegro IT ApS — international project leadership, legacy-code maintenance & cloud hosting.
UDP broadcasts don't cross routers. If a device shouts a UDP packet onto its local network, only listeners on that same network hear it — an application on another LAN, a VPN, or the cloud never sees it.
UDP Relay sits on a machine inside the device's network, listens for those packets, and forwards them to a remote endpoint you choose. It also relays the remote endpoint's answers back to the device, so request/response protocols keep working across the boundary.
- Sensors, alarms, and IoT devices that announce themselves or stream readings via UDP broadcast, while the monitoring application lives elsewhere (another site, a data centre, the cloud).
- Legacy industrial / building-automation equipment that only speaks LAN-local UDP and can't be reconfigured.
- Bridging a discovery or telemetry protocol from an isolated network segment to a central server.
Have a device that's stuck on the wrong side of the network? Allegro IT does exactly this kind of integration and legacy-system work — get in touch.
The relay runs two independent forwarding tasks so traffic flows both ways:
flowchart LR
subgraph LAN["Device LAN"]
Device["Broadcasting device<br/>(sensor / alarm / PLC)"]
end
subgraph Host["UDP Relay host<br/>(Console or Windows Service)"]
R(("UDP Relay"))
end
subgraph Remote["Remote network / cloud"]
Server["Receiving application<br/>(server)"]
end
Device -- "1 · broadcast → :55530" --> R
R -- "2 · forward → server :55550" --> Server
Server -- "3 · reply → :55540" --> R
R -- "4 · forward back → device :55520" --> Device
- The device broadcasts a UDP packet; the relay is listening on the client port.
- The relay forwards the packet to the configured remote server.
- The server replies; the relay is listening on the server port.
- The relay forwards the reply back to the device.
Each direction is just a localEndPoint → relayEndPoint pair, configured in XML — no recompiling to change addresses or ports.
| Project | Target framework | Role |
|---|---|---|
UDP_Relay_Core |
.NET Standard 2.0 | The reusable engine — relay logic, XML settings reader, pluggable logging, async cancellation. Usable from .NET Framework and modern .NET. |
UDP_Relay_Console |
.NET 8 / 9 / 10 | Cross-platform console host (Windows / Linux / macOS). |
UDP_Relay_Service |
.NET 10 (Worker Service) | Windows Service host (Microsoft.Extensions.Hosting) with Event Log integration and sc-based install scripts; also runs as a console for testing. |
TestSender |
.NET 8 / 9 / 10 | Test harness that simulates a broadcasting device. |
TestReceiver |
.NET 8 / 9 / 10 | Test harness that simulates the remote server (echoes replies). |
UDP_Relay_Core.Tests |
.NET 8 / 9 / 10 | xUnit test suite for the core engine (run with dotnet test). |
Run either the Console or the Service — both host the same core engine. Pick the Console for cross-platform or quick runs; pick the Service for an always-on Windows deployment.
- Bidirectional relaying built from composable one-way tasks.
- IPv4 and IPv6 support (address family is detected per endpoint).
- Cancellable async I/O —
UdpClient.ReceiveAsync()has no built-in cancellation, so the core adds aWithCancellationextension for clean, prompt shutdown. - Pluggable logging through
Microsoft.Extensions.Logging— attach anyILogger(console, rolling file, Windows Event Log, …). IDisposablethroughout for deterministic socket cleanup.
Prefer a prebuilt binary? Self-contained builds (no .NET install required) for Windows and Linux are attached to each release — download, edit the
Settings_*.xml, and run. To build from source instead, read on.
- .NET 10 SDK (for the Console, test harnesses and tests; the projects also target .NET 8 and 9).
- For the Windows Service: Windows with the .NET 10 runtime — or grab the self-contained build from Releases, which bundles the runtime.
git clone https://github.com/jackwjensen/UDP_Relay.git
cd UDP_Relay
dotnet build UDP_Relay.sln -c ReleaseEvery project is SDK-style, so
dotnet build UDP_Relay.slnbuilds the whole solution — including the .NET 10 Worker Service. The console and test apps are cross-platform; the Windows Service installs on Windows.
The Console multi-targets .NET 8/9/10, so pass -f to pick a runtime:
cd UDP_Relay_Console
dotnet run -c Release -f net10.0Edit Settings_UDP_Relay_Console.xml first (see Configuration). Press any key to stop relaying.
The Service is a .NET 10 Worker Service. Build or publish it, then from an elevated command prompt in the output folder use the included scripts (it can also run as a plain console with dotnet run --project UDP_Relay_Service for testing):
| Script | Action |
|---|---|
ServiceInstall.bat |
Register the service (sc create) |
ServiceStart.bat |
Start it (sc start) |
ServiceStop.bat |
Stop it (sc stop) |
ServiceUninstall.bat |
Remove it (sc delete) |
Settings live in Settings_UDP_Relay_Service.xml next to the executable. The service also writes to the Windows Application event log under source UDP_Relay_Service.
All endpoints are plain XML — change addresses and ports without rebuilding. The Console and Service share the same four-endpoint shape:
<UDP_Relay_Console>
<ListeningClientPort>55530</ListeningClientPort>
<ListeningClientIP>0.0.0.0</ListeningClientIP> <!-- listen for the device -->
<ListeningServerPort>55540</ListeningServerPort>
<ListeningServerIP>0.0.0.0</ListeningServerIP> <!-- listen for the server's reply -->
<SendingClientPort>55520</SendingClientPort>
<SendingClientIP>192.168.1.255</SendingClientIP> <!-- where the device expects the reply -->
<SendingServerPort>55550</SendingServerPort>
<SendingServerIP>192.168.1.255</SendingServerIP> <!-- the remote server's address -->
<TimeOut>0</TimeOut>
</UDP_Relay_Console>| Setting | Meaning |
|---|---|
ListeningClientIP / ListeningClientPort |
Interface and port the relay listens on for the device's packets. 0.0.0.0 = all interfaces. |
SendingServerIP / SendingServerPort |
Address the relay forwards device packets to — i.e. your remote server. |
ListeningServerIP / ListeningServerPort |
Interface and port the relay listens on for the server's reply. |
SendingClientIP / SendingClientPort |
Address the relay forwards the reply back to — i.e. the device. |
TimeOut |
Socket timeout in milliseconds; 0 means block indefinitely. |
Tip: the sample uses the broadcast address
192.168.1.255so replies reach any listener on the subnet. For a real cross-network setup, setSendingServerIPto your remote server's routable address (and adjust the subnet broadcast to match your LAN).
Three console apps let you prove the path end-to-end before wiring in real hardware:
- Configure and start
TestReceiver— stands in for your remote server; it echoes back whatever it receives. - Configure and start
UDP_Relay_Console— the relay itself. - Configure and start
TestSender— stands in for the broadcasting device; it sends 100 numbered packets and prints the replies it gets back.
With the default port layout, a packet travels TestSender → Relay → TestReceiver → Relay → TestSender. If TestSender prints the echoes, your relay path works. Adapt the settings files to mirror your real devices and servers.
The core engine is covered by an xUnit suite in UDP_Relay_Core.Tests — settings parsing, async cancellation, and a loopback relay round-trip — run across every target framework with:
dotnet testEvery push and pull request is built and tested on Windows via GitHub Actions.
Logging is injectable. The static Logger fans out to every ILogger you register via Logger.AddLogger(...), and can also mirror to the console (Logger.WriteToConsole — off by default so the library stays quiet when embedded; the console host and test harnesses enable it). Out of the box:
- Console (in the console host + test harnesses) and Debug output.
- Rolling file logs —
.logfiles in aLogs/folder (e.g.UDP_Relay_Console<date>.0.log) viaNetEscapades.Extensions.Logging.RollingFile. - Windows Event Log in the Service host.
Swap in Serilog, NLog, Application Insights, or anything else that exposes an ILogger — no changes to the relay core.
UDP_Relay_Core is a standalone .NET Standard 2.0 library, so you can embed the relay directly:
using System.Net;
using UDP_Relay_Core;
using var relay = new UDP_Relay();
// Forward device broadcasts (heard on :55530) to a remote server
relay.StartRelaying(
localEndPoint: new IPEndPoint(IPAddress.Any, 55530),
relayEndPoint: new IPEndPoint(IPAddress.Parse("203.0.113.10"), 55550));
// Relay the server's replies (heard on :55540) back to the device
relay.StartRelaying(
localEndPoint: new IPEndPoint(IPAddress.Any, 55540),
relayEndPoint: new IPEndPoint(IPAddress.Parse("192.168.1.255"), 55520));
// ... later ...
relay.StopRelaying();Send(...) and Receive(...) helpers are also available for one-off datagrams.
- Console & test apps: .NET 8, 9 or 10 (cross-platform; multi-targeted).
- Windows Service: Windows + .NET 10 (or a self-contained release build — no runtime needed).
- Core library: .NET Standard 2.0 — works with .NET Framework 4.6.1+ and .NET 8/9/10 (and .NET Core 2.0+).
Released under the MIT License. © 2023 Jack W. Jensen.
"International projektledelse med holdånd" — international project management with team spirit.
Allegro IT ApS is a Danish software consultancy specialising in project leadership, legacy-code maintenance, and cloud hosting. UDP Relay grew out of real integration work — connecting devices and systems that were never designed to talk to each other.
If you need to bridge protocols, modernise legacy systems, or get a stubborn piece of equipment talking to the cloud, we'd love to help.
- 🌐 Website: allegroit.dk
- ✉️ Contact: kontakt@allegroit.dk
- 📍 Randers, Denmark
If this project helped you, a ⭐ on the repo is appreciated — and tell us what you built with it.