Nginx+Apache2+LetsEncrypt with IPhone cannot display page

apache-2.4iosiphonenginxsafari

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.

Best Answer

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.