Apache support for weird SNI request

Hello,

I have a very strange situation I need to solve using Apache and PHP, which is related to SSL and SNI so I’m asking in this forum. This has nothing to do with Lets Encrypt in general, but I figured here in this forum are lots of people who know about webserver SSL configuration so I might be able to get an answer there. I hope that is allowed.

I am making a web server for existing (proprietary) clients to access, so I cannot modify the clients at all. The client has an interesting bug: It sends the “Host:” header twice, with the exact same domain inside it. I worked around that by configuring Apache like this:
ServerName "my-weird-domain.com, my-weird-domain.com"
and now the weird requests using the two headers correctly work.
The client doesn’t support SNI (which is kinda stupid but well, now wasting a single IP on that service), but other than that, everything worked.

Now the client got an update. It now supports SNI. Hey, great, no longer a second IP needed.

That comes with another problem though: It still sends the duplicate host header. That means, Apache is spitting out this error:

[Sat Nov 10 16:09:48.039323 2018] [ssl:error] [pid 9104] AH02032: Hostname my-weird-domain.com provided via SNI and hostname my-weird-domain.com, my-weird-domain.com provided via HTTP are different

Now I have two goals:
First, make Apache ignore the fact that these two things don’t match, so the updated client can connect to my web service as well.
Second, if possible, I’d like to know (from within my PHP script on that domain) if a client is version 1 or 2, i.e., if it used SNI to connect to Apache or not.

Unfortunately, when I google for that error, I always get “yeah it’s a client error not a server bug” - I know it is a client error but I can’t modify the client, I need to work around that on the server somehow. And I need to know if a client is version 1 or version 2, so the PHP script needs to know if SNI was used or not, but if I search for Apache and SNI, I always get info on how to set up a vhost with SNI, which is not what I need.

As said earlier, nothing to do with Lets Encrypt, but I hope one of the guys here will still be able to help me out with this.

Not really an answer to your question, but do you keep supporting the non-SNI client? I imagine not every client is updated immediately, right?

I keep supporting the non-SNI client. The fact with “I no longer need the 2nd IP” is more like for the future. And because I want to keep supporting it I’d like to know the client version inside PHP - but the only difference to the server is if SNI is used or not, the actual HTTP requests are absolutely the same. And I need to get Apache to ignore that error.

Are you seeking answers with support for the non-SNI clients? Because if you're keeping non-SNI client support around, why even bother using a ServerName directive in your non-SNI VirtualHost? Apache should have enough to go with with the IP address and port in the <VirtualHost> directive. I suppose that would get rid of your error.

Also, how to get the info to PHP? I would suggest using the environment variables provided by mod_ssl. It uses the SSLOptions directive with the StdEnvVars option. There's a SSL_TLS_SNI variable possible. I'm sure PHP can import environment variables, so you can use that in your application.

Thanks for the hint with SSL_TLS_SNI, I will check that.

About the first part with the SNI stuff, sorry, I had something wrong in my mind (the config has been sitting there for a while already and I didn’t look at it again before posting) - we do not have a second IP, but are instead forcing Apache to load the vHost for this web service first, thus it is the default vHost and is used for all non-SNI clients.

Thus, we can’t use the solution you proposed. We tried something like RequestHeader edit Host ",.*" "" early to edit the Host header so it matches the SNI header, but apparently this SNI / Host header check is done before this modification runs. Do you have any other idea, maybe that error can somehow be turned into a warning or turned off?

Hi @Leseratte10

I'm not so firm with such things. But isn't it possible to create a proxy that rewrites this host header?

There it should be possible to transform

my-weird-domain.com, my-weird-domain.com -> my-weird-domain.com

and add an own header, if the original header is a little bit stupid. So the backend is able to check this new header.

How about setting ServerName as:
ServerName "my-weird-domain.com*"
or
ServerName "*my-weird-domain.com"

1 Like

I think only ServerAlias can use wildcards @rg305, but good thinking, I think that might even work :smiley:

