paivana

HTTP paywall reverse proxy
Log | Files | Refs | Submodules | README | LICENSE

commit bc3e31a173fd251b3348b99951afc3e91cc967ce
parent f81de57d9b83cf5705672b4dae247ce3eb44d183
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  6 Aug 2026 18:00:42 +0200

make BASE_URL mandatory if '-f' is not given

Diffstat:
MREADME | 13++++++++++---
Msrc/backend/paivana-httpd.c | 29+++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/README b/README @@ -78,6 +78,7 @@ Paivana reads an INI-style `.conf` file. The only section used is DESTINATION_BASE_URL = https://example.com/ MERCHANT_BACKEND_URL = https://backend.demo.taler.net/instances/sandbox/ MERCHANT_ACCESS_TOKEN = secret-token:sandbox + BASE_URL = http://localhost:9967/ SERVE = tcp PORT = 9967 @@ -88,13 +89,14 @@ Paivana reads an INI-style `.conf` file. The only section used is DESTINATION_BASE_URL Upstream server to proxy to once payment is confirmed. MERCHANT_BACKEND_URL Base URL of the Taler merchant backend. MERCHANT_ACCESS_TOKEN Bearer token for all calls to the merchant backend. + BASE_URL Public base URL of Paivana. Required unless `-f` + is given, in which case it is derived from the + forwarding headers (see below). ### Optional keys Key Description -------- --------------------------------------------------------------- - BASE_URL Public base URL of Paivana. Derived from request headers - (X-Forwarded-Host / Host / X-Forwarded-Port) if absent. SECRET Stable secret for cookie MAC and Paivana ID derivation. A random nonce is generated on every startup if absent. WHITELIST POSIX extended regular expression; matching request paths @@ -242,7 +244,12 @@ Put IPv4 proxies in `TRUSTED_PROXIES`, not in `TRUSTED_PROXIES6` as matching, so a mapped entry would never be hit. Set `BASE_URL` in the configuration file to the public HTTPS URL so -that redirects and cookie domains are correct. +that redirects and cookie domains are correct. It may be omitted only +when `-f` is given: the flag asserts that a reverse proxy in front of +Paivana has already enforced a correct `Host`, which is what makes it +safe to reconstruct our own URL from the request. Without `-f` the +client is assumed to have connected directly, `Host` is whatever it +chose to send, and `BASE_URL` is therefore mandatory. Source layout diff --git a/src/backend/paivana-httpd.c b/src/backend/paivana-httpd.c @@ -474,6 +474,35 @@ run (void *cls, "BASE_URL", &PH_base_url)) { + /* Without BASE_URL we reconstruct our own URL from the request, and + the only thing that makes that safe is a reverse proxy in front + of us that enforced a correct Host: -- which is exactly what -f + asserts. Talking to clients directly, Host: is whatever the + client typed, and it decides both the string the access cookie is + keyed on and the string the templates' website_regex is matched + against: a client sending "Host: anything.invalid" would match no + template and be served for free. The scheme has the same + problem in reverse: direct connections have no X-Forwarded-Proto + to consult, so a site reached over https would generate http:// + URLs and again match no template. */ + if ( (! PH_respect_forwarded_headers) && + (! PH_no_check) ) + { + /* -n has no paywall, hence no access decision that the site's + own identity could be got wrong for; the base URL is then only + cosmetic and the "pure reverse proxy" mode stays configurable + with nothing but DESTINATION_BASE_URL. */ + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "paivana", + "BASE_URL"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "BASE_URL is required unless -f is given: without a" + " reverse proxy vouching for it, the client's Host" + " header cannot be used to identify this site\n"); + PH_global_ret = EXIT_NOTCONFIGURED; + GNUNET_SCHEDULER_shutdown (); + return; + } GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, "paivana", "BASE_URL");