HALRAD Research

Firebug — stop rewriting the same firewall code

Every time I drop a small HTTP server inside a Windows app — a plugin that streams to a Chromecast, a REST endpoint for a companion phone app, a LAN dashboard — I hit the same two chores. Pick a port that isn't already taken. Then convince Windows to let a non-admin process actually serve on it: a URL-ACL reservation and a firewall rule, both keyed to that exact port, both behind a UAC prompt.

It's not hard. It's just fiddly, easy to get subtly wrong, and I'd written it four times — an MBCCRules.exe here, a firewall-utility there, a FirewallManager copy-pasted into two more projects. Four implementations of the same thing, each with its own bugs.

Firebug is those four collapsed into one. Two jobs, done right:

No dependencies beyond the .NET base library. It multi-targets net48 and net8.0, so it drops into a legacy plugin and a modern service alike. There's a library, plus a self-elevating firebug.exe if you'd rather stay out of process:

firebug add --name "My App" --port 8000 --urlacl firebug check --name "My App" --port 8000 firebug remove --name "My App" --port 8000

The port doesn't need to be fixed

One insight worth stating, because it trips people up: for a media server, the port doesn't need to be a fixed, well-known number. The device you're streaming to is told the full URL — host and port — and just fetches it. So the port is your business, not the user's. Pick whatever's free, persist it, and stop asking people to edit config.

// reuse the saved port if it's still free, else ladder up from 8000 int port = PortPicker.Resolve(settings.Port, preferred: 8000); settings.Port = port; // persist it fb.AddUrlAcl(port); // non-admin may now bind a LAN prefix fb.AddTcpInboundRule("My App", port); // peers on the LAN can reach it

Built to be shared

I pulled it into its own repo because the whole point is that nobody should write this a fifth time. It's Apache-2.0. Bind the DLL, grab the NuGet package, or copy the two files into your project and change the namespace — federation over dependency, your call.

Small library, boring job, done once. That's the pitch.