At present, if a request contains no "Host:" header [HTTP pre-1.1] or if the supplied header does not match any of the servers configured in httpd.conf, the request is directed to the first server. This isn't documented, AFAICT.
For example, if httpd.conf has just one server server "www.example.com" then we currently get $ printf "HEAD / HTTP/1.0\r\nHost: www.openbsd.org\r\n\r\n" \ | nc www.example.com www | sed 1q HTTP/1.0 200 OK This behaviour strikes me as wrong (or at least sub-optimal) in the case of non-matching "Host:" headers. The simplistic patch below changes things to return a 404 status if no matching server is found. [If status code 400 (bad request) is preferred, "goto fail;" could be used.] Justification: - This seems more correct, and is consistent with the "fail closed" approach. - There is a net gain in functionality, as use of glob/patterns wildcards can easily re-establish the current behaviour. In contrast, there's no way at present to disable the implicit match-anything behaviour. If this is adopted, it should be document in current.html A followup patch could merge this if statement with the one above it. Several other issues exist in "Host:" header handling. Ross -- Index: server_http.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v retrieving revision 1.140 diff -u -p -r1.140 server_http.c --- server_http.c 3 Aug 2020 10:59:53 -0000 1.140 +++ server_http.c 9 Aug 2020 04:37:08 -0000 @@ -1200,7 +1200,7 @@ server_response(struct httpd *httpd, str struct server_config *srv_conf = &srv->srv_conf; struct kv *kv, key, *host; struct str_find sm; - int portval = -1, ret; + int hostmatch = 0, portval = -1, ret; char *hostval, *query; const char *errstr = NULL; @@ -1277,16 +1277,20 @@ server_response(struct httpd *httpd, str /* Replace host configuration */ clt->clt_srv_conf = srv_conf; srv_conf = NULL; + hostmatch = 1; break; } } } - if (srv_conf != NULL) { + if (host == NULL) { /* Use the actual server IP address */ if (server_http_host(&clt->clt_srv_ss, hostname, sizeof(hostname)) == NULL) goto fail; + } else if (!hostmatch) { + server_abort_http(clt, 404, "not found"); + return (-1); } else { /* Host header was valid and found */ if (strlcpy(hostname, host->kv_value, sizeof(hostname)) >=