Add destination domain ACL rules
This commit is contained in:
1 parent
a33549e81a
commit
467624b747
5 files changed
+450
-24
No files matched your search
@@ -8,7 +8,7 @@ Hermes is a minimal HTTP/1.1 forward proxy written in Rust. It supports streamin
|
||||
- HTTPS and arbitrary TCP tunneling with `CONNECT host:port`
|
||||
- Streaming request and response bodies
|
||||
- Upstream connection pooling and configurable timeouts
|
||||
- Ordered allow/deny ACLs using Basic authentication and/or client IP networks
|
||||
- Ordered allow/deny ACLs using Basic authentication, client IP networks, and destination domains
|
||||
- Fast salted SHA-256 password hashes; plaintext passwords are never stored in YAML
|
||||
- Removal of standard and `Connection`-nominated hop-by-hop headers
|
||||
- W3C Trace Context extraction and injection for plain HTTP traffic
|
||||
@@ -57,6 +57,10 @@ acl:
|
||||
- name: office-network
|
||||
action: allow
|
||||
networks: ["10.20.0.0/16", "2001:db8:20::/48"]
|
||||
|
||||
- name: approved-domains
|
||||
action: allow
|
||||
domains: ["docs.example.com", "example.org", "*.rust-lang.org"]
|
||||
```
|
||||
|
||||
| Field | Default | Description |
|
||||
@@ -68,22 +72,61 @@ acl:
|
||||
| `acl.users` | empty | Usernames and salted SHA-256 password hashes |
|
||||
| `acl.rules` | empty | Ordered ACL rules |
|
||||
|
||||
Configuration is loaded and validated at startup. Unknown fields, invalid CIDRs, duplicate or empty rules, references to unknown users, and unsupported password hashes prevent startup. Restart Hermes to apply configuration changes.
|
||||
Configuration is loaded and validated at startup. Unknown fields, invalid CIDRs or domain patterns, duplicate or empty rules, references to unknown users, and unsupported password hashes prevent startup. Restart Hermes to apply configuration changes.
|
||||
|
||||
`RUST_LOG` controls log filtering and defaults to `info`, for example `RUST_LOG=hermes=debug`.
|
||||
|
||||
### ACL rules
|
||||
|
||||
- Rules are evaluated in order; the **first match wins**.
|
||||
- Separate user and network rules provide Basic-auth OR IP-address authorization.
|
||||
- If a rule contains both `users` and `networks`, both selectors must match. Entries within each selector are ORed.
|
||||
- Separate user, network, and domain rules provide Basic-auth, source-IP, or destination-domain authorization.
|
||||
- If a rule contains multiple selector types, every specified selector must match. Entries within each selector are ORed.
|
||||
- A rule must contain at least one selector; accidental match-all rules are rejected.
|
||||
- IP matching uses the actual TCP peer address. `X-Forwarded-For` is never trusted.
|
||||
- `networks` uses the actual client TCP peer address. `X-Forwarded-For` is never trusted.
|
||||
- `domains` uses the request-target authority, never the downstream `Host` header, and works for both HTTP and `CONNECT`.
|
||||
- Requests without required credentials receive `407 Proxy Authentication Required` and a Basic `Proxy-Authenticate` challenge.
|
||||
- Invalid credentials receive 407; authenticated or IP-identified clients denied by policy receive 403.
|
||||
- Invalid credentials receive 407; clients denied by policy receive 403.
|
||||
- ACLs are enforced before upstream HTTP requests or `CONNECT` connections are made.
|
||||
- `Proxy-Authorization` is consumed by Hermes and is never forwarded upstream.
|
||||
|
||||
### Destination domains
|
||||
|
||||
Domain entries support exact names and leading-subdomain wildcards:
|
||||
|
||||
- `example.com` matches only that name.
|
||||
- `*.example.com` matches `www.example.com` and `a.b.example.com`, but not the apex `example.com` or a lookalike such as `evil-example.com`.
|
||||
- Matching is case-insensitive, ignores ports, and normalizes one trailing DNS root dot.
|
||||
- Single-label names such as `localhost` are supported. International domains must use ASCII/punycode form.
|
||||
- IP literals never match domain patterns.
|
||||
|
||||
A domain whitelist uses `default_action: deny` with allow rules:
|
||||
|
||||
```yaml
|
||||
acl:
|
||||
default_action: deny
|
||||
rules:
|
||||
- name: approved-domains
|
||||
action: allow
|
||||
domains: ["example.com", "*.rust-lang.org"]
|
||||
```
|
||||
|
||||
A domain blacklist uses deny rules, typically with `default_action: allow`:
|
||||
|
||||
```yaml
|
||||
acl:
|
||||
default_action: allow
|
||||
rules:
|
||||
- name: blocked-domains
|
||||
action: deny
|
||||
domains: ["ads.example.net", "*.tracker.example"]
|
||||
```
|
||||
|
||||
Domain selectors can be combined with `users` and/or `networks` when client and destination restrictions must both apply. A domain-only allow rule does not implicitly require authentication.
|
||||
|
||||
**Domain matching is not destination-IP filtering.** A hostname blacklist can be bypassed by connecting directly to an IP address. Hermes also does not inspect resolved addresses or provide DNS-rebinding protection. A domain-only whitelist with `default_action: deny` rejects IP-literal destinations unless another rule allows them.
|
||||
|
||||
### Basic authentication
|
||||
|
||||
For Basic authentication, curl can supply proxy credentials with `--proxy-user`:
|
||||
|
||||
```sh
|
||||
|
||||
Reference in new issue
Block a user