3

I have nginx+letsencrypt ssl cert and it's works fine for all but new iOS with Safari. It works fine with iPhone 4, but with iPhone 5 and newer it's not.

And I see multiple requests in nginx log:

IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5999 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5999 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5998 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5999 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5998 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5998 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 200 5998 "REFERER" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
...
and ends with 499 code
IPADDRESS - - [03/Dec/2016:10:08:08 +0000] "GET / HTTP/2.0" 499 5998 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"

and blank page in Safari browser.

HTTP section ngixn config:

##
# SSL Settings
##

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
ssl_dhparam /etc/nginx/ssl/dhparams.pem;

ssl_session_cache shared:SSL:5m;
ssl_session_timeout 1h;

SERVER section for domain:

listen 443 ssl http2;

ssl_certificate         /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
ssl_certificate_key     /etc/letsencrypt/live/domain.com/privkey.pem;

location / {
    proxy_pass          http://localhost:40011/;
    proxy_set_header    Host $http_host;
    proxy_set_header    X-Real-IP $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto $scheme;
}

Nginx is used with Apache 2.4.23

<VirtualHost localhost:40011>
Protocols h2 http/1.1

AddDefaultCharset UTF-8

ServerName localhost

ServerAdmin support@domain.com
DocumentRoot /var/www/domain.com/public
DirectoryIndex index.php

SetEnvIf X-Forwarded-Proto https HTTPS=on

<Directory /var/www/domain.com/public>
    Order Allow,Deny
    Allow From All
    AllowOverride None
    Options FollowSymLinks
</Directory>

</VirtualHost>

And Apache log contains same requests:

127.0.0.1 - - [05/Dec/2016:14:36:00 +0000] "GET / HTTP/1.0" 200 6122 "-" "Mozilla/5.0 (iPhone; CPU OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
::1 - - [05/Dec/2016:14:36:00 +0000] "GET / HTTP/1.0" 200 6122 "-" "Mozilla/5.0 (iPhone; CPU OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
127.0.0.1 - - [05/Dec/2016:14:36:00 +0000] "GET / HTTP/1.0" 200 6122 "-" "Mozilla/5.0 (iPhone; CPU OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"
::1 - - [05/Dec/2016:14:36:00 +0000] "GET / HTTP/1.0" 200 6121 "-" "Mozilla/5.0 (iPhone; CPU OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 Mobile/14B100 Safari/602.1"

...and still blank page in Safari.

dima
  • 41
  • 5
  • Run a couple of SSL tests and report back : https://www.ssllabs.com/ssltest/ and https://www.ssllabs.com/ – Tim Dec 03 '16 at 20:27
  • What is nginx version? Make sure you are running the latest from mainline branch. – Alex Dec 04 '16 at 07:09
  • ssllabs says A+, nginx version is 1.11.6, ALPN support enabled – dima Dec 05 '16 at 09:45

3 Answers3

2

This doesn't seem to be a problem with SSL (or Let's encrypt). The fact, that the request shows up in your log file proves that the request came through fine (the SSL handshake is done before the actual request reaches the server).

A little googling for nginx http 499 shows that nginx uses this (unofficial) return code to indicate that the client closed the connection before nginx was able to send an answer.

The most probable reason for this would be that the script on the server takes so long to run, that the client thinks the connection timed out and closes the connection. This could be "solved" by reducing the time a script is allowed to run (if nginx supports this, I know it is possible with apache). Of course this doesn't solve the actual issue, it only changes the error code and reports it back to the client.

If the cause is a long running script, you would have to debug the script on the server side to determine what part of it takes so long.

Another possibility, with the client being a mobile device, could be that it is just a bad connection that results in the connection being dropped.

Gerald Schneider
  • 19,757
  • 8
  • 52
  • 79
  • It doesn't explain multiple requests and a fact that only new iOS devices are affected. – dima Dec 05 '16 at 10:49
  • No, it doesn't, it just points out that you are looking in the wrong place for the problem. Without knowing more about what's actually being served by nginx the question can't be answered. – Gerald Schneider Dec 05 '16 at 10:51
  • It's a simple ngixn+apache2 server with `proxy_pass http://localhost:1234`. Apache log contains the same multiple requests. Can it be problem with Apache? I really confused that only iOS Safari is affected... – dima Dec 05 '16 at 11:20
  • If the requests show up in apaches request log as well it confirms that this is not an SSL problem. It could be a problem with apache, with the connection between nginx and apache, the possibilities already mentiond above or something completely different. With the little information you provide the only thing that can be determined for certain is that it is not a problem with SSL. Everything else is just blind guessing. – Gerald Schneider Dec 05 '16 at 12:51
1

Nginx cannot proxy to Apache by h2 protocol:

Protocols h2 http/1.1

removing this line solve the problem, but I still cannot understand why it's happing ONLY WITH devices iOS 10.

dima
  • 41
  • 5
1

Now facing the same/similar issue on iOS 12 with nginx 1.16.0 proxying to apache enabled with http2. Workaround is to disable http2 on nginx, the right solution is described here https://trac.nginx.org/nginx/ticket/915 or https://trac.nginx.org/nginx/ticket/1150 - adding proxy_hide_header Upgrade; will solve that. With Upgrade header (probably only) the iOS cannot handle "protocol upgrade request" together with that the request is already in http2.

The same proxy on apache 2.4 and mod_proxy works ok as this header is not forwarded to client as default.