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
18 changes: 11 additions & 7 deletions crates/server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,17 @@ pub struct ServerConfig {
/// `true` only for local development / compose stacks.
#[serde(default)]
pub allow_insecure_defaults: bool,
/// Extra `Host` names (an optional `:port` is ignored) under which the
/// server is legitimately reached, besides the host of
/// [`Self::public_base_url`]. Only consulted for the trusted-header
/// realms: a request whose `Host` matches neither is not named by the
/// headers of the proxy in front (a DNS-rebinding page in an internal
/// user's browser presents its own host name). Add the names a reverse
/// proxy rewrites `Host` to, or that internal clients use. Default empty.
/// Extra `Host` names (an optional `:port` is ignored) under which
/// clients reach the server, besides the host of
/// [`Self::public_base_url`], such as a name internal clients use. Only
/// consulted for the trusted-header realms: a request whose `Host`
/// matches neither is not named by the headers of the proxy in front (a
/// DNS-rebinding page in an internal user's browser presents its own host
/// name). The guard needs the client's own `Host`, so the reverse proxy
/// must forward it (nginx: `proxy_set_header Host $host`). Never add a
/// name the proxy rewrites `Host` to (`forge` for `proxy_pass
/// http://forge:8421`): every request then names an allowed host, and
/// the guard is off. Default empty.
#[serde(default)]
pub allowed_hosts: Vec<String>,
/// Seconds a client may take to send a request's headers before the
Expand Down
6 changes: 6 additions & 0 deletions docs/changes/2.2.0/583.docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The comment on `server.allowed_hosts` in `forge.toml.example` advised adding
the name a reverse proxy rewrites `Host` to. That turns off the
trusted-header realms' DNS-rebinding guard, since every request then names an
allowed host. The comment and the deployment guide now say that the proxy
must forward the client's own `Host`, and that such a name must never be
listed.
6 changes: 5 additions & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,11 @@ What Forge believes, and when:
`auth.trusted_proxy_cidrs` and the request's `Host` is one of Forge's own
names (the host of `public_base_url`, or one in `server.allowed_hosts`: a
DNS-rebinding page reaches the proxy under its own name). From any other
request they are ignored.
request they are ignored. This guard holds only while the proxy forwards
the client's own `Host`: never list the name a proxy rewrites `Host` to
(`forge` for an nginx `proxy_pass http://forge:8421` without
`proxy_set_header Host $host`) in `server.allowed_hosts`, since every
request would then name an allowed host.
- They name the caller only when the request has **no credential of its
own**: an API token, a password or a signed-in session is that
credential's, whatever the headers say, and one that is refused is a 401,
Expand Down
10 changes: 7 additions & 3 deletions forge.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ allow_insecure_defaults = true # (default: false)
# It also caps the upload limit a repository may be given. Set below 1 GiB, it
# lowers the docker defaults (upload limit, docker.max_blob_bytes) to fit.
# Host names (port ignored) clients reach this server under besides the host of
# public_base_url, e.g. the name a reverse proxy rewrites Host to. Only gates
# the trusted-header realms (Admin → Authentication): a request naming any
# other host is not named by the proxy's headers (DNS-rebinding guard).
# public_base_url, e.g. a name internal clients use. Only gates the
# trusted-header realms (Admin → Authentication): a request naming any other
# host is not named by the proxy's headers (DNS-rebinding guard). The guard
# needs the client's own Host: the reverse proxy must forward it (nginx:
# proxy_set_header Host $host). Never add a name the proxy rewrites Host to
# ("forge" for proxy_pass http://forge:8421): every request then names an
# allowed host, and the guard is off.
allowed_hosts = [] # (default: [])
# Connection and request time limits. A client that takes longer to send its
# request headers, or whose request body stalls longer, is cut off; a handler
Expand Down
Loading