1 Like

Maybe, not sure.
But either way it’s definitely worth the try :slight_smile:
The question in my mind now is:
Will the * include/overcome the ", " ?
Only testing can tell for sure…

Well using a wildcard instead of writing the hostname twice (in the ServerAlias entry) does indeed work (the correct vHost is used), but that doesn’t change the fact that SNI hostname (my-weird-domain.com) and transmitted HTTP header hostname (my-weird-domain.com, my-weird-domain.com) differ, and I still get the error.

Have you tried running mod_headers in early mode? Sorry, missed the directive at the end.. Didn't expect it there and just read about the position after I posted this.. :blush:

I guess you really should press for fixing that bug, as the whole client seems to be useless for every SNI enabled Apache server on the world wide web.. Shouldn't be too good for business for that client I guess.

Also, what's the name of the client and the company? So I know which company not to give my money to in the future.

Can you explain, in as much detail, what the problem is?

Well, the problem is, I have a client transmitting the following Headers:

...
Host: my-weird-domain.com
User-Agent: Some random UA string
Host: my-weird-domain.com

Apache merges these to Host: my-weird-domain.com, my-weird-domain.com.

And because the SNI header says “my-weird-domain.com” and the Host header now says “my-weird-domain.com, my-weird-domain.com” these two differ and Apache refuses to do anything and claims “Hostname provided via SNI and hostname provided via HTTP are different”, and I’m looking for a server-side fix that doesn’t involve recompiling Apache with custom patches.

Can you show a sample get from the apache logs?

You mean a complete HTTP request? Sure.

POST /some-custom-path HTTP/1.1
Host: my-weird-domain.com
User-Agent: SDK/1.0
Host: my-weird-domain.com
HTTP_X_DATA: some-custom-data
Content-Type: application/x-www-form-urlencoded
Content-Length: 305

and the content is URL-encoded form data, like such:
parameter1=value1&parameter2=value2&parameter3=value3

Or were you talking about a different log?

While trying to simulate your connection (on Apache 2.4.25)…
I show apache error log entries with “AH00126: Invalid URI in request HOST: host.name” when issuing:
telnet host.IP 80
HOST: host.name
GET / HTTP/1.1
HOST: host.name

or any combination that includes multiple HOST lines.
[[[ WHERE THE HOST COMES BEFORE THE GET ]]]
I don’t think Apache is equipped to handle this.

Perhaps inserting another proxy (in front of this one) that can handle the multiple HOST entries and reshape them…
Into a proper format?

NGINX (1.15.5) responds in a similar manner.
They both DON’T like HOST before GET.
However, Apache seems to combine them (http://host.name, host.name/, where NGINX does not (http://host.name/).

You could file a bug/feature request with Apache. Its current behavior is mandated by the HTTP/1.1 RFC, but maybe they’d be willing to relax it.

https://tools.ietf.org/html/rfc7230#page-45

You could switch web servers – Nginx doesn’t mind (currently).

1 Like

@rg305 where in my request is a host header before Get? That’s a POST request and both Host headers are after the POST line.

@mnordhoff
Thanks for the RFC that describes that, but that is not the problem, at least not with Apache 2.4.6 (I know that’s pretty old):

$ ncat 1.2.3.4 80
GET / HTTP/1.1
Host: some-hostname.com
User-Agent: Test
Host: some-hostname.com

HTTP/1.1 302 Found
Date: Sun, 11 Nov 2018 05:34:23 GMT
Server: Apache/2.4.6 (Linux/SUSE)
X-Powered-By: PHP/5.4.20
Location: https://some-hostname.com/
Content-Length: 0
Content-Type: text/html

I don’t know if newer versions of Apache enforce this RFC, but the one we currently use doesn’t (which is good). The current problem is not that apache rejects the duplicate host header, but that it rejects a request when host header and SNI header differ.

Yes, I see that now.
Still trying different tests…

I can concur.
NGINX (1.15.5) will proxy:

to some-hostname.com/test.file