在Nginx代理后台HTTPS服务时,有几个关键的参数需要配置,以确保代理服务器能够正确地与后端服务器进行通信。一些重要参数的介绍:
-
proxy_ssl_server_name:这个参数用于指定是否在TLS握手时通过SNI(Server Name Indication)传递主机名给后端服务器。默认情况下,这个参数是关闭的(off),开启的话是:on。这意味着如果后端服务器使用SNI来选择证书,而没有接收到正确的主机名,可能会导致SSL握手失败,也可以后台服务返回一个默认的证书。启用这个参数可以确保后端服务器收到正确的主机名,从而使用正确的证书进行SSL握手。
-
proxy_ssl_name:配置第一个参数开启时传递的主机名称。
-
proxy_ssl_certificate:指定客户端证书的文件路径,用于向后端服务器验证Nginx的身份。这对于双向SSL认证是必要的。
-
proxy_ssl_certificate_key:指定客户端证书的私钥文件路径,与proxy_ssl_certificate一起使用。
-
proxy_ssl_trusted_certificate:指定受信任的CA证书文件路径,用于验证后端服务器的证书。这对于自签名证书或内部CA颁发的证书是必要的。
-
proxy_ssl_verify:启用或禁用对后端服务器证书的验证。默认情况下,这个参数是关闭的(off),这意味着Nginx不会验证后端服务器返回的证书。启用这个参数可以提高安全性,但可能需要额外的配置,如指定受信任的CA证书。
-
proxy_ssl_verify_depth:指定验证后端服务器证书时的最大深度。这个参数通常与proxy_ssl_verify一起使用。默认值是: 1
-
proxy_ssl_protocols:指定允许的SSL/TLS协议版本。例如,可以设置为TLSv1 TLSv1.1 TLSv1.2,以限制只使用这些版本的协议。
-
proxy_ssl_ciphers:指定允许的加密套件。例如,可以设置为HIGH:!aNULL:!MD5,以限制只使用高强度且不包括某些已知弱点的加密套件。
-
proxy_ssl_session_reuse:启用或禁用SSL会话复用。启用这个参数可以减少建立SSL连接时的开销,提高性能。
Nginx作用反向代理与上游服务器使用HTTPS建连时,
- 默认不启用
SNI
,使用proxy_ssl_server_name on;
参数启用; - 默认不验证上游服务器返回的证书,开启的话使用
proxy_ssl_verify on;
- 开启上游证书验证后Nginx会使用配置文件中指定的CA验证上游服务器返回证书的合法性,同时也会比对证书中的CommonName信息。
实例1配置
server {
listen 80;
server_name www.dianduidian.com;
location / {
proxy_pass https://blog.dianduidian.com;
proxy_ssl_verify on; //开启nginx验证后台的证书合法性
proxy_ssl_trusted_certificate /etc/nginx/conf.d/cacert.pem; //配置信任的根证书,用于验证后台的证书是否合法
proxy_ssl_server_name on; ///开启了在进行tls通信链接握手时传hostname给后台,
proxy_ssl_name www.baidu.com; //这个就是配置的传递的主机名
}
}
实例2配置
场景是: 由外部nginx代理--->k8s集群的ingress---->代理内部的service: dashboard。都是用了https。 因为ingress代理service: dashboard是根据hostname来分流的。但是现在有个问题是:前端nginx代理是通过ip访问的,那么怎么设置nginx代理ingress时带上对应的域名呢?
proxy_set_header Host $http_host; 一开始时这样设置了,一直访问不了,这个配置proxy_set_header Host 确实是设置nginx访问后台时设置的Http请求的头部字段Host的,但是$http_host获取的值是当前请求的值,也就是https://47.xx.xx.22:446/ 这个请求的,这里就没有域名,所以nginx在访问后台ingress时,就没法设别域名,也就不能把请求转发到service: dashboard。后面我直接设置 proxy_set_header Host k8sdashboard.jtkjk8s.com;这样就可以了,这样就保证了nginx请求ingress把域名带过去了。从这里也可以得出一个结论: proxy_pass https://k8sdashboard.jtkjk8s.com:30443; 这个配置并不会让nginx把这个域名设置到http的头部字段Host字段上。
server {
listen 446 ssl;
server_name 47.xx.xx.22;
ssl_certificate /root/pki/ca.crt;
ssl_certificate_key /root/pki/private.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
client_max_body_size 0;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host k8sdashboard.jtkjk8s.com;
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;
proxy_ssl_name k8sdashboard.jtkjk8s.com;
proxy_ssl_server_name on;
proxy_ssl_verify off;
proxy_pass https://k8sdashboard.jtkjk8s.com:30443;
}
}
这个是k8s 的ingress 分流到内部的一个k8sdashboard服务上的配置。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jtktk8s-ingress
namespace: jtkjdev
annotations:
nginx.ingress.kubernetes.io/secure-backends: "true" #指定用https访问后台
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" #指定用https访问后台,这两个参数一起设置
nginx.ingress.kubernetes.io/proxy-ssl-verify: "false" #不验证服务端的证书合法性,因为我用的是自签名的
spec:
ingressClassName: nginx
rules:
- host: k8sdashboard.jtkjk8s.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: k8sdashboard
port:
number: 443
其他大牛的一些文章:Nginx反向代理,当后端为Https时的一些细节和原理-****博客