Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ resolver = "3"

[dependencies]
axum = "0.8"
base64 = "0.22"
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "multipart", "json", "stream"] }
futures-util = { version = "0.3", default-features = false, features = ["std"] }
libloading = "0.8"
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ curl http://127.0.0.1:8080/dnsbl/zone
curl http://127.0.0.1:8080/gateway/demo?q=union%20select
```

Fetch a public HTTPS document through Wardnet's destination policy and pinned DNS:

```bash
curl -X POST http://127.0.0.1:8080/api/outbound/fetch \
-H 'content-type: application/json' \
-H 'x-admin-token: dev-secret' \
-d '{"url":"https://example.com/privacy","max_bytes":524288}'
```

The JSON response contains `status`, `content_type`, `final_url`, `body_base64`,
and `redirects`. Wardnet follows at most three HTTPS redirects, revalidates and
pins DNS at every hop, disables ambient proxies, accepts document content types,
and caps `max_bytes` at 8 MiB. A missing, malformed, or unsupported
`Content-Type` is rejected rather than inferred from bytes. Errors return stable
`code` and safe `error` fields. Security research grounding is recorded in
[`docs/research/outbound-egress-security.md`](docs/research/outbound-egress-security.md).

Add a blocking route:

```bash
Expand Down
34 changes: 34 additions & 0 deletions docs/research/outbound-egress-security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Outbound egress security research

Wardnet's fetch boundary follows two research-backed constraints: destination
authorization must cover resolved addresses, and the authorized address set must
remain bound to the subsequent connection. URL-string filtering alone does not
cover DNS rebinding or redirects.

Jackson et al. describe DNS rebinding as a firewall-circumvention technique and
evaluate policy-based pinning and hostname authorization as deployable defenses.
Wardnet therefore evaluates every resolved address, rejects denied address
classes, and gives each fetch hop a request-local DNS pin board so the HTTP
connection cannot perform a second, different resolution.

Jabiyev et al. show that SSRF defenses are bypassed when validation and the
actual network request are separated, including through changing DNS answers.
Wardnet keeps URL parsing, address-class policy, redirect validation, and the
connect-time address set inside one egress owner. Redirects are disabled in the
HTTP client and followed manually only after a new policy evaluation.

## References

Jackson, C., Barth, A., Bortz, A., Shao, W., & Boneh, D. (2009). Protecting
browsers from DNS rebinding attacks. *ACM Transactions on the Web, 3*(1), 1–26.
https://doi.org/10.1145/1462148.1462150. Author publication
page and manuscript: https://cs.stanford.edu/people/dabo/pubs/abstracts/dnsrebind.html

Jabiyev, B., Mirzaei, O., Kharraz, A., & Kirda, E. (2021). Preventing server-side
request forgery attacks. In *Proceedings of the 36th ACM/SIGAPP Symposium on
Applied Computing* (pp. 1626–1635).
https://doi.org/10.1145/3412841.3442036. Author-hosted manuscript:
https://theseclab.org/publications/sac21.pdf

The papers are linked rather than copied because redistribution rights for the
publisher versions were not established for this repository.
Loading
Loading