aboutsummaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2024-05-29 07:52:13 +0000
committerOmar Polo <op@omarpolo.com>2024-05-29 07:52:13 +0000
commit1ef0cd0cdb6512fad96ecf0830e581af677d5947 (patch)
tree398ead8e51094c18fda333df8ca9e70b958ebf7a /server.c
parent42e2af25aec9e9eef05bddc9e408ab2a11e3d5fb (diff)
relax the SNI requirement
There are legitimate cases where SNI can't be used, for example when connecting via an IPv6 address, so don't rejects those requests. Instead, fill the requested domain with the address (literal) of the socket they're connected to and attempt to match on it. This possibly still incur in a "won't proxy" error if the client then requests a different hostname. See the github issue https://github.com/omar-polo/gmid/issues/25
Diffstat (limited to 'server.c')
-rw-r--r--server.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/server.c b/server.c
index b215dad..b9bb0d8 100644
--- a/server.c
+++ b/server.c
@@ -119,6 +119,16 @@ match_host(struct vhost *v, struct client *c)
if (addr == NULL)
return 0;
+ if (*c->domain == '\0') {
+ if (getnameinfo((struct sockaddr *)&addr->ss, addr->slen,
+ c->domain, sizeof(c->domain), NULL, 0,
+ NI_NUMERICHOST) == -1) {
+ log_warn("failed to fill the domain; getnameinfo");
+ *c->domain = '\0';
+ return 0;
+ }
+ }
+
if (matches(v->domain, c->domain))
return 1;
@@ -403,16 +413,19 @@ handle_handshake(int fd, short ev, void *d)
evbuffer_unfreeze(c->bev->output, 1);
#endif
- if ((servname = tls_conn_servername(c->ctx)) == NULL) {
+ if ((servname = tls_conn_servername(c->ctx)) == NULL)
log_debug("handshake: missing SNI");
- goto err;
- }
-
if (!puny_decode(servname, c->domain, sizeof(c->domain), &parse_err)) {
log_info("puny_decode: %s", parse_err);
- goto err;
+ start_reply(c, BAD_REQUEST, "Wrong/malformed host");
+ return;
}
+ /*
+ * match_addr will serialize the (matching) address if c->domain
+ * is empty, so that we can support requests for raw IPv6 address
+ * that can't have a SNI.
+ */
TAILQ_FOREACH(h, &conf->hosts, vhosts)
if (match_host(h, c))
break;
@@ -428,8 +441,7 @@ handle_handshake(int fd, short ev, void *d)
return;
}
-err:
- start_reply(c, BAD_REQUEST, "Wrong/malformed host or missing SNI");
+ start_reply(c, BAD_REQUEST, "Wrong/malformed host");
}
static void