Building a Custom OOB Server
5 min read
If you're reading this, you've probably used Burp, and you're probably aware of Burp Collaborator, the out of band detection feature. Basically, it gives you a (sub)domain name and tells you if there has been a DNS/HTTP/STMP lookup/request for it. This allows you to test for blind command injections, blind xss, SSRFs etc. Now, the problem is, if you use Burp's built in collaborator server, you'll lose your ability to see interactions if you close Burp. There are some workarounds for this, but they're mostly cumbersome. Alternatively, I'll just use the web version of interactsh for quick testing.
These all have a lot of drawbacks, though. Chiefly is that egress from internal networks often blocks traffic related to these beacons. So, you could be getting an interaction, but you have no idea. And that means lost money, and in the case of the interactions we are testing for, they're usual High or Critical-risk vulns we get paid well for.
But also, if you're using a third-party service, you're exporting some very sensitive information to a third-party if you discover a vulnerability. A site like XSS Report will now have access to all your bXSS interaction including URLs, cookies, DOM, etc. That is not a good thing.
There is also limited customization, which is a must for long-term persistence, testing, and engagements.
What Do I Do?
I roll my own OOB server. This allows me to bypass egress filters, create specific client IDs and test IDs to identify the exact spot an injection succeeded on a mass scale. My server supports DNS lookups, HTTP(S) requests, and blind XSS. But not only that. I've also set it up to serve files and monitor remote (JS mostly) files for changes. Additionally, I've setup a second network interface on the device that I use for a proxy, and I rotate the IP of the interface via an automated script on a regular basis.
The backend server(s) is/are written in Golang. The frontend, which I run locally, is React. There is a bit of setup e.g. setting up your own server to be the authoritative name server for your test domain, but the end result is very impressive. It enables seamless testing and POC hosting and allows me to track interactions on a long-term basis. I've received callbacks months later and then not remembered where they were from. This fixes that.
Rolling Your Own: The General Blueprint
You don't need to reverse-engineer my exact stack to get most of the value here. The core idea is simple: you own a domain, you point it at a box you control, and that box listens for anything that touches it. Here's the shape of it.
1. Get a domain you're comfortable burning. Use a throwaway-ish domain that isn't tied to your real identity or brand. OOB payloads end up pasted into bug reports, logs, and third-party WAFs, so don't use a domain you care about being associated with. Cheap .xyz/.com registrations are fine.
2. Stand up a small, always-on server. This is the part that matters most: it has to run 24/7. The whole point of self-hosting is catching the callback that lands at 3am three weeks after you injected the payload. A laptop or a box you turn off defeats the purpose. A cheap cloud VPS is the right tool - I use Linode.
3. Make your server the authoritative name server for the domain. This is the step that trips people up. At your registrar, set the domain's NS records to point at your server (e.g. ns1.yourdomain.com / ns2.yourdomain.com) and create the matching glue records. Now your box sees every DNS lookup for the domain and any subdomain which is what lets you detect blind DNS/SSRF interactions and encode data into subdomain labels.
4. Run listeners for each protocol you care about:
- DNS — a small authoritative resolver that logs every query (source IP, full queried name, timestamp) and answers with your server's IP.
- HTTP + HTTPS — a web listener that logs the full request (method, path, headers, body, source IP) and can also serve files for POC hosting and blind-XSS payloads.
- Blind XSS — really just an HTTP endpoint that collects the goodies (DOM, cookies, URL, screenshots) when your injected JS fires in someone else's browser.
5. Get real TLS. Use Let's Encrypt with a DNS-01 challenge (wildcard *.yourdomain.com) so HTTPS callbacks and browser-based bXSS payloads don't get blocked or throw cert warnings. Automate the renewal — expired certs are silent failures. Automate the renewal of this cert or some callbacks mail fail down the road.
6. Tag everything with client IDs and test IDs. Bake a unique identifier into each payload's subdomain or path (c1-t42.yourdomain.com). When a callback lands months later, that tag tells you exactly which target, which parameter, and which injection point fired. Without it, a stale interaction is just noise.
Nice-to-haves once the basics work
- A separate interface + IP rotation for your proxy traffic, so egress and callbacks aren't trivially correlated or blocked as a block.
- Remote file monitoring — watch a target's JS files for changes and diff them over time.
- A local dashboard — I run a React frontend locally against the server so nothing sensitive lives on the public box longer than it has to.
- Retention + search — keep interactions long-term and make them searchable by client/test ID. This is the single biggest quality-of-life win.
A note on the server: why Linode
You want something cheap, stable, and permanently online, with a static IP and full control over DNS and firewall rules. A basic VPS is plenty — you're not doing heavy compute, you're mostly sitting there listening. Their entry-level shared plan (currently around $5/mo) comfortably runs the DNS and HTTP(S) listeners for this setup, and I've had boxes up for years without babysitting them.
I use and recommend Linode for the always-on box. If you want to try it, you can use my referral link below - new accounts get a credit to start, and it helps support the blog:
Anyway, here are some screenshots of an older version of my setup.




