18.加密NGINX与upstream组或代理服务器之间的流量
本文介绍如何加密NGINX与upstream组或代理服务器之间的流量。
获取 SSL 服务器证书
可以从受信任的证书颁发机构 (CA) 购买服务器证书,也可以使用 OpenSSL 库创建自己的内部 CA 并生成自己的证书。服务器证书和私钥应放置在每个upstream服务器上。
获取 SSL 客户端证书
NGINX将使用SSL客户端证书向upstream服务器标识自己。此客户端证书必须由受信任的 CA 签名,并与相应的私钥一起在 NGINX 上配置。
还需要将upstream服务器配置为要求所有传入SSL连接的客户端证书,并信任颁发NGINX客户端证书的CA。然后,当NGINX连接到upstream时,它将提供其客户端证书,upstream服务器将接受它。
配置 NGINX
首先,将 URL 更改为upstream组以支持 SSL 连接。在 NGINX 配置文件中,在 proxy_pass 指令中为代理服务器或upstream组指定 “https” 协议:
location /upstream {
proxy_pass https://backend.example.com;
}
添加客户端证书和密钥,用于使用 proxy_ssl_certificate 和 proxy_ssl_certificate_key 指令在每个upstream服务器上对 NGINX 进行身份验证:
location /upstream {
proxy_pass https://backend.example.com;
proxy_ssl_certificate /etc/nginx/client.pem;
proxy_ssl_certificate_key /etc/nginx/client.key;
}
如果对upstream或您自己的 CA 使用自签名证书,则还包括proxy_ssl_trusted_certificate。该文件必须采用 PEM 格式。(可选)包括 proxy_ssl_verify 和 proxy_ssl_verfiy_depth 指令,让 NGINX 检查安全证书的有效性:
location /upstream {
#...
proxy_ssl_trusted_certificate /etc/nginx/trusted_ca_cert.crt;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
#...
}
每个新的 SSL 连接都需要客户端和服务器之间进行完整的 SSL 握手,这是相当占用 CPU 的。要让 NGINX 代理先前协商的连接参数并使用所谓的缩写握手,请包含 proxy_ssl_session_reuse 指令:
location /upstream {
#...
proxy_ssl_session_reuse on;
#...
}
(可选)您可 以指定使用的 SSL 协议和密码:
location /upstream {
#...
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
}
配置upstream服务器
每个upstream服务器都应配置为接受 HTTPS 连接。对于每个upstream服务器,使用 ssl_certificate 和 ssl_certificate_key 指令指定服务器证书和私钥的路径:
server {
listen 443 ssl;
server_name backend1.example.com;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/certs/server.key;
#...
location /yourapp {
proxy_pass http://url_to_app.com;
#...
}
}
使用 ssl_client_certificate 指令指定客户端证书的路径:
server {
#...
ssl_client_certificate /etc/ssl/certs/ca.crt;
ssl_verify_client optional;
#...
}
完整示例
http {
#...
upstream backend.example.com {
server backend1.example.com:443;
server backend2.example.com:443;
}
server {
listen 80;
server_name www.example.com;
#...
location /upstream {
proxy_pass https://backend.example.com;
proxy_ssl_certificate /etc/nginx/client.pem;
proxy_ssl_certificate_key /etc/nginx/client.key;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
proxy_ssl_trusted_certificate /etc/nginx/trusted_ca_cert.crt;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_session_reuse on;
}
}
server {
listen 443 ssl;
server_name backend1.example.com;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/certs/server.key;
ssl_client_certificate /etc/ssl/certs/ca.crt;
ssl_verify_client optional;
location /yourapp {
proxy_pass http://url_to_app.com;
#...
}
server {
listen 443 ssl;
server_name backend2.example.com;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/certs/server.key;
ssl_client_certificate /etc/ssl/certs/ca.crt;
ssl_verify_client optional;
location /yourapp {
proxy_pass http://url_to_app.com;
#...
}
}
}
在此示例中,proxy_pass指令中的“https”协议指定NGINX转发到上游服务器的流量受到保护。
当安全连接首次从NGINX传递到upstream服务器时,将执行完整的握手过程。proxy_ssl_certificate 指令定义upstream服务器所需的 PEM 格式证书的位置,proxy_ssl_certificate_key 指令定义证书私钥的位置,proxy_ssl_protocols 和 proxy_ssl_ciphers 指令控制使用哪些协议和密码。
下次NGINX传递到upstream服务器的连接时,会话参数会因为 proxy_ssl_session_reuse指令而复用,安全连接的建立速度更快。
proxy_ssl_trusted_certificate 指令命名的文件中的受信任 CA 证书用于验证upstream的证书。proxy_ssl_verify_depth指令指定检查证书链中的两个证书,proxy_ssl_verify指令验证证书的有效性。
上面是HTTP流量示例,下面是TCP流量示例
TCP流量完整示例
stream {
upstream backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
server {
listen 12345;
proxy_pass backend;
proxy_ssl on;
proxy_ssl_certificate /etc/ssl/certs/backend.crt;
proxy_ssl_certificate_key /etc/ssl/certs/backend.key;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
proxy_ssl_ciphers HIGH:!aNULL:!MD5;
proxy_ssl_trusted_certificate /etc/ssl/certs/trusted_ca_cert.crt;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_session_reuse on;
}
}