paivana-httpd.h (12113B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2026 Taler Systems SA 4 5 Paivana is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Affero General Public License 7 as published by the Free Software Foundation; either version 8 3, or (at your option) any later version. 9 10 Paivana is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty 12 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 the GNU Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public 16 License along with Paivana; see the file COPYING. If not, 17 write to the Free Software Foundation, Inc., 51 Franklin 18 Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 /** 22 * @author Christian Grothoff 23 * @file paivana-httpd.h 24 * @brief globals for the HTTPD reverse proxy 25 */ 26 #ifndef PAIVANA_HTTPD_H 27 #define PAIVANA_HTTPD_H 28 29 #include <regex.h> 30 #include <stdbool.h> 31 32 /** 33 * The de-facto forwarding headers. libmicrohttpd only defines the 34 * standardized #MHD_HTTP_HEADER_FORWARDED (RFC 7239), but these are 35 * what nginx, Apache and everything else in front of us actually 36 * emit. They are consumed on the way in (client address, base URL) 37 * and produced on the way out (proxying), in different files, so 38 * they are spelled out once here. 39 */ 40 #define PH_HEADER_X_FORWARDED_FOR "X-Forwarded-For" 41 #define PH_HEADER_X_FORWARDED_PROTO "X-Forwarded-Proto" 42 #define PH_HEADER_X_FORWARDED_HOST "X-Forwarded-Host" 43 #define PH_HEADER_X_FORWARDED_PORT "X-Forwarded-Port" 44 45 /** 46 * Longest URL we are willing to run a regular expression over. 47 * 48 * Both the WHITELIST expression and the ones from the merchant's 49 * templates are matched against client-controlled URLs on the 50 * pre-payment path, and neither is validated beyond regcomp(3) 51 * succeeding. A careless expression can exhibit catastrophic 52 * backtracking, whose cost then grows super-linearly in the length of 53 * the subject; capping the subject length bounds that cost. 16 kb is 54 * far above any legitimate URL and at (or above) the request line 55 * limit of the usual front-end servers. 56 */ 57 #define PH_MAX_URL_LENGTH (16 * 1024) 58 59 #define PAIVANA_LOG_INFO(...) \ 60 GNUNET_log (GNUNET_ERROR_TYPE_INFO, __VA_ARGS__) 61 #define PAIVANA_LOG_DEBUG(...) \ 62 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) 63 #define PAIVANA_LOG_WARNING(...) \ 64 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, __VA_ARGS__) 65 #define PAIVANA_LOG_ERROR(...) \ 66 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__) 67 68 /** 69 * Destination to which HTTP server we forward requests to. 70 * Of the format "http://servername:PORT" 71 */ 72 extern char *PH_target_server_base_url; 73 74 /** 75 * Replace the connection to target server. 76 * File path to the unix socket 77 */ 78 extern char *PH_target_server_unixpath; 79 80 /** 81 * Public merchant backend base URL advertised to browsers and wallets. 82 */ 83 extern char *PH_merchant_base_url; 84 85 /** 86 * Merchant backend base URL used for Paivana's private API requests. 87 * Defaults to a copy of #PH_merchant_base_url. 88 */ 89 extern char *PH_merchant_internal_url; 90 91 /** 92 * Optional Unix socket used to reach the merchant backend. Kept so the 93 * forced-fresh transport diagnostic follows the same route as the regular 94 * merchant client. 95 */ 96 extern char *PH_merchant_unixpath; 97 98 /** 99 * Base URL of this site as seen by the client. If not set, 100 * we will try to determine it from "X-Forwarded-Host" and 101 * "Host" and "X-Forwarded-Port" headers. 102 */ 103 extern char *PH_base_url; 104 105 /** 106 * Curl context for talking to the merchant backend. Carries the 107 * `Authorization: Bearer $MERCHANT_ACCESS_TOKEN` header on every 108 * request, so it must never be used for anything but the backend. 109 * NULL in `-n` (no payment) mode, where there is no backend. 110 */ 111 extern struct GNUNET_CURL_Context *PH_merchant_ctx; 112 113 /** 114 * Curl context for forwarding client requests to the origin server. 115 * Deliberately separate from #PH_merchant_ctx: headers appended to a 116 * context apply to every request made through it, and our credentials 117 * for the merchant backend have no business being sent to the site we 118 * proxy for. 119 */ 120 extern struct GNUNET_CURL_Context *PH_proxy_ctx; 121 122 /** 123 * Pre-compiled regular expression for sites that are whitelisted 124 * and never paywalled. 125 */ 126 extern regex_t PH_whitelist_ex; 127 128 /** 129 * True if whitelist_ex was set. 130 */ 131 extern bool PH_have_whitelist_ex; 132 133 /** 134 * Set to true if the cookie applies globally to all sites 135 * and not per-page. 136 */ 137 extern int PH_global_cookie; 138 139 /** 140 * Disable paywall check. 141 */ 142 extern int PH_no_check; 143 144 /** 145 * If set, we are behind a reverse proxy: the socket peer is a proxy we 146 * trust, and the forwarding headers ("Forwarded" and the "X-Forwarded-*" 147 * family) are read to recover what the client actually did. Unset, no 148 * forwarding header is consulted at all and the peer *is* the client. 149 * Only enable it when the server in front writes those headers itself, 150 * either setting them or appending to them. Appending is enough -- 151 * what it appends is the address it accepted the request from, so the 152 * element we read is still one it vouches for. What is not safe is a 153 * front server that passes the client's own headers through unchanged, 154 * which leaves the client writing the element we believe. 155 * 156 * This flag alone extends trust exactly one hop, to the peer, so with 157 * no #PH_trusted_proxies4 / #PH_trusted_proxies6 the client is the 158 * RIGHTMOST element of the chain -- the only one the peer vouches for. 159 * Naming further networks there extends the walk leftwards, one hop per 160 * trusted node; see PAIVANA_HTTPD_resolve_forwarding(). 161 * 162 * It also decides whether `BASE_URL` is optional: the flag is the 163 * assertion that the proxy enforced a correct "Host", which is what 164 * makes reconstructing our own URL from the request safe. 165 */ 166 extern int PH_respect_forwarded_headers; 167 168 /** 169 * Networks whose members are reverse proxies we trust to report the 170 * client address truthfully, from the `TRUSTED_PROXIES` configuration 171 * option. NULL if unconfigured. These are the hops BEYOND the socket 172 * peer: #PH_respect_forwarded_headers already trusts the peer, and each 173 * network named here lets the walk step one element further left, past 174 * a node it matches. The first node not covered is the client. 175 */ 176 extern struct GNUNET_STRINGS_IPv4NetworkPolicy *PH_trusted_proxies4; 177 178 /** 179 * IPv6 counterpart of #PH_trusted_proxies4, from `TRUSTED_PROXIES6`. 180 */ 181 extern struct GNUNET_STRINGS_IPv6NetworkPolicy *PH_trusted_proxies6; 182 183 /** 184 * True if either #PH_trusted_proxies4 or #PH_trusted_proxies6 was 185 * configured. Distinguishes "no hop beyond the peer is trusted" from 186 * "these networks are, in addition to the peer". 187 */ 188 extern bool PH_have_trusted_proxies; 189 190 /** 191 * Value to return from main() 192 */ 193 extern int PH_global_ret; 194 195 /** 196 * Our configuration. 197 */ 198 extern const struct GNUNET_CONFIGURATION_Handle *PH_cfg; 199 200 /** 201 * Total number of concurrent client connections we accept, from the 202 * `CONNECTION_LIMIT` configuration option. Divided evenly over the 203 * listen sockets that come up, because MHD's own limit is per daemon 204 * and TALER_MHD_listen_bind() starts one daemon per address. 205 * 206 * MHD's default (about 1018 per daemon) is wrong here in both 207 * directions: it is not process-wide, and it does not know that we 208 * spend file descriptors on outbound libcurl handles from the same 209 * table -- exhausting them makes *paying* clients' requests fail. 210 */ 211 extern unsigned int PH_connection_limit; 212 213 /** 214 * Number of the total connection slots reserved for requests to redeem a 215 * payment, from `PAYMENT_CONNECTION_LIMIT`; 32 by default. Keeping this 216 * separate prevents a burst of ordinary proxy traffic from consuming every 217 * request slot needed to confirm already-paid orders. 218 */ 219 extern unsigned int PH_payment_connection_limit; 220 221 /** 222 * Number of concurrent connections we accept from any single client 223 * address, from `PER_IP_CONNECTION_LIMIT`; 0 disables the check, which 224 * is MHD's default. 225 * 226 * Must be 0 wherever the peer address is not the client's: under 227 * `SERVE = unix` or `systemd` every client shares one peer, and behind 228 * a reverse proxy or a NAT many clients do. See the README. 229 */ 230 extern unsigned int PH_per_ip_connection_limit; 231 232 /** 233 * Maximum aggregate bytes the ordinary-request streaming rings may account 234 * for, from `RELAY_MEMORY_LIMIT`; 256 MiB by default. Startup validates the 235 * product of the two per-request ring limits and the ordinary request slots. 236 */ 237 extern unsigned long long PH_relay_memory_limit; 238 239 /** 240 * Time accepted requests may finish after shutdown begins, from 241 * `SHUTDOWN_GRACE_PERIOD`; 60 seconds by default. Zero requests immediate 242 * shutdown, while the packaged service allows another 15 seconds for cleanup. 243 */ 244 extern struct GNUNET_TIME_Relative PH_shutdown_grace_period; 245 246 /** 247 * How many bytes of a request body we hold in memory at once while 248 * relaying it upstream, from `REQUEST_BUFFER_MAX` or the `-u` / 249 * `--max-upload` command-line option; 256 KiB by default. 250 * 251 * A throughput knob, not a limit: the body is streamed, so this bounds 252 * only how far the client may run ahead of the origin before we stop 253 * reading from it. What an upload is *allowed* to be is 254 * #PH_max_request_size. Larger means fewer suspend/resume round trips 255 * on a fast link and more memory per request in flight; the worst case 256 * is the product with #PH_connection_limit. 257 * 258 * Bounds the *proxied* path only. Bodies sent to our own endpoints 259 * never reach this buffer: `POST /.well-known/paivana` is read by 260 * TALER_MHD_parse_post_json(), whose limit is 261 * #TALER_MHD_REQUEST_BUFFER_MAX. 262 */ 263 extern unsigned long long PH_request_buffer_max; 264 265 /** 266 * How many bytes of a response body we hold in memory at once while 267 * relaying it to the client, from `RESPONSE_BUFFER_MAX`; 256 KiB by 268 * default. The mirror of #PH_request_buffer_max, and equally not a 269 * limit — there is deliberately no ceiling on the size of a response. 270 */ 271 extern unsigned long long PH_response_buffer_max; 272 273 /** 274 * Largest request body we accept, from `MAX_REQUEST_SIZE`; 1 MiB by 275 * default. Anything above it is answered 413, on the declared 276 * `Content-Length` where there is one and otherwise once the body 277 * actually exceeds it. 278 * 279 * Distinct from #PH_request_buffer_max, which used to do both jobs 280 * because a body that could not be buffered could not be forwarded. 281 * Streaming separates them: this one is policy, that one is memory. 282 * For the sake of configurations written when they were one number, 283 * an explicitly configured `REQUEST_BUFFER_MAX` with no 284 * `MAX_REQUEST_SIZE` beside it still sets both. 285 */ 286 extern unsigned long long PH_max_request_size; 287 288 /** 289 * How long the origin has to produce its response *headers* before we 290 * give up on it and answer 504, from `UPSTREAM_TIMEOUT`; 60 s by 291 * default. 292 * 293 * Deliberately not a bound on the whole request: a response is 294 * relayed as it arrives, so a large one legitimately runs for as long 295 * as it runs. This clock is cancelled the moment the final header 296 * section ends, and it is the only one of the three that can still 297 * produce a status code — after that the status is already on the 298 * wire. A stalling origin is caught afterwards by 299 * #PH_upstream_stall_timeout instead. 300 */ 301 extern struct GNUNET_TIME_Relative PH_upstream_timeout; 302 303 /** 304 * How long the origin may make no progress at all — no byte moved in 305 * either direction — before we give up on the request, from 306 * `UPSTREAM_STALL_TIMEOUT`; 60 s by default. 307 * 308 * Not a bound on how long a request may take: a 500 MiB download is 309 * expected to run for as long as it runs. The clock is suspended 310 * whenever *we* are the reason nothing is moving, i.e. while we hold 311 * libcurl's receive side paused because the client has not drained 312 * what we already have. 313 */ 314 extern struct GNUNET_TIME_Relative PH_upstream_stall_timeout; 315 316 317 #endif