Nginx-https安全最佳实践
一、介绍
使网站SSL/TLS的服务符合行业最佳实践,符合PCI DSS支付卡行业安全标准,符合Apple ATS规范
二、https安全实践事项
1.PCI DSS支付卡行业安全标准
PCI DSS,全称Payment Card Industry Data Security Standard,第三方支付行业数据安全标准,是由PCI安全标准委员会制定,力在使国际上采用一致的数据安全措施。
早在去年6月30号PCI安全标准委员会官方发表博文将于2018年6月30号(最晚),也就是本月月底禁用早期SSL/TLS,并实施更安全的加密协议 (TLS v1.1或更高版本,强烈建议使用TLS v1.2)以满足PCI数据安全标准的要求,从而保护支付数据。
解决方案
评估兼容性后,禁用 TLS1.0
nginx-
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
2.Apple ATS规范
自2017年1月1日起,根据苹果要求,所有iOS应用必须使用ATS(App Transport Security),即iOS应用内的连接必须使用安全的HTTPS连接。同时,苹果要求使用的不仅是一个简单的HTTPS协议连接,而且必须要满足iOS9中的新增特性。
App Transport Security(ATS) 是Apple为增强iOS App网络通信安全提出的安全功能,它会强制应用通过HTTPS(而不是HTTP)连接网络服务。
ATS默认的安全要求
- SSL证书由操作系统信任的CA根证书签发;
- 服务器必须支持传输层安全(TLS)协议1.2以上版本;
- 连接必须使用AES-128或AES-256对称加密算法;
- TLS协商算法必须通过规定的ECDHE密钥交换保证完全正向保密;
- SSL证书必须使用SHA256或更高的哈希算法签名;以及2048位以上RSA密钥或256位以上ECC密钥。
HTTP/2协议便使用TLS 1.2+版本作为安全加密层
解决方案
评估兼容性后,启用大于等于 TLS1.2
优化配置Ciphers,支持完全正向加密技术
nginx-
ssl_protocols TLSv1.2 TLSv1.3;
3.防御XSS攻击
跨站点脚本(XSS 或 CSS)的保护被构建到大多数流行的浏览器中,除了 Firefox 之外。
这种保护是用户可配置的,可以关闭。因此,明确要求浏览器在你的网站上使用它的 XSS 过滤器是个好主意。
解决方案
使用加入 HTTP header, 启用xss攻击防御
nginx-
add_header 'X-XSS-Protection' '1; mode=block' always;
4.启用HTTP严格传输安全(HSTS)
指示浏览器只使用 HTTPS 连接到目标服务器。这可以防止一些潜在的中间人攻击,包括 SSL 剥离,会话 cookie 窃取(如果没有被 适当保护)。如果遇到任何与证书相关的错误,它还可以阻止浏览器连接到网站。当浏览器访问一个设置相应 HTTP header 的 HTTPS 网站时,HSTS 将被激活。
HSTS 有一个固定期限,由 max-age 字段值控制。这个值可以是静态的,也可以是相对于将来某个特定日期的,你可以设置成 SSL 证书的过期时间。
解决方案
设置 HSTS header 长的生命周期,最好是半年及以上。
nginx-
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
5.预防降级攻击
可以看到 HSTS 可以很好的解决 HTTPS 降级攻击,但是对于 HSTS 生效前的首次 HTTP 请求,依然无法避免被劫持。浏览器厂商们为了解决这个问题,提出了 HSTS Preload List 方案:内置一份可以定期更新的列表,对于列表中的域名,即使用户之前没有访问过,也会使用 HTTPS 协议。
目前这个 Preload List 由 Google Chrome 维护,Chrome、Firefox、Safari、IE 11 和 Microsoft Edge 都在使用。
如果要想把自己的域名加进这个列表,首先需要满足以下条件:
- 拥有合法的证书(如果使用 SHA-1 证书,过期时间必须早于 2016 年);
- 将所有 HTTP 流量重定向到 HTTPS;
- 确保所有子域名都启用了 HTTPS;
- 输出 HSTS 响应头:
- max-age 不能低于 18 周(10886400 秒);
- 必须指定 includeSubdomains 参数;
- 必须指定 preload 参数;
即便满足了上述所有条件,也不一定能进入 HSTS Preload List,更多信息可以看这里。通过 Chrome 的 chrome://net-internals/#hsts 工具,可以查询某个网站是否在 Preload List 之中,还可以手动把某个域名加到本机 Preload List
Google已经提议一种叫TLSFALLBACKSCSV的SSL/TLS的拓展,旨在防止强制SSL降级。以下是升级后自动启用的OpenSSL版本:( http://nginx.org/en/docs/http/ngx_http_ssl_module.html )
OpenSSL 1.0.1 有 TLSFALLBACKSCSV 在 1.0.1j 及更高的版本.
OpenSSL 1.0.0 有 TLSFALLBACKSCSV 在 1.0.0o 及更高的版本.
OpenSSL 0.9.8 有 TLSFALLBACKSCSV 在 0.9.8zc 及更高的版本.
6.启用安全强度的加密套件
TLS1.3 废弃了RSA密钥交换方案(因为RSA不具有前向保密性),仅支持(EC)DHE密钥协商方案.
所以我在ssl_ciphers屏蔽了RSA的密钥交换方案,保留了tls1.3的最佳标准
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4:!RSA;
三、https安全实践配置
在nginx server 中加入
ssl_certificate /etc/nginx/cert.d/xxx.com.crt;
ssl_certificate_key /etc/nginx/cert.d/xxx.com.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_session_timeout 1h;
ssl_prefer_server_ciphers on;
#启用TLS1.1、TLS1.2要求OpenSSL1.0.1及以上版本
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_early_data on;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4:!RSA;
#ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header 'X-XSS-Protection' '1; mode=block' always;
TLS 1.3可以在第一个网络往返中完成共享密钥协商和身份认证,在完成共享密钥协商和身份认证后可以直接切换到应用数据协议,所以TLS 1.3 完整握手过程只需要一个网络往返(1-RTT)
关于nginx-ssl_ciphers
nginx中的加密套件是通过ssl_ciphers指令指定的,加密套件格式通常就是以‘:’分隔,然后写在一行.
ssl_ciphers 宏定义
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
HIGH代表是高级的加密套件,也就是密钥长度大于128位的,在openssl的ciphers中,还有MEDIUM和LOW,
但是LOW已经在openssl 1.0.2g中禁用了.
nginx-ssl_protocols与 ssl_ciphers的注意点
1. 在实际测试中发现,在低版本的nginx(1.17版本或者小于1.17版本)虽然两个配置都在server 块内,ssl_protocols 却属于全局配置(http配置),而 ssl_ciphers 却针对特定的虚拟主机(server配置)起作用, 如果server内配置了 ssl_protocols,那么nginx还是会用 全局配置 的覆盖server块的 配置,并且在全局配置和server都配置了ssl_protocols,语法不会提示有问题。
2. ssl_ciphers的配置就可以根据域名来区分开来。
解决办法:
低版本的nginx(1.17版本或者小于1.17版本) 全局配置(http配置)内加上ssl_protocols 。(隐患:会导致全局nginx使用新配置的ssl_protocols。好的建议是:升级nginx到1.19版本)
查看ssl整个连接过程
通过openssl工具来建立连接,查看整个连接过程,比如通过openssl s_client -connect xxx.com:443(这里端口要带,或者可以-h查看使用方法)
openssl s_client -connect xxx.com:443
openssl的ciphers查看加密套件
# openssl ciphers 'HIGH' -v|column -t
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384
ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
DH-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH/DSS Au=DH Enc=AESGCM(256) Mac=AEAD
DHE-DSS-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=DSS Enc=AESGCM(256) Mac=AEAD
DH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH/RSA Au=DH Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256
DHE-DSS-AES256-SHA256 TLSv1.2 Kx=DH Au=DSS Enc=AES(256) Mac=SHA256
DH-RSA-AES256-SHA256 TLSv1.2 Kx=DH/RSA Au=DH Enc=AES(256) Mac=SHA256
DH-DSS-AES256-SHA256 TLSv1.2 Kx=DH/DSS Au=DH Enc=AES(256) Mac=SHA256
查看加密套的复杂程度
# yum -y install nmap
# nmap --script ssl-cert,ssl-enum-ciphers -p 443 www.baidu.com
Starting Nmap 6.40 ( http://nmap.org ) at 2022-07-26 19:04 CST
Nmap scan report for www.baidu.com (14.215.177.39)
Host is up (0.0066s latency).
Other addresses for www.baidu.com (not scanned): 14.215.177.38
PORT STATE SERVICE
443/tcp open https
| ssl-cert: Subject: commonName=baidu.com/organizationName=Beijing Baidu Netcom Science Technology Co., Ltd/stateOrProvinceName=beijing/countryName=CN
| Issuer: commonName=GlobalSign RSA OV SSL CA 2018/organizationName=GlobalSign nv-sa/countryName=BE
| Public Key type: rsa
| Public Key bits: 2048
| Not valid before: 2022-07-05T05:16:02+00:00
| Not valid after: 2023-08-06T05:16:01+00:00
| MD5: ed19 4909 8287 a63d 206f 549a 2291 8c38
|_SHA-1: 486a edd1 6852 e597 4fa0 9246 b33c 5646 3dd9 9cd5
| ssl-enum-ciphers:
| SSLv3:
| ciphers:
| TLS_RSA_WITH_RC4_128_SHA - strong
| compressors:
| NULL
| TLSv1.0:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_RC4_128_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_RC4_128_SHA - strong
| compressors:
| NULL
| TLSv1.1:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_RC4_128_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_RC4_128_SHA - strong
| compressors:
| NULL
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - strong
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_ECDHE_RSA_WITH_RC4_128_SHA - strong
| TLS_RSA_WITH_AES_128_CBC_SHA - strong
| TLS_RSA_WITH_AES_256_CBC_SHA - strong
| TLS_RSA_WITH_RC4_128_SHA - strong
| compressors:
| NULL
|_ least strength: strong
Nmap done: 1 IP address (1 host up) scanned in 0.79 seconds
密码套件
密码套件是认证,加密和消息认证码(MAC)算法的组合
功能 | 算法 |
---|---|
密钥交换 | RSA,Diffie-Hellman,ECDH,SRP,PSK |
认证 | RSA,DSA,ECDSA |
批量密码 | RC4,3DES,AES |
消息验证 | HMAC-SHA256,HMAC-SHA1,HMAC-MD5,GCM-SHA384 |
加密套件的示例
ECDHE-RSA-AES256-GCM-SHA384
部分 | 描述 | 名字 |
---|---|---|
ECDHE | 密钥交换算法 | "短暂 - 椭圆曲线 - 迪菲 - 赫尔曼" 算法 |
RSA | 认证算法 | 非对称加密算法 |
AES256 | 对称加密算法 | 高级加密标准 |
GCM-SHA384 | 消息验证算法 |
握手时使用 ECDHE 算法进行密钥交换;用 RSA 签名和身份认证;握手后的通信使用 AES 对称算法,密钥长度 256 位;分组模式是 GCM, 摘要算法 SHA384 用于消息认证和产生随机数
ssl_ciphers屏蔽不安全的加密套
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4:!RSA;
这里额外屏蔽了RSA
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
四、注意事项
如有客户端因为超低版本无法访问,请使用最新版谷歌浏览器或者火狐浏览器
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?