我正在尝试在 Ubuntu 16.04 上为 nginx 配置 HTTPS。我已经用listen 443 ssl语句设置了它,并告诉它在哪里可以找到证书和私钥文件。之后我用sudo service nginx restart.
现在,当我curl https://my_ip_address收到以下消息时:
curl: (35) gnutls_handshake() failed: Handshake failed
Run Code Online (Sandbox Code Playgroud)
我检查了我知道的两个日志文件,/var/log/nginx/access.log并且/var/log/nginx/error.log;但它没有显示任何来自请求的痕迹。
我的问题:SSL 握手失败时是否会记录任何内容?如果是在哪里?一般来说,如何解决这样的问题,在 HTTP 请求发送到服务器或由服务器提取之前 SSL 协议中存在错误?
编辑:我通过从我的配置中删除以下几行来让它工作:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
Run Code Online (Sandbox Code Playgroud)
更新:该ssl_ecdh_curve secp384r1;线路似乎是导致问题的原因。没有它,一切正常,但有了它,SSL 握手就会失败。奇怪的是,错误消息是“没有共享密码”。我不确定它有什么作用,所以我只是删除了它。我还删除了 ssl_stapling 的东西,因为我不知道它的用途,并且它正在创建自己的错误消息
正如@Paul 所说,解决方案是提高日志级别。我在我的nginx.conf文件中更改了一行,所以它现在显示如下:
error_log /var/log/nginx/error.log debug;
Run Code Online (Sandbox Code Playgroud)
现在日志级别更高,它会记录 ssl 握手错误:
2016/09/19 22:38:08 [info] 10114#10114: *2 SSL_do_handshake() failed (SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher) while SSL handshaking, client: 108.162.242.24, server: 0.0.0.0:443
Run Code Online (Sandbox Code Playgroud)
实际上,您已经使用选项ssl_ecdh_curve在 Nginx 中配置了Diffie Hellman 密钥交换,但您还没有提供参数文件。因此,您必须使用选项ssl_dhparam并且必须使用 openssl 创建一个文件。
创建文件:
openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Run Code Online (Sandbox Code Playgroud)
在 Nginx 中使用文件及以上 Diffie Hellman 配置:
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_ecdh_curve secp384r1;
Run Code Online (Sandbox Code Playgroud)