# Host header and SSL

**URL:** <https://www.ruby-forum.com/t/host-header-and-ssl/216922>\
**Category:** NGINX\
**Created:** [February 17, 2012, 12:20am UTC](https://www.ruby-forum.com/t/host-header-and-ssl/216922 "2012-02-17T00:20:01Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [February 17, 2012, 12:20am UTC](https://www.ruby-forum.com/t/host-header-and-ssl/216922/1 "2012-02-17T00:20:01Z")

</div>

Hi,

in my setup Nginx is a load balancer to many different services, some  
of them are using SSL (so Nginx is also SSL terminator in this case).  
I have many different IPs and for every IP it happen to be more than  
one domain (of course only in non-SSL situation).

So I am using virtual hosts heavily with http and since my backends  
rely on Host header from user (it has to be correct) I have catch-all  
section for not matching server\_names. Something like this

… (many different server sections with different server\_names) …

server {  
listen IP1:80 default\_server;  
listen IP2:80 default\_server;  
serrver\_name \_;  
return 444;  
}

But this technique simply does not work for SSL. As far I understand  
correctly there are two techniques to cope with my problem (to prevent  
https request with non-matching Host header to be served):

1. using if

server {  
listen IP3:443 ssl default\_server;  
server\_name some\_host.com;

ssl\_certificate…

if ($host != “some\_host.com”) {  
return 444;  
}

location / {  
…  
proxy\_set\_header Host $host; // safe  
}  
}

1. using catch-all but slightly more complicated and weird:

server {  
listen IP3:443 ssl;  
server\_name some\_host.com;

(no ssl\_certificate section - it is in catch-all block)

location / {  
…  
proxy\_set\_header Host $host; // safe because of catch-all below  
}  
}

server {  
listen IP3:443 ssl default\_server;  
server\_name \_;

ssl\_certificate…

return 444;  
}

What do you think? Are both solutions equivalent? Which one is  
preffered (more efficient, elegant)? Will it work?

Thanks for your help!

–  
Kamil

---

<div class="post-metadata">

**Author:** ![grymuz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/779978/32.png) [@grymuz](https://www.ruby-forum.com/u/grymuz)\
**Post date:** [February 17, 2012, 1:07am UTC](https://www.ruby-forum.com/t/host-header-and-ssl/216922/2 "2012-02-17T01:07:44Z")

</div>

On Fri, Feb 17, 2012 at 6:18 AM, Kamil G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> https request with non-matching Host header to be served):

It should work (at least passes `nginx -t` in my test).

> …  
> return 444;  
> }

Nothing weird or complicated in this one. It’s the preferred method  
but you need to specify ssl\_certificate parameters on each server  
blocks. I’m not sure how it behaves on non-SNI environment though.

Alternatively you can force passing some\_host.com as the Host header  
to your proxy:

proxy\_set\_header Host some\_host.com

–  
O\< ascii ribbon campaign - stop html mail - [www.asciiribbon.org](http://www.asciiribbon.org)

---

<div class="post-metadata">

**Author:** ![grymuz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/779978/32.png) [@grymuz](https://www.ruby-forum.com/u/grymuz)\
**Post date:** [February 17, 2012, 8:16am UTC](https://www.ruby-forum.com/t/host-header-and-ssl/216922/3 "2012-02-17T08:16:10Z")

</div>

On Fri, Feb 17, 2012 at 1:06 AM, Edho A. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > correctly there are two techniques to cope with my problem (to prevent  
> > https request with non-matching Host header to be served):
> 
> It should work (at least passes `nginx -t` in my test).

You mean soultion no. 1 (the one with if in server block, which you -  
maybe accidentally - cut off)?

> > …  
> > return 444;  
> > }
> 
> Nothing weird or complicated in this one. It’s the preferred method  
> but you need to specify ssl\_certificate parameters on each server  
> blocks. I’m not sure how it behaves on non-SNI environment though.

By writing ‘weird’ I meant that ssl configuration is not in one place  
(in the server\_name with corresponding server\_name) but instead in  
some weird ‘server\_name \_’ block which maybe confusing for some  
non-experienced Nginx config writers 😛

Performance wisely - is 1 and 3 imperceptible?

> Alternatively you can force passing some\_host.com as the Host header  
> to your proxy:
> 
> proxy\_set\_header Host some\_host.com

No, this is not exactly what I want because:  
a) it does not work when I have server\_name like \*.some\_host.com (of  
course in combination with some wildcard certificate)  
b) it tells backend that user came with some\_host.com which is not true

Thanks for your help.

Cheers,

–  
Kamil
