requestrepo: a self-hosted HTTP, DNS and SMTP out-of-band listener
Analyze HTTP, DNS and SMTP requests and create custom responses and DNS records for your subdomain
At a glance
- What is it?
- requestrepo is a Rust service that captures inbound HTTP, DNS and SMTP requests on domains you control, serves custom responses and DNS records per subdomain, and streams them live over WebSocket. It replaces the hosted out-of-band interaction services that security testers otherwise depend on, and issues its own TLS certificates.
- Who is it for?
- requestrepo suits a security tester who needs out-of-band interaction for blind vulnerabilities and does not want to send traffic through a third party service, since it listens on all three protocols, mints its own certificates and keeps everything on infrastructure you control. It is the wrong tool if you need a hosted service with guaranteed availability from a target's network, and it is the wrong tool if you cannot delegate a DNS zone or serve on port 25.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 29 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What out-of-band interaction is for
requestrepo is described as a tool for analyzing HTTP, DNS and SMTP requests with custom DNS records and response files, and the homepage is requestrepo.com.
The problem it addresses is a class of vulnerability that cannot be seen directly. When an application fetches a URL that the attacker controls, or resolves a hostname, or sends mail, the response comes back over a channel the attacker can watch. That channel is called out-of-band, and it is how blind server-side request forgery, blind SQL injection, XXE with an external entity and a range of other bugs become visible. The attacker needs somewhere for the target to talk to, and somewhere to see what came back.
The hosted services that provide this, the ones whose names appear in the repository's topic list, do exactly that job and have the obvious property that everything the target sends passes through a third party's servers. For an engagement where that traffic carries a session cookie, a token or a piece of internal data, that is a disclosure you may not be able to justify. Running the listener yourself removes that question entirely.
The repository's topic list also names burp-collaborator. The difference in approach is that requestrepo is the server, and you point the scanner's collaborator server setting at it, rather than being a plugin that talks to someone else's server.
The primary language is Rust, the licence is MIT, and the last push to the repository was on 2026-09-23.
One process serving four protocols
The features list describes a single service that speaks several protocols. Requests are captured in real time across HTTP, DNS and SMTP, custom DNS records of type A, AAAA, CNAME and TXT can be created for a subdomain, custom HTTP responses with headers and body can be defined, and updates are streamed live over WebSocket.
The TLS story is the part that removes most of the friction. Certificates are obtained automatically through Let's Encrypt, using the DNS-01 challenge for domains and HTTP-01 for IP addresses. The DNS-01 challenge is the one that matters here, because it does not require an inbound HTTP request to the domain being certified, so a service whose whole purpose is to receive unexpected connections can still get a valid certificate for a hostname that nothing points at in the usual way.
There is also an IP certificate path, enabled with IP_CERT_ENABLED, with its own check interval and renewal threshold, and the certificate management code lives in its own module in the source tree. The cache/ directory holds an in-memory LRU cache, and the features list is explicit that no external dependencies are needed, no Redis required. The architecture diagram confirms the shape of the Rust backend:
βββ src/ # Rust backend
β βββ cache/ # In-memory LRU cache
β βββ certs/ # TLS/ACME certificate management
β βββ dns/ # DNS server
β βββ http/ # HTTP/HTTPS server + REST API
β βββ smtp/ # SMTP server
β βββ utils/ # JWT, config, helpersThe frontend is a React application with components, pages, Zustand stores and hooks, built with Vite. Both halves are served from the same container in the Docker image, which is why the Dockerfile has a separate stage for the frontend build.
Running it with Docker
The quick start is a single docker run invocation:
docker run -d \
--name requestrepo \
-p 80:80 -p 443:443 -p 53:53/udp -p 53:53/tcp -p 25:25 \
-e JWT_SECRET=your-secret-key-min-32-chars \
-e DOMAIN=yourdomain.com \
-e SERVER_IP=your.server.ip \
-e TLS_ENABLED=true \
-e [email protected] \
-v requestrepo-certs:/app/certs \
ghcr.io/adrgs/requestrepo:latestFive ports are published, HTTP on 80, HTTPS on 443, DNS on both UDP and TCP 53, and SMTP on 25. The certificate directory is a named volume so the certificates survive container replacement.
The compose file is the route for a longer-lived deployment. It pulls the image from GitHub Container Registry rather than building locally, and it sets a file descriptor limit that is worth reading:
ulimits:
nofile:
soft: 65536
hard: 65536The comment above it explains why. The default soft RLIMIT_NOFILE of 1024 is exhausted quickly because requestrepo is internet-facing and every scanner probe, DNS query and TLS session needs a descriptor. Once accept() starts returning EMFILE the server cannot recover on its own, so the limit is raised rather than relying on the daemon default. That is a real operational detail about running a service whose entire purpose is to be scanned.
The compose file also merges a docker-compose.override.yml automatically when present, which is how the local build path works without a second command.
Building from source with make
For development the README asks for Rust 1.75 or newer, Bun 1.0 or newer, and optionally Docker for deployment. The frontend is a React and Vite application, and the backend is Rust.
The build commands are make targets:
# Start backend (Rust)
make start-backend
# Start frontend (React/Vite)
make start-frontendand installation is a single target, make install, which the command table describes as installing all dependencies and git hooks.
Looking at the Makefile shows what that means concretely. The install target depends on install-deps and install-hooks. install-deps builds the Rust backend with cargo build --release in the src directory and runs bun install in the frontend directory. install-hooks writes pre-commit and pre-push scripts into.git/hooks with shell echo redirection and makes them executable. Those hooks then call the format, lint and test targets, so a pre-push runs all three.
The command table lists the full set: make install, make start-backend, make start-frontend, make build for a release build of the Rust backend, make test to run all tests, make lint running clippy and eslint together, make format using rustfmt and prettier, and the docker-build, docker-up and docker-down targets.
The test target is split into test-backend and test-frontend, and the backend test runs with a JWT_SECRET injected, which tells you the JWT secret is required at runtime and that the test harness supplies its own.
The configuration surface, and the knobs that matter
The .env.example file is the practical reference, and it is well commented. Three variables are required: JWT_SECRET with a minimum of 32 characters, DOMAIN as the base domain, and SERVER_IP as the public IP to return in DNS answers. SERVER_IPV6 is optional and the comment is precise about the behaviour, with the address returned for AAAA queries with no user-defined record and an empty value keeping the zone IPv4-only.
The rest falls into groups. Ports, with HTTP_PORT, HTTPS_PORT, DNS_PORT and SMTP_PORT defaulting to 80, 443, 53 and 25. TLS, with TLS_ENABLED defaulting to false, ACME_EMAIL, and the compose file adding ACME_DIRECTORY, CERT_DIR, CERT_RENEWAL_DAYS and CERT_CHECK_HOURS. Rate limiting, with SESSION_RATE_LIMIT at 10 sessions per IP per window and SESSION_RATE_WINDOW_SECS at 60. Size limits, MAX_SUBDOMAIN_SIZE_MB and MAX_REQUEST_BODY_MB both at 10, and CACHE_MAX_MEMORY_PCT at 0.7, described as the maximum cache memory as a percentage of the container limit.
Two defaults deserve attention because they are named for what they disable. DANGEROUSLY_ALLOW_SAME_ORIGIN_USER_CONTENT enables the /r/ subdomain user content on the dashboard origin, for domainless or IP deployments, and DANGEROUSLY_ALLOW_ALL_HEADERS allows origin-scoped headers such as Service-Worker-Allowed and Alt-Svc on the /r/ routes. Both default to false. The naming convention is a reasonable signal that a maintainer expects these to be turned on deliberately.
The subdomain configuration is what makes the tool usable in a multi-tenant way: SUBDOMAIN_LENGTH at 8, and SUBDOMAIN_ALPHABET set to lowercase letters and digits, with INCLUDE_SERVER_DOMAIN controlling whether the server domain is included in generated subdomains. A default TXT record is set to Hello!, which is the record a resolver will see for names with no user-defined entry.
IP geolocation is handled by a separate module, the ip2country directory, using the DB-IP country database, which the Dockerfile downloads at build time with a fallback that disables the feature rather than failing the build.
Where requestrepo is the wrong choice
Three limits are structural. The first is that out-of-band interaction only works if the target can reach you, and reachability is per protocol. A target that can make HTTP requests will not necessarily resolve your DNS zone or connect to port 25 on your server, and egress rules that permit one do not permit the others. The README's own note that reverse-proxy setups need the Host header preserved and WebSocket support enabled for /api/v2/ws points at the same fragility from the other direction.
The second is the operational surface. Listening on ports 80, 443, 53 and 25 means you are running a mail server and a DNS server as well as a web server, which means you need a real domain with a delegated zone, a server reachable on those ports, and either a public IP or a reverse proxy in front. The DNS setup section shows the two shapes, dedicating an entire domain to the tool with NS and A records, or running it on a subdomain, and the subdomain case is the one that needs the proxy care.
The third is that this is a listener, not a scanner. requestrepo does not find vulnerabilities, it receives what a target sends. If the goal is discovering blind SSRF by itself, you still need something to make the target issue requests.
The comparison with a hosted interaction service is the real one, and the difference in approach is ownership rather than capability. A hosted service gives you a guaranteed public address, existing TLS, a maintained web interface and no server to run, at the cost of the target's outbound traffic passing through infrastructure you do not control and cannot audit. requestrepo gives you the same feature set on your own machine, with the cost being the DNS delegation, the certificate lifecycle, the firewall rules and the fact that a scanner probing your listener will find it.
The code itself is MIT licensed, with LICENSE.md and SECURITY.md at the root, so the audit question is a reading exercise rather than a legal one, but a security review of a Rust service handling untrusted input on four ports is still a real task rather than a formality.
Editorial conclusion
requestrepo suits a security tester who needs out-of-band interaction for blind vulnerabilities and does not want to send traffic through a third party service, since it listens on all three protocols, mints its own certificates and keeps everything on infrastructure you control. It is the wrong tool if you need a hosted service with guaranteed availability from a target's network, and it is the wrong tool if you cannot delegate a DNS zone or serve on port 25. Verify first whether your target's outbound rules permit DNS and SMTP as well as HTTP, and note that the Docker image is built on rust:1.88 and bun 1.2 with a Debian bookworm runtime, the last push was on 2026-09-23, and there are no GitHub releases.
Frequently asked questions
What is requestrepo and what does it capture?
It is a Rust service for analyzing HTTP, DNS and SMTP requests with custom DNS records and response files, capturing all three protocols in real time and streaming updates to the dashboard over WebSocket. It is aimed at out-of-band interaction during security testing.
How do I run requestrepo with Docker?
Run the docker run command from the README, publishing ports 80, 443, 53 over UDP and TCP and 25, and setting JWT_SECRET, DOMAIN, SERVER_IP, TLS_ENABLED and ACME_EMAIL. The image is ghcr.io/adrgs/requestrepo:latest, and the compose file is the longer-lived alternative.
Which environment variables does requestrepo require?
Three are required: JWT_SECRET with a minimum of 32 characters, DOMAIN for the base domain and SERVER_IP for the public IP returned in DNS answers. SERVER_IPV6 is optional, and the .env.example file documents the full set of ports, TLS, rate limiting and cache options.
How does requestrepo handle TLS certificates?
Certificates are obtained automatically via Let's Encrypt, using DNS-01 for domains and HTTP-01 for IP addresses. There is a separate IP certificate path enabled with IP_CERT_ENABLED, with configurable check and renewal intervals, and the certificate volume is mounted at /app/certs.
Do I need an external cache or database for requestrepo?
No. The features list states there are no external dependencies, with an in-memory cache using LRU eviction and no Redis required. The only external data file is the DB-IP country database used for IP geolocation, which the Dockerfile downloads at build time and which falls back to disabling that feature if the download fails.
How do I build requestrepo from source?
Install Rust 1.75 or newer and Bun 1.0 or newer, then run make install to install dependencies and git hooks. Use make start-backend for the Rust server and make start-frontend for the React and Vite frontend, and make test to run both test suites.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/adrgs-requestrepo)Was this useful?