Prevent Arbitary HTTP Host header in nginx

Kaushal Shriyan kaushalshriyan at gmail.com
Fri Feb 28 17:49:30 UTC 2020


On Fri, Feb 28, 2020 at 9:08 PM Reinis Rozitis <r at roze.lv> wrote:

> > I did follow your steps. My nginx.conf file is
> https://paste.centos.org/view/ae22889e when I run the curl call, I am
> still receiving HTTP 200 OK response instead of HTTP 444 (No Response) as
> per the below output
>
> If you've just called config reload then most likely your nginx is still
> using an old configuration (you should always check with: nginx -t).
>
>
> I tried to make a simple test case and turns out you can't have just
> 'listen 443;' directive (even there is no 'ssl' option) in one server block
> if another has ' listen 443 ssl;' nginx requires to specify a
> "ssl_certificate" (which is kind of understandable if you know that nginx
> has several caveats regarding listen ip:port pairs).
>
> The error looks like:
>
> nginx  -t
> nginx: [emerg] no "ssl_certificate" is defined for the "listen ... ssl"
> directive in nginx.conf:39
> nginx: configuration file nginx.conf test failed
>
> So before writing solutions out of head one should always note that and/or
> test your own suggestions :)
>
>
>
> The correct configuration example should look like this (for
> somedummy.crt/key certificate you can either use some self signed or just
> any other valid certificate (since nginx checks the validity of ssl
> certificates at startup/config reload you can't place nonexisting/nonvalid
> certs here)):
>
>
>
>     server {
>         listen 443;
>         ssl_certificate      somedummy.crt;
>         ssl_certificate_key  somedummy.key;
>         server_name _;
>         return       444;
>     }
>
>     server {
>         listen 443 ssl;
>         ssl_certificate      validdomain.crt;
>         ssl_certificate_key  validdomain.key;
>         server_name validdomain;
>         return 200 'Works';
>     }
>
>
> Then the curl requests with Host injects should work as expected:
>
> curl --verbose https://validdomain
>
> > GET / HTTP/1.1
> > Host: validdomain
> >
> < HTTP/1.1 200 OK
> * Connection #0 to host validdomain left intact
> Works
>
>
> curl --verbose --header 'Host: invalidhost' https://validdomain
>
> > GET / HTTP/1.1
> > Host: invalidhost
> >
> * Empty reply from server
> * Connection #0 to host validdomain left intact
> curl: (52) Empty reply from server
>
>
>
>
> p.s. for further testing you should note also that curl doesn't use the
> Host header for SNI (https://github.com/curl/curl/issues/607 ) rather
> than the one in the url
>
> So something like:
>
> curl --verbose --header 'Host: validhostname' https://127.0.0.1
> will fail with:
> curl: (51) SSL: no alternative certificate subject name matches target
> host name '127.0.0.1'
>
>
> will fail but on the other hand (if your somedummy.crt has an actual
> domain):
>
> curl --verbose --header 'Host: validdomain' https://somedummy
>
> * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
> > GET / HTTP/1.1
> > Host: validdomain
>
> < HTTP/1.1 200 OK
> < Server: nginx/1.17.8
> * Connection #0 to host somedummy left intact
> Works
>
> the dummy ssl certificate will be used but nginx will serve the validdoman
> virtualhost .
>
> rr
>
>
> _______________________________________________
> nginx mailing list
> nginx at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx


Thanks Reinis for a detailed explanation. It worked as expected. Thanks a
lot for all the help and much appreciated.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20200228/e7cbfef3/attachment.htm>


More information about the nginx mailing list