paivana-httpd.h (10776B)
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 * Merchant backend base URL. 82 */ 83 extern char *PH_merchant_base_url; 84 85 /** 86 * Base URL of this site as seen by the client. If not set, 87 * we will try to determine it from "X-Forwarded-Host" and 88 * "Host" and "X-Forwarded-Port" headers. 89 */ 90 extern char *PH_base_url; 91 92 /** 93 * Curl context for talking to the merchant backend. Carries the 94 * `Authorization: Bearer $MERCHANT_ACCESS_TOKEN` header on every 95 * request, so it must never be used for anything but the backend. 96 * NULL in `-n` (no payment) mode, where there is no backend. 97 */ 98 extern struct GNUNET_CURL_Context *PH_merchant_ctx; 99 100 /** 101 * Curl context for forwarding client requests to the origin server. 102 * Deliberately separate from #PH_merchant_ctx: headers appended to a 103 * context apply to every request made through it, and our credentials 104 * for the merchant backend have no business being sent to the site we 105 * proxy for. 106 */ 107 extern struct GNUNET_CURL_Context *PH_proxy_ctx; 108 109 /** 110 * Pre-compiled regular expression for sites that are whitelisted 111 * and never paywalled. 112 */ 113 extern regex_t PH_whitelist_ex; 114 115 /** 116 * True if whitelist_ex was set. 117 */ 118 extern bool PH_have_whitelist_ex; 119 120 /** 121 * Set to true if the cookie applies globally to all sites 122 * and not per-page. 123 */ 124 extern int PH_global_cookie; 125 126 /** 127 * Disable paywall check. 128 */ 129 extern int PH_no_check; 130 131 /** 132 * If set, we are behind a reverse proxy: the socket peer is a proxy we 133 * trust, and the forwarding headers ("Forwarded" and the "X-Forwarded-*" 134 * family) are read to recover what the client actually did. Unset, no 135 * forwarding header is consulted at all and the peer *is* the client. 136 * Only enable it when the server in front writes those headers itself, 137 * either setting them or appending to them. Appending is enough -- 138 * what it appends is the address it accepted the request from, so the 139 * element we read is still one it vouches for. What is not safe is a 140 * front server that passes the client's own headers through unchanged, 141 * which leaves the client writing the element we believe. 142 * 143 * This flag alone extends trust exactly one hop, to the peer, so with 144 * no #PH_trusted_proxies4 / #PH_trusted_proxies6 the client is the 145 * RIGHTMOST element of the chain -- the only one the peer vouches for. 146 * Naming further networks there extends the walk leftwards, one hop per 147 * trusted node; see PAIVANA_HTTPD_resolve_forwarding(). 148 * 149 * It also decides whether `BASE_URL` is optional: the flag is the 150 * assertion that the proxy enforced a correct "Host", which is what 151 * makes reconstructing our own URL from the request safe. 152 */ 153 extern int PH_respect_forwarded_headers; 154 155 /** 156 * Networks whose members are reverse proxies we trust to report the 157 * client address truthfully, from the `TRUSTED_PROXIES` configuration 158 * option. NULL if unconfigured. These are the hops BEYOND the socket 159 * peer: #PH_respect_forwarded_headers already trusts the peer, and each 160 * network named here lets the walk step one element further left, past 161 * a node it matches. The first node not covered is the client. 162 */ 163 extern struct GNUNET_STRINGS_IPv4NetworkPolicy *PH_trusted_proxies4; 164 165 /** 166 * IPv6 counterpart of #PH_trusted_proxies4, from `TRUSTED_PROXIES6`. 167 */ 168 extern struct GNUNET_STRINGS_IPv6NetworkPolicy *PH_trusted_proxies6; 169 170 /** 171 * True if either #PH_trusted_proxies4 or #PH_trusted_proxies6 was 172 * configured. Distinguishes "no hop beyond the peer is trusted" from 173 * "these networks are, in addition to the peer". 174 */ 175 extern bool PH_have_trusted_proxies; 176 177 /** 178 * Value to return from main() 179 */ 180 extern int PH_global_ret; 181 182 /** 183 * Our configuration. 184 */ 185 extern const struct GNUNET_CONFIGURATION_Handle *PH_cfg; 186 187 /** 188 * Total number of concurrent client connections we accept, from the 189 * `CONNECTION_LIMIT` configuration option. Divided evenly over the 190 * listen sockets that come up, because MHD's own limit is per daemon 191 * and TALER_MHD_listen_bind() starts one daemon per address. 192 * 193 * MHD's default (about 1018 per daemon) is wrong here in both 194 * directions: it is not process-wide, and it does not know that we 195 * spend file descriptors on outbound libcurl handles from the same 196 * table -- exhausting them makes *paying* clients' requests fail. 197 */ 198 extern unsigned int PH_connection_limit; 199 200 /** 201 * Number of concurrent connections we accept from any single client 202 * address, from `PER_IP_CONNECTION_LIMIT`; 0 disables the check, which 203 * is MHD's default. 204 * 205 * Must be 0 wherever the peer address is not the client's: under 206 * `SERVE = unix` or `systemd` every client shares one peer, and behind 207 * a reverse proxy or a NAT many clients do. See the README. 208 */ 209 extern unsigned int PH_per_ip_connection_limit; 210 211 /** 212 * How many bytes of a request body we hold in memory at once while 213 * relaying it upstream, from `REQUEST_BUFFER_MAX` or the `-u` / 214 * `--max-upload` command-line option; 256 KiB by default. 215 * 216 * A throughput knob, not a limit: the body is streamed, so this bounds 217 * only how far the client may run ahead of the origin before we stop 218 * reading from it. What an upload is *allowed* to be is 219 * #PH_max_request_size. Larger means fewer suspend/resume round trips 220 * on a fast link and more memory per request in flight; the worst case 221 * is the product with #PH_connection_limit. 222 * 223 * Bounds the *proxied* path only. Bodies sent to our own endpoints 224 * never reach this buffer: `POST /.well-known/paivana` is read by 225 * TALER_MHD_parse_post_json(), whose limit is 226 * #TALER_MHD_REQUEST_BUFFER_MAX. 227 */ 228 extern unsigned long long PH_request_buffer_max; 229 230 /** 231 * How many bytes of a response body we hold in memory at once while 232 * relaying it to the client, from `RESPONSE_BUFFER_MAX`; 256 KiB by 233 * default. The mirror of #PH_request_buffer_max, and equally not a 234 * limit — there is deliberately no ceiling on the size of a response. 235 */ 236 extern unsigned long long PH_response_buffer_max; 237 238 /** 239 * Largest request body we accept, from `MAX_REQUEST_SIZE`; 1 MiB by 240 * default. Anything above it is answered 413, on the declared 241 * `Content-Length` where there is one and otherwise once the body 242 * actually exceeds it. 243 * 244 * Distinct from #PH_request_buffer_max, which used to do both jobs 245 * because a body that could not be buffered could not be forwarded. 246 * Streaming separates them: this one is policy, that one is memory. 247 * For the sake of configurations written when they were one number, 248 * an explicitly configured `REQUEST_BUFFER_MAX` with no 249 * `MAX_REQUEST_SIZE` beside it still sets both. 250 */ 251 extern unsigned long long PH_max_request_size; 252 253 /** 254 * How long the origin has to produce its response *headers* before we 255 * give up on it and answer 504, from `UPSTREAM_TIMEOUT`; 60 s by 256 * default. 257 * 258 * Deliberately not a bound on the whole request: a response is 259 * relayed as it arrives, so a large one legitimately runs for as long 260 * as it runs. This clock is cancelled the moment the final header 261 * section ends, and it is the only one of the three that can still 262 * produce a status code — after that the status is already on the 263 * wire. A stalling origin is caught afterwards by 264 * #PH_upstream_stall_timeout instead. 265 */ 266 extern struct GNUNET_TIME_Relative PH_upstream_timeout; 267 268 /** 269 * How long the origin may make no progress at all — no byte moved in 270 * either direction — before we give up on the request, from 271 * `UPSTREAM_STALL_TIMEOUT`; 60 s by default. 272 * 273 * Not a bound on how long a request may take: a 500 MiB download is 274 * expected to run for as long as it runs. The clock is suspended 275 * whenever *we* are the reason nothing is moving, i.e. while we hold 276 * libcurl's receive side paused because the client has not drained 277 * what we already have. 278 */ 279 extern struct GNUNET_TIME_Relative PH_upstream_stall_timeout; 280 281 282 #endif