tempesta-tech / tempesta

All-in-one solution for high performance web content delivery and advanced protection against DDoS and web attacks
https://tempesta-tech.com/
GNU General Public License v2.0
615 stars 103 forks source link

tls_match_any_server_name not straightforward behavior #2123

Open const-t opened 3 months ago

const-t commented 3 months ago

In general tls_match_any_server_name works fine, but in some cases it little bit confusing. tls_match_any_server_name - Accordingly to wiki should do only two things, allow SNI that not matched with vhosts listed in config file and match such request to default.

Relying on description let's consider following example:

listen 443 proto=https;
frang_limits {
   http_strict_host_checking true;
   http_header_cnt 500;
   http_body_len 10485760; #10MB
}

srv_group default {
    server 192.168.122.128:8080 conns_n=1024;
}

tls_match_any_server_name;
#Cert is issued only for tempesta-tech.com
tls_certificate /etc/tempesta/tfw-root.crt;
tls_certificate_key /etc/tempesta/tfw-root.key;

vhost tempesta-tech.com {
    resp_hdr_set tempesta-hdr "tempesta only header";
    proxy_pass default;
}

vhost default {
    tls_match_any_server_name;
    resp_hdr_set tempesta-hdr "default only header";
    proxy_pass default;
}

cache 0;
block_action attack reply;
block_action error reply;

http_chain {
  -> tempesta-tech.com;
}

I'm doing curl -vk https://unknown and in this case request will be forwarded to tempesta-tech.com, because we have http_chain that explicitly forwards request to tempesta-tech.com. But, when request will be matched to default? In this configuration - never. default vhost it's just a garbage in this config. However, if we delete http_chain from config then request will be forwarded to default.

Another one not straightforward thing, if in this config we move certificates inside vhost tempesta-tech.com and make request curl -vk https://unknown tls error will be occurred. But this is not expected, because in this config we have default routing -> tempesta-tech.com, therefore default vhost is not reachable. We could check later that requested vhost(matched by http chain) doesn't configured for tls, when right vhost found by http chains, that eliminate confusion. Or even don't do this check and rely on browser, that will show error message if SNI and address of requested site are not matched. Looks like some of vendors went this way. For instance google successfully respond to request with unknown SNI(relying on browser SNI == URL check) and even to empty SNI, but for empty SNI google respond with following cert:

- Certificate[0] info:
 - subject `CN=invalid2.invalid,OU=No SNI provided\; please fix your client.', issuer `CN=invalid2.invalid,OU=No SNI provided\; please fix your client.', serial 0x0090768918e93393a0, RSA key 2048 bits, signed using RSA-SHA256, activated `2015-01-01 00:00:00 UTC', expires `2030-01-01 00:00:00 UTC', pin-sha256="j4i4cwAEhF/BFKbkqi8WZWur4bMvr2/EbovM0ku1FNc="
    Public Key ID:
        sha1:183151b78e084135af782d70db9efc747b8d5d88
        sha256:8f88b8730004845fc114a6e4aa2f16656babe1b32faf6fc46e8bccd24bb514d7
    Public Key PIN:
        pin-sha256:j4i4cwAEhF/BFKbkqi8WZWur4bMvr2/EbovM0ku1FNc=

Conclusion, I propose to use tls_match_any_server_name only to allow any SNIs and do this check only on tls level. Then do second check right after vhost chosen by http chain or don't do it at all.

krizhanovsky commented 3 months ago

Maybe we should just get rid of the default vhost to simplify configuration code and user experience. I don't remember any case, when we configured default vhost.