Nginx多主机共享443端口的安全证书问题

Nginx多主机共享443端口的安全证书问题

1. 事情的起源

同一台机器作为Jira/Gitlab的入口,采用Nginx作为统一代理入口,服务端口为443,配置上采用 server_name 进行区分。

Jira的域名为:  jira.xxxx.com
Gitlab域名为:  gitlab.xxxx.com

证书为正规机构颁发的统配证书 *.xxxx.com

在Nginx.conf中的顺序如下:Jira的配置在前面,Gitlab的配置在后面。

Jira 配置文件样例:

server {
    listen    443;
    ssl      on;
    server_name  jira.xxxx.com;

    ssl_protocols TLSv1.2;   # only allow tlsv1.2, 要求的安全级别较高

    ssl_certificate       "ssl/server.crt";
    ssl_certificate_key   "ssl/server.key";

    location /{
        proxy_pass http://jira.xxxx.com;
     }
}

Gitlab 配置文件样例:

server {
    listen  443;
    ssl      on;
    server_name  gitlab.xxxx.com;

    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;

    ssl_certificate       "ssl/server.crt";
    ssl_certificate_key   "ssl/server.key";

    location /{
        proxy_pass http://gitlab.xxxx.com;
     }
}

同事配置好上述以后,基本上都工作正常,通过浏览器访问基本上都能正常工作,除了个别浏览器Opera。 但是在Jenkins调用编译代码的过程中不能够正常工作,使用 curl -v 调试 gitlab 时候发现以下错误:

$ curl -v https://gitlab.xxxxx.com/backend
*   Trying 192.168.1.206...
* Connected to gitlab.xxxx.com (192.168.1.206) port 443 (#0)
* Server aborted the SSL handshake
* Closing connection 0
curl: (35) Server aborted the SSL handshake

2. 问题排查

2.1 端口抓包验证

使用 tcpudmp 在443端口上抓包分析:

通过上图发现 curl 默认是用的协议是TLS1.0,在客户端发送了 Client Hello 后,gitlab 服务网端直接发送了 Reset 复位了客户端的连接,但是后采用Chrome浏览器进行访问则能够正常访问Gitlab。 但是Nginx的配置文件中Gitlab的server项中 ssl_protocols TLSv1.2 TLSv1.1 TLSv1, 理论上讲应该可以能够正常访问。

问题的根源还是在于Nginx服务端Gitlab项的配置上。

2.2 更换端口进行测试

将 Gitlab 的端口 从 443 修改为 6443,然后使用 curl 进行测试一切正常,因此初步怀疑是 Jira 和 Gitlab 同时监听在 443 端口上,配置项上不一致导致。

将 Jira server中的配置项 ssl_protocols TLSv1.2 修改成 ssl_protocols TLSv1.2 TLSv1.1 TLSv1,然后继续使用 curl 测试 gitlab,则一切OK。

3. 问题分析

通过以上多次测试初步定位,是 Jira 和 Gitlab 同时监听在 443 端口上,不同的配置造成了干扰。 后仔细分析得知:

由于多个服务同时监听在443端口,采用 server_name 进行区分,这个行为是发生在
 Nginx 应用层的Virtual host,但是SSL的协议握手阶段处于 TCP 之上,位于 应用层协议之下, 
在SSL/TLS握手阶段,客户端还未明确发起访问HTTP Resource 的 Request,因此还无法确认到 
Virtual Host 的相关配置上,因此 SSL/TLS 发起连接过程中的server相关配置,证书和
SSL/TLS的相关配置,因此在 443 端口上第一个配置会生效(上例中的Jira的配置中设定的
 **ssl_protocols TLSv1.2** 会直接生效在 443 端口上,而后续配置的 
Gitlab 的 SSL/TLS 的配置则被忽略)

4. 总结

在 Nginx 中配置多个 server_name 而共享同一个端口时候的配置,需要格外注意,避免多个配置的不一致性。

发表评论

电子邮件地址不会被公开。 必填项已用*标注