reqs: improve stathost detection#606
Conversation
- check stathost before transparent proxy check, else stathost might be misdetected as a trans host request. - rather than just the URL in the request, check "Host" header first. if it exists, we only check it for a match, else we extract the host from the url and check that. for both cases we need to exclude trailing port specs, and a trailing path in case it's an URL. this should make it easier to access the stathost, for example by injecting a host header into a curl command line with -H: $ curl -H "Host: tinyproxy.stats" 127.0.0.1:8080 the stathost can also be specified as an ip address, e.g. Stathost "127.0.0.10" + a separate Listen statement for that ip. in such a case e.g. $ curl http://127.0.0.10:8080 would work too, even if curl didn't add a Host header (but it does anyway).
There was a problem hiding this comment.
Pull request overview
Improves Tinyproxy’s “stathost” (stats page) request detection by checking it earlier in request processing and by matching against the Host header (when present) instead of relying only on the parsed request host later in the flow.
Changes:
- Adds helper functions to detect stathost requests from either the
Hostheader or an absolute-form URL. - Moves stathost detection earlier in
process_request()(before reverse/transparent-proxy handling). - Removes the later
strcmp(config->stathost, request->host)stathost check.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static int check_stathost(char* hosts_header, char *url) { | ||
| /* if the Host: header was passed it's the only source of truth */ | ||
| if (hosts_header) return is_stathost(hosts_header); | ||
| return !strncasecmp (url, "http://", 7) && is_stathost(url + 7); | ||
| } |
use an early stathost check for the host header, in case it exists, and stick to comparing the hostname extracted from the url after the transparent proxy logic executed. this simplifies parsing in is_stathost and makes sure that a trans request that resolves to the stathost still ends up there.
There was a problem hiding this comment.
Pull request overview
This PR adjusts Tinyproxy’s request parsing flow to more reliably detect requests intended for the configured StatHost, prioritizing the Host header and performing the stathost check earlier to avoid transparent-proxy misclassification.
Changes:
- Added an
is_stathost()helper to match a host value againstconfig->stathostwhile tolerating an optional trailing:port. - Moved/added stathost detection to occur earlier in
process_request()using theHostheader. - Kept a secondary stathost check using the hostname extracted from the request URL.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (is_stathost (pseudomap_find (hashofheaders, "host"))) { | ||
| got_stathost: | ||
| log_message (LOG_NOTICE, "Request for the stathost."); | ||
| connptr->show_stats = TRUE; | ||
| goto fail; |
| if (is_stathost (pseudomap_find (hashofheaders, "host"))) { | ||
| got_stathost: | ||
| log_message (LOG_NOTICE, "Request for the stathost."); | ||
| connptr->show_stats = TRUE; | ||
| goto fail; | ||
| } |
There was a problem hiding this comment.
Pull request overview
This PR improves Tinyproxy “stathost” detection by checking the Host header first (and earlier in request processing) to avoid misclassification as transparent-proxy traffic and to support accessing the stats page via injected Host headers.
Changes:
- Add an
is_stathost()helper to matchstathostwith an optional:portsuffix. - Check for stathost via the
Hostheader early inprocess_request()(before reverse/transparent proxy handling). - Reuse the updated stathost matching for basic-auth handling when selecting
AuthorizationvsProxy-Authorization.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static int is_stathost(const char* host) { | ||
| const char *p = config->stathost, *q = host; | ||
| if (!p || !q) return 0; | ||
| while (*p && *(p++) == *(q++)); | ||
| return *p == 0 && (*q == 0 || *q == ':'); | ||
| } | ||
|
|
| /* | ||
| * Check to see if they're requesting the stat host | ||
| */ | ||
| if (is_stathost (pseudomap_find (hashofheaders, "host"))) { | ||
| got_stathost: | ||
| log_message (LOG_NOTICE, "Request for the stathost."); | ||
| connptr->show_stats = TRUE; | ||
| goto fail; | ||
| } |
| static int is_stathost(const char* host) { | ||
| const char *p = config->stathost, *q = host; | ||
| if (!p || !q) return 0; | ||
| while (*p && *(p++) == *(q++)); |
by checking whether the entire stathost name matches the start of the hostname passed, if we encounter a colon after the name we can be sure it's for the port - by using strchr instead a colon could be part of an ipv6 string.
this should make it easier to access the stathost, for example by injecting a host header into a curl command line with -H: $ curl -H "Host: tinyproxy.stats" 127.0.0.1:8080
the stathost can also be specified as an ip address, e.g. Stathost "127.0.0.10" + a separate Listen statement for that ip. in such a case e.g.
$ curl http://127.0.0.10:8080
would work too, even if curl didn't add a Host header (but it does anyway).