Total Pageviews

Thursday 30 June 2022

HTTPS安全优化配置最佳实践指南

 SSL/TLS 简单说明

描述: 当下越来越多的网站管理员为企业站点或自己的站点进行了SSL/TLS配置, SSL/TLS 是一种简单易懂的技术,它很容易部署及运行,但要对其进行安全部署的情况下通常是不容易。

如果想掌握如何配置一个安全的 web 服务器或应用,往往需要系统管理员和开发者去了解 SSL 和 TLS 相关的技术, 这无疑会耗费很大的精力去看相关的技术文档,乏味且宽泛并加大了学习成本。

所以本篇文章主要是为了让系统管理员或开发者用尽可能少的时间部署一个安全的 web 站点或应用,即 SSL 和 TLS 部署最佳实践,但在学习实践之前我们需要了解一下SSL/TLS 相关术语,避免在后续实践中一头雾水。
 

如何让HTTPS站点评级达到A+? 还得看这篇HTTPS安全优化配置最佳实践指南:

https://mp.weixin.qq.com/s/ggU_5sIZXQGhdZkUOa1waw


 如何让HTTPS站点更加安全?这篇HTTPS安全加固配置最佳实践指南就够了:

https://mp.weixin.qq.com/s/Evt0P9lN7rTobDlYNRPaDA

前置知识推荐了解:
    HTTPS原理介绍以及证书签名的申请配置 (https://mp.weixin.qq.com/s/S-ZgJ3tFhmU4qvt80QwKqw)


    SSL与TLS协议原理和证书签名生成实践指南 (https://mp.weixin.qq.com/s/g-X8UPNwIkuR_Qd2MDvVQw)

SSL/TLS 相关术语一览
EV : EV证书(Extended Validation Certificate)是一种根据一系列特定标准颁发的X.509电子证书,根据要求,在颁发证书之前,证书颁发机构(CA)必须验证申请者的身份。不同机构根据证书标准发行的扩展验证证书并无太大差异,但是有时候根据一些具体的要求,特定机构发行的证书可以被特定的软件识别。
OV : OV证书(Organization Validation SSL),指需要验证网站所有单位的真实身份的标准型SSL证书,此类证书不仅能够起到网站信息加密的作用,而且能向用户证明网站的真实身份。
DV : DV证书(Domain Validation SSL),指需要验证域名的有效性。该类证书只提供基本的加密保障,不能提供域名所有者的信息。
CAA : DNS Certification Authority Authorization,使用DNS来指定该域名可以由哪些CA机构签发证书,这不是为TLS层的安全提供保证,而是作为CA签发证书程序中的一部分。使用CAA可以避免一些CA签发错误证书的情况。
CSR : CSR(Certificate Signing Request),在PKI系统中,CSR文件必须在申请和购买SSL证书之前创建,也就是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件
CT : CT (Certificate Transparency) 证书透明,Certificate Transparency的目标是提供一个开放的审计和监控系统,可以让任何域名所有者或者CA确定证书是否被错误签发或者被恶意使用,从而提高HTTPS网站的安全性。
CRL : CRL(Certificate revocation list 证书吊销列表)是一个已经被吊销的数字证书的名单,这些在证书吊销列表中的证书不再会受到信任,但目前OCSP(在线证书状态协议)可以代替CRL实现证书状态检查。
OCSP : OCSP(Online Certificate Status Protocol)是一个用于获取X.509数字证书撤销状态的网际协议,在RCF 6960中定义,作为证书吊销列表的替代品解决公开密钥基础建设(PKI)中使用证书吊销列表而带来的多个问题。协议数据传输过程中使用ASN.1编码,并通常创建在HTTP协议上
OCSP Stapling : OCSP装订,是TLS证书状态查询扩展,作为在线证书状态协议的替代方法对X.509证书状态进行查询,服务器在TLS握手时发送事先缓存的OCSP响应,用户只要验证该响应的时效性而不用再向数字证书认证机构(CA)发送请求,可以加快握手速度。
RSA : RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。对极大整数做因数分解的难度决定了RSA算法的可靠性,支持签名和加密。
ECC : ECDSA(椭圆曲线签名算法)的常见叫法,和RSA同时具有签名和加密不同,它只能做签名,它的优势是具有很好的性能、大小和安全性更高。
DH/DHE : Diffie-Hellman(DH)密钥交换是一种密钥交换的协议,DH的诀窍是使用了一种正向计算简单、逆向计算困难的数学函数,即使交换中某些因子已被知晓,情况也是一样。DH密钥交换需要6个参数,其中两个(dh_p和dh_g)称为域参数,由服务器选取,协商过程中,客户端和服务器各自生成另外两个参数,相互发送其中一个参数(dh_Ys和dh_Yc)到对端,在经过计算,最终得到共享密钥。临时Diffie-Hellman(ephemeral Diffie-Hellman,DHE)密钥交换中没有任何参数被重复利用。与之相对,在一些DH密钥交换方式中,某些参数是静态的,并被嵌入到服务器和客户端的证书中,这样的话密钥交换的结果是一直不变的共享密钥,就无法具备前向保密的能力。
ECDH/ECHDE : 椭圆曲线Diffie-Hellman(elliptic curve Diffie-Hellman,ECDH)密钥交换原理与DH相似,但是它的核心使用了不同的数学基础,ECHD基于椭圆曲线加密,ECDH密钥交换发生在一条由服务器定义的椭圆曲线上,这条曲线代替了DH中域参数的角色,理论上,ECDH支持静态的密钥交换。临时椭圆曲线Diffie-Hellman密钥交换,和DHE类似,使用临时的参数,具有前向保密的能力。
RC4 : 是一种流加密算法,对称加密,密钥长度可变。由于RC4算法存在弱点,2015年2月所发布的 RFC 7465 规定禁止在TLS中使用RC4加密算法, Chrome 48版本开始会拒绝与「以 RC4 做为对称加密算法的 CipherSuite」建立 TLS 连接 。
3DES : 在加密套件中很多的密码使用的是3DES_EDE_CBC这种类型的,在维基上3DES提供的bits数是192bits(168+24),但由于Meet-in-the-middle attack攻击的影响,只能提供112bits的安全。因此在等级评定上使用192bits,在套件的安全性上使用112bits.
PSK : PSK 是“Pre-Shared Key”的缩写。就是 预先让通讯双方共享一些密钥(通常是对称加密密钥), 这种算法用的不多它的好处是:不需要依赖公钥体系,不需要部属 CA 证书。不需要涉及非对称加密,TLS 协议握手(初始化)时的性能好于 RSA 和 DH,密钥交换时通讯双方已经预先部署了若干个共享的密钥为了标识多个密钥,给每一个密钥定义一个唯一的 ID客户端通过ID 和服务端进行通讯。
SRP : TLS-SRP( Secure Remote Password)密码套件有两类:第一类密码套件仅使用SRP认证。第二类使用SRP认证和公共密钥证书来增加安全性。
TLS GREASE : 为了保持可扩展性,服务器必须忽略未知值,是Chrome 推出的一种探测机制。GREASE for TLS (https://tools.ietf.org/html/draft-davidben-tls-grease-01)
AEAD : 全称是使用关联数据的已验证加密,Authenticated Encryption with Associated Data (AEAD) algorithms, 是用一个算法在内部同时实现cipher+MAC,是TLS1.2、TLS1.3上采用的现代加密算法,相关密码套件(https://tools.ietf.org/html/rfc6655):
 

TLS_RSA_WITH_AES_128_CCM = {0xC0,0x9C}
TLS_RSA_WITH_AES_256_CCM = {0xC0,0x9D)
TLS_DHE_RSA_WITH_AES_128_CCM = {0xC0,0x9E}
TLS_DHE_RSA_WITH_AES_256_CCM = {0xC0,0x9F}
TLS_RSA_WITH_AES_128_CCM_8 = {0xC0,0xA0}
TLS_RSA_WITH_AES_256_CCM_8 = {0xC0,0xA1)
TLS_DHE_RSA_WITH_AES_128_CCM_8 = {0xC0,0xA2}
TLS_DHE_RSA_WITH_AES_256_CCM_8 = {0xC0,0xA3}


AES-GCM : AES-GCM是一种AEAD,是目前TLS的主力算法,互联网上https流量的大部分依赖使用AES-GCM。
ChaCha20-poly1305 : ChaCha20-poly1305是一种AEAD,提出者是Daniel J. Bernstein教授,针对移动互联网优化,目前Google对移动客户端的所有流量都使用ChaCha20-Poly1305
AES-CBC : 关于AES-CBC,在AES-GCM流行之前,TLS主要依赖AES-CBC,而由于历史原因,TLS在设计之初固定选择了MAC-then-Encrypt结构,AES-CBC和MAC-then-encrypt结合,为选择密文攻击(CCA)创造了便利条件,TLS历史上有多个漏洞都和CBC模式有关。

PFS : PFS(perfect forward secrecy)正向保密 ,在密码学中也可以被称为FS(forward secrecy),是安全通信协议的特性,要求一个密钥只能访问由它所保护的数据,用来产生密钥的元素一次一换,不能再产生其他的密钥,一个密钥被破解,并不影响其他密钥的安全性。
HPKP : 公钥固定,这是一种https网站防止攻击者使用CA错误颁发的证书进行中间人攻击的一种安全机制,用于预防诸如攻击者入侵CA偷发证书、浏览器信任CA签发伪造证书等情况,采用该机制后服务器会提供一个公钥哈希列表,客户端在后续的通信中只接受该列表上的一个或多个公钥。

  HPKP是一个响应头 Public-Key-Pins:max-age=xxx;pin-sha256=xxxx;includeSubDomains; 其中可以使用多个pin-sha256,pin-sha256的值是对证书公钥sha256的值,includeSubDomains决定是否包含所有子域名,在max-age所指定的时间内(秒),证书链中的证书至少一个公钥须和固定公钥相符,这样客户端才认为该证书链是有效的,
    还有一种响应头:Public-Key-Pins-Report-Only:max-age=xxx;pin-sha256=xxxx;includeSubDomains;report-uri=xxx,Public-Key-Pins-Report-Only 中的report-uri,决定是否回报违反HTTP公钥固定策略的事件。客户端进行HTTP公钥固定验证失败后,将把此次错误详情以JSON格式回报个report-uri参数中指定的服务器。

H2 : HTTP/2 的协议名称,口语叫法HTTP2和http/1.1 是一个概念,通过ALPN协商, HTTP/2 中只能使用 TLSv1.2+协议。

CSP : CSP,全称是 Content Security Policy,它有非常多的指令,用来实现各种各样与页面内容安全相关的功能。 这里只介绍两个与 HTTPS 相关的指令,更多内容可以看我之前写的《Content Security Policy Level 2 介绍》。

    block-all-mixed-content :前面说过,对于 HTTPS 中的图片等 Optionally-blockable 类 HTTP 资源,现代浏览器默认会加载。图片类资源被劫持,通常不会有太大的问题,但也有一些风险,例如很多网页按钮是用图片实现的,中间人把这些图片改掉,也会干扰用户使用。通过 CSP 的 block-all-mixed-content 指令,可以让页面进入对混合内容的严格检测(Strict Mixed Content Checking)模式。在这种模式下,所有非 HTTPS 资源都不允许加载。跟其它所有 CSP 规则一样,可以通过以下两种方式启用这个指令。
    HTTP 响应头方式:Content-Security-Policy: block-all-mixed-content
    标签方式:upgrade-insecure-requests 通过 CSP 指令,可以让浏览器帮忙做这个转换。启用这个策略后,有两个变化页面所有 HTTP 资源,会被替换为 HTTPS 地址再发起请求, 页面所有站内链接,点击后会被替换为 HTTPS 地址再跳转;
    跟其它所有 CSP 规则一样,这个指令也有两种方式来启用,具体格式请参考上一节。需要注意的是 upgrade-insecure-requests 只替换协议部分,所以只适用于 HTTP/HTTPS 域名和路径完全一致的场景。

HSTS: 在网站全站 HTTPS 后,如果用户手动敲入网站的 HTTP 地址,或者从其它地方点击了网站的 HTTP 链接,依赖于服务端 301/302 跳转才能使用 HTTPS 服务。而第一次的 HTTP 请求就有可能被劫持,导致请求无法到达服务器,从而构成 HTTPS 降级劫持。该问题可以通过 HSTS(HTTP Strict Transport Security,RFC6797)来解决。

HSTS 是一个响应头,格式如下:Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]

        max-age,单位是秒,用来告诉浏览器在指定时间内,这个网站必须通过 HTTPS 协议来访问。也就是对于这个网站的 HTTP 地址,浏览器需要先在本地替换为 HTTPS 之后再发送请求。
        includeSubDomains,可选参数,如果指定这个参数,表明这个网站所有子域名也必须通过 HTTPS 协议来访问。
        preload,可选参数,后面再介绍它的作用。
        温馨提示: HSTS 这个响应头只能用于 HTTPS 响应;网站必须使用默认的 443 端口;必须使用域名且不能是 IP。而且启用 HSTS 之后一旦网站证书错误,用户无法选择忽略。

HSTS Preload List: HSTS 可以很好的解决 HTTPS 降级攻击,但是对于 HSTS 生效前的首次 HTTP 请求,依然无法避免被劫持。浏览器厂商们为了解决这个问题,提出了 HSTS Preload List 方案:内置一份可以定期更新的列表,对于列表中的域名,即使用户之前没有访问过,也会使用 HTTPS 协议。目前这个 Preload List 由 Google Chrome 维护,Chrome、Firefox、Safari、IE 11 和 Microsoft Edge 都在使用。

    如果要想把自己的域名加进这个列表,首先需要满足以下条件,不过值得注意的是即便满足了上述所有条件,也不一定能进入 HSTS Preload List,更多信息可以看这里。

        拥有合法的证书(如果使用 SHA-1 证书,过期时间必须早于 2016 年);
        将所有 HTTP 流量重定向到 HTTPS;
        确保所有子域名都启用了 HTTPS;
        输出 HSTS 响应头:
        max-age 不能低于 18 周(10886400 秒);
        必须指定 includeSubdomains 参数;
        必须指定 preload 参数;
        温馨提示: 通过 Chrome 的 chrome://net-internals/#hsts 工具,可以查询某个网站是否在 Preload List 之中,还可以手动把某个域名加到本机 Preload List。

SNI : SNI(服务器名称指示),这个是一个扩展的TLS协议,在该协议中,在TLS握手过程中客户端可以指定服务器的主机名称,这允许服务器在相同的IP和端口上部署多个证书,并允许在相同的IP地址上提供多个HTTPS网站或者基于TLS的服务。
SRI : HTTPS 可以防止数据在传输中被篡改,合法的证书也可以起到验证服务器身份的作用,但是如果 CDN 服务器被入侵,导致静态文件在服务器上被篡改,HTTPS 也无能为力。W3C 的 SRI(Subresource Integrity)规范可以用来解决这个问题。SRI 通过在页面引用资源时指定资源的摘要签名,来实现让浏览器验证资源是否被篡改的目的。只要页面不被篡改,SRI 策略就是可靠的, 有关 SRI 的更多说明请看Jerry Qu写的《Subresource Integrity 介绍》。SRI 并不是 HTTPS 专用,但如果主页面被劫持,攻击者可以轻松去掉资源摘要,从而失去浏览器的 SRI 校验机制。
ALPN : ALPN(应用层协议协商 Application-Layer Protocol Negotiation) 是一个进行应用层协议协商的传输层安全协议(TLS)扩展,ALPN允许应用层协商应该在安全连接上实行哪个协议,以避免额外且独立于应用层协议的往返协商通信, 它已被HTTP/2使用。
NPN : NPN(Next Protocol Negotiation) 下一协议协商,在TLS上允许应用层协商使用哪个协议,在2014年7月11日的RFC 7301中使用ALPN代替NPN。
STARTTLS : STARTTLS 是对纯文本通信协议(SMTP/POP3/IMAP)的扩展。它提供一种方式将纯文本连接升级为加密连接(TLS或SSL),而不是另外使用一个端口作加密通信。RFC 2595定义了IMAP和POP3的STARTTLS;RFC 3207定义了SMTP的;

Session ID : Session ID 完成SSL握手后会获得一个编号(Session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的缓存,双方就可以重新使用已有的”对话密钥”,而不必重新生成一把(握手的主要开销)。 因为要缓存每个连接的握手参数,服务端存储开销会比较大。
Session Ticket : Session ticket获得方式和SessionID类似,但是使用时是在每次握手时由服务器进行解密,获得加密参数。服务端无需维持握手参数,可以减少内存开销。

POODLE : POODLE(贵宾犬漏洞 CVE-2014-3566),贵宾犬漏洞的根本原因是CBC模式在设计上的缺陷,具体来说就是CBC只对明文进行了身份验证,但是没有对填充字节进行完整性校验。这使得攻击者可以对填充字节修改并且利用填充预示来恢复加密内容,让POODLE攻击成为可能的原因是SSL3中过于松散的填充结构和校验规则。
TLS POODLE :TLS POODLE(TLS 贵宾犬漏洞 CVE-2014-8730) 该漏洞的原理和POODLE漏洞的原理一致,但不是SSL3协议,而是在TLS协议上,TLS协议本身没有问题,但是在其实现上。一些开发人员在进行SSL3到TLS的转换的时候,没有遵守协议规定的填充要求,使得他们的实现容易受到POODLE攻击的威胁

DROWN : 一句话概括就是“使用SSLv2对TLS进行交叉协议攻击”,DROWN(CVE-2016-0800)表示仅支持SSL2是对现代服务器和客户端的威胁,它允许攻击者通过讲探测发送到支持SSLv2的服务器并使用相同的私钥来解密最新客户端和服务器之间的TLS连接,如果如果服务器容易受到DROWN的影响,有两种原因:

        服务器允许SSL2连接
        私钥用于允许SSL2连接的其他服务器,即使是另一个支持SSL/TLS的协议,例如,Web服务器和邮件服务器上使用相同的私钥和证书,如果邮件服务器支持SSL2,即使web服务器不支持SSL2,攻击者可以利用
        邮件服务器来破坏与web服务器的TLS连接。
        使用40bit的出口限制RSA加密套件,单台PC能在一分钟内完成工具,对于攻击的一般变体(对任何SSL2服务起作用)也可以在8个小时内完成。

Logjam : Logjam(CVE-2015-4000) 使用 Diffie-Hellman 密钥交换协议的 TLS 连接很容易受到攻击,尤其是DH密钥中的公钥强度小于1024bits。中间人攻击者可将有漏洞的 TLS 连接降级至使用 512 字节导出级加密。这种攻击会影响支持 DHE_EXPORT 密码的所有服务器。这个攻击可通过为两组弱 Diffie-Hellman 参数预先计算 512 字节质数完成,特别是 Apache 的 httpd 版本 2.1.5 到 2.4.7,以及 OpenSSL 的所有版本。

BEAST : BEAST(CVE-2011-3389) BEAST攻击针对TLS1.0和更早版本的协议中的对称加密算法CBC模式,初始化向量IV可以预测,这就使得攻击者可以有效的讲CBC模式削弱为ECB模式,ECB模式是不安全的
Downgrade : Downgrade attack(降级攻击) 是一种对计算机系统或者通信协议的攻击,在降级攻击中,攻击者故意使系统放弃新式、安全性高的工作方式,反而使用为向下兼容而准备的老式、安全性差的工作方式,降级攻击常被用于中间人攻击,讲加密的通信协议安全性大幅削弱,得以进行原本不可能做到的攻击。 在现代的回退防御中,使用单独的信号套件来指示自愿降级行为,需要理解该信号并支持更高协议版本的服务器来终止协商,该套件是TLS_FALLBACK_SCSV(0x5600)

MITM : MITM(Man-in-the-middle) 是指攻击者与通讯的两端分别创建独立的联系,并交换其所有收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个对话都被攻击者完全控制,在中间人攻击中,攻击者可以拦截通讯双方的通话并插入新的内容。一个中间人攻击能成功的前提条件是攻击者能够将自己伪装成每个参与会话的终端,并且不被其他终端识破。

Openssl Padding Oracle : Openssl Padding Oracle(CVE-2016-2107) openssl 1.0.1t到openssl 1.0.2h之前没有考虑某些填充检查期间的内存分配,这允许远程攻击者通过针对AES CBC会话的padding-oracle攻击来获取敏感的明文信息。

CCS : CCS(openssl MITM CCS injection attack CVE-2014-0224) 0.9.8za之前的Openssl,1.0.0m之前的以及1.0.1h之前的openssl没有适当的限制ChangeCipherSpec信息的处理,这允许中间人攻击者在通信之间使用0长度的主密钥。

FREAK : FREAK(CVE-2015-0204) 客户端会在一个全安全强度的RSA握手过程中接受使用弱安全强度的出口RSA密钥,其中关键在于客户端并没有允许协商任何出口级别的RSA密码套件。

Export-cipher : 在1998年9月之前,美国曾经限制出口高强度的加密算法。具体来说,限制对称加密强度为最大40位,限制密钥交换强度为最大512位。

CRIME : CRIME(Compression Ratio Info-leak Made Easy CVE-2012-4929),这是一种可攻击安全隐患,通过它可窃取启用数据压缩特性的HTTPS或SPDY协议传输的私密Web Cookie。在成功读取身份验证Cookie后,攻击者可以实行会话劫持和发动进一步攻击。
Heartbleed : Heartbleed(心血漏洞 CVE-2014-0160) 是Openssl的程序漏洞,如果使用带缺陷的Openssl版本,无论是服务器还是客户端,都可能因此受到攻击。此问题的原因是在实现TLS的心跳扩展时没有对输入进行适当的验证(缺少边界检查),该程序错误属于缓冲区过读,即可以读取的数据比应该允许读取的还多。


0x01 HTTPS安全实践指南

1.证书(certificate)与私钥(Private key).

描述: 在TLS中所有的安全性都从服务器的密码标识开始,所以我们需要一个强大的私钥以及有一个有效的和强大的证书来防止攻击者进行模拟攻击。

最佳安全实践
1.1) 建议使用2048位的RSA私钥或者128位的ECDSA私钥, 注意如果使用RSA私钥想要获得128位的安全性,则需要3072位的RSA key, 但会对性能造成一定影响, 所以推荐使用ECDSA key它是一种提供更好安全性和更好性能的替代方法。

1.2) 建议保护好你的私钥, 在可信计算机上用足够的熵生成私有密钥, 将密钥进行加密存储分配给指定人员管理, 可以访问拥有私钥的人越少越好, 除非保持相同的密钥对于公钥密钥很重要,否则每当获得新证书时,还应该生成新的私钥。

1.3) 建议从可信 CA 颁发获取证书, 选择CA时重点考虑如果以下条件提供商是否发生过安全风险、业务侧重点、是否提供对证书吊销列表(CRL)和在线证书状态协议(OCSP)撤销方法的支持、是否提供便捷的证书管理无法。

1.4) 建议使用强签名算法,证书安全性取决于用于签署证书的私钥的强度、签名中使用的散列函数的强度, 当前大多数的证书都依赖于SHA256散列函数,截止2022年。

1.5) 建议为指定站点名称申请对应证书而非使用通配符(泛域名)证书,通配符证书能满足更广泛的需求但如果准备将密钥暴露给更多的人员,特别是跨团队或部门,则避免使用它们。

温馨提示: 为了获得最佳效果,请提前获得证书,并在部署到生产业务环境之前至少一周,有助于避免在计算机上没有正确时间的一些用户的证书警告,以及避免与 CA 需要额外时间的 CA 失败的撤销检查,以向 OCSP 响应者传播有效的新证书.

2.中间件SSL/TLS服务器配置

描述: 使用正确的TLS服务器配置,您可以确保将凭据正确呈现给站点的访问者,仅使用安全的加密原语,并减轻所有已知的缺陷。

最佳安全实践

2.1) 建议使用完整的证书链, 通过情况下仅服务器证书不够的,我们需要两个或多个证书来建立完整的信任链,当部署具有有效证书但没有所有必要的中间证书的服务器时会发生常见的配置问题,这是因为无效的证书链有效地使服务器证书无效并导致浏览器警告。

 # 例如, 我采用Let'sEncrypt进签发的证书,生成nginx响应的证书配置链。
acme.sh  --installcert -d mydomain.com \
  --key-file /etc/nginx/ssl/mydomain.com.key \
  --fullchain-file /etc/nginx/ssl/fullchain.cer \
  --reloadcmd "service nginx force-reload"

# Nginx 中证书链与证书密钥配置
ssl_certificate      /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key  /etc/nginx/ssl/mydomain.com.key;

2.2) 建议选择使用安全的SSL/TLS协议, 避免使用 SSL v2,SSL v3, 当前推荐使用 TLS v1.0,TLS v1.1和TLS v1.2 以及 TLS 1.3 协议以消除所有过时和不安全的功能。

# Nginx
# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;

2.3) 建议选择使用安全的套件, 为了安全通信您必须首先确定您正在与所需方(而不是通过将窃听的其他人)直接沟通并安全地交换数据则需要至少128位加密的AEAD套件, 并且在配置中避免使用如下加密套件:
NULL 密码套件不提供加密
匿名 Diffie-Hellman(ADH)套件不提供身份验证
弱密码(通常为 40 和 56 位)的套件使用可以轻松破坏的加密
MD5 密码套件是不安全的,容易被碰撞检测
RC4 密码套件是不安全的
DES/3DES 密码套件缓慢而虚弱

例如, Nginx 中的ssl_ciphers配置项里加入不支持如下 !NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DES:!3DES:!MD5:!RC4; 密码套件。
# 使用以RSA和ECDSA键为基础的以下套件配置,作为起点(使用标准 TLS 套件名称):
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-SHA
ECDHE-ECDSA-AES256-SHA
ECDHE-ECDSA-AES128-SHA256
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-RSA-AES128-SHA256
ECDHE-RSA-AES256-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-SHA
DHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA256
DHE-RSA-AES256-SHA256

# 使用 openssl 命令查看指定套件对应的标准 TLS 套件名称以及支持的协议。
openssl ciphers -V 'ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:HIGH:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DES:!MD5:!RC4;' | column -t
0x13,0x02  -  TLS_AES_256_GCM_SHA384          TLSv1.3  Kx=any   Au=any    Enc=AESGCM(256)             Mac    =AEAD
0x13,0x03  -  TLS_CHACHA20_POLY1305_SHA256    TLSv1.3  Kx=any   Au=any    Enc=CHACHA20/POLY1305(256)  Mac    =AEAD
0x13,0x01  -  TLS_AES_128_GCM_SHA256          TLSv1.3  Kx=any   Au=any    Enc=AESGCM(128)             Mac    =AEAD
0xC0,0x2F  -  ECDHE-RSA-AES128-GCM-SHA256     TLSv1.2  Kx=ECDH  Au=RSA    Enc=AESGCM(128)             Mac    =AEAD

# Nginx
# 推荐安全配置(牺牲了兼容性)生产环境中请根据业务需要配置。
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

2.4) 建议选择合适的协议在SSLv3及更高版本的协议版本中, 将通用性安全较强的套件放在首位,使服务器主动选择最佳可用加密套件对于实现最佳安全性至关重要。

2.5) 建议使用FS前向保密, FS有时也称为完全前向保密是一种协议功能,可实现不依赖服务器私钥的安全对话, 对于不提前向保密的密码套件,如果有可以恢复服务器的私钥的人就可以解密所有较早记录的加密对话(也就是可以先大量记录密文,再解密,比如您的证书到期后没有正确销毁,它的私钥就能用来解密非PFS的密文),所以我们应该使用 DHE 套件作为 ECDHE 后备并且避免 RSA 密钥交换(除非必要)。

2.6) 建议使用强的密钥交换算法,前面我们说不建议选择经典的短暂的 Diffie-Hellman密钥交换(DHE)以及RSA 密钥交换(不提供FS前向保密),通常推荐其椭圆曲线变体 ECDHE 密钥交换,它更加安全和快速。

温馨提示: 我们建议您始终首先在分段环境中测试TLS配置,仅在确定所有内容按预期工作时将更改应用到生产环境。请注意,以上是一个通用列表,并不是所有系统(特别是较旧的)支持所有套件。

3.SSL/TLS站点性能

描述: 本章节HTTPS安全是我们讨论的重点,于此同时我们也需要关注配置了TLS站点的性能, 一个不符合性能标准的安全服务无疑将被丢弃。通过正确配置TLS服务器访问其站点时速度将会有很大提升, 例如使用现代协议(例如 HTTP/2),甚至可能比明文通信更快。。

最佳安全实践
3.1) 建议避免使用过度安全的密钥长度, 使用超过 2048 位的 RSA 密钥和强大于 256 位的 ECDSA 密钥会浪费 CPU 功耗,并可能会损害用户体验。

3.2) 建议使用 session 恢复, 会话恢复是一种性能优化技术,可以节省昂贵的密码操作的结果,并重复使用一段时间.  

# Nginx
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
ssl_session_tickets off;

3.3) 建议使用 WAN 优化和启用 HTTP/2, 通常TLS 开销不是来自CPU的加密操作,而是来自网络延迟, 只有在 TCP 握手完成后才能启动TLS握手,需要进一步交换数据包,并且离开服务器的距离更远, 所以最小化延迟的最佳方法是避免创建新的连接,换句话说就是保持现有的连接长时间(keep-alives)。
    

# Nginx
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
}
......

3.4) 建议缓存网站中公共的静态资源, 通过TLS进行通信时浏览器可能会认为所有流量都是敏感的, 默认的浏览器在使用中会缓存某些静态资源但是一旦关闭浏览器所有缓存内容可能会丢失, 所以为了获得性能提升我们需要长期缓存一些静态资源。

3.5) 建议使用 OCSP Stapling, OCSP 装订是 OCSP 协议的扩展,可以直接从服务器提供撤销信息作为 TLS 握手的一部分。因此客户端不需要联系 OCSP 服务器进行带外验证,并且总体 TLS 连接时间显着减少。
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

3.6) 建议使用 ECDSA 密钥进行快速加密, 在选择加密套件时除了保证其安全性还需要其良好的性能表现, 尽可能使用支持硬件加速 AES 的 CPU。

温馨提示: 用于建立安全连接的密码握手是一种操作,其费用受私钥大小的高度影响,使用太短的密钥是不安全的,但使用太长的密钥将导致“太多”的安全性和缓慢的操作。
温馨提示: 残疾或非功能性会话恢复机制可能会引起显着的性能损失。
温馨提示: OCSP装订是一种重要的优化技术,但并不是所有的网络服务器都提供了可靠的 OCSP 装订实现。

4.HTTP与应用安全

描述: HTTP 协议和 Web 应用交付的周边平台在 SSL 诞生后继续快速发展, 所以在进行TLS服务器配置时它们也是最重要的一环。

最佳安全实践
4.1) 建议加密无处不在, https加密不能是可选项,可靠地保护网站通信的唯一方法是无一例外地执行加密。

4.2) 建议消除混合内容, 请将任何地方的所有内容都 HTTPS 化(全站 HTTPS), 通过 TLS 传输但是包含不通过 TLS 传输的资源(例如,JavaScript 文件,images,CSS 文件)的页面, 可能会被一个活跃的中间人(MITM)攻击者可以搭载一个单独的未受保护的 JavaScript 资源,便有可能劫持用户的会话。

4.3) 建议使用可信第三方js或者css并且第三方必须是警告https加密的从而避免MITM 攻击, 于此同时使用子资源完整性(SRI)的新技术,可用于通过第三方资源来减少潜在的风险。

4.4) 建议配置安全cookie,要正确安全网站需要 TLS,而且所有的 Cookie 在创建时都被明确标记为安全的,为了获得最佳效果,请考虑为您的 Cookie 添加加密完整性验证或甚至加密。

4.5) 建议进行安全 HTTP 压缩, TIME 和 BREACH 专注于使用 HTTP 压缩压缩的 HTTP 响应实体中的秘密,HTTP 压缩是必需的不能关闭。

4.6) 建议部署配置 CSP ,内容安全策略(CSP)是网站可以用来限制浏览器操作的安全机制。尽管最初旨在解决跨站点脚本(XSS),CSP 不断发展并支持对增强TLS安全性有用的功能, 部署CSP可以防止第三方混合内容,通常使用Strict-Transport-Security响应头。

4.7) 建议不要缓存敏感内容

4.8) 考虑其它威胁, TLS 旨在仅解决安全机密和您与用户之间通信的完整性的一个方面,但还有许多其他威胁需要处理,确保您的网站尽可能的减少攻击面。

温馨提示: 下述配置是不一定是部署 CSP 的最佳方法,为了提供不破坏混合内容以外的任何内容的示例,我不得不禁用某些默认安全功能。随着时间的推移,当您了解 CSP 的更多信息时,您应该更改您的策略以使其恢复。

Content-Security-Policy: default-src https: 'unsafe-inline' 'unsafe-eval'; connect-src https: wss:

5.定期HTTPS检查避免已知问题

描述: 近几年来已经发生了几次严重的 SSL 和 TLS 攻击,但是如果您正在运行最新的openssl软件以及使用上述指南中的协议和加密套件建议,那么它们通常不会关心您。但是没有什么是完全安全的,所以为了保持对安全性的了解, 你应该排查和关注https相关漏洞, 以便于在第一时间保护或更新您的TLS服务器配置。

所以通常情况下我建议定期使用全面的 SSL/TLS 评估工具来验证您的配置,以确保您开始安全,对于公共网站建议您使用如下SSL实验室服务器进行站点https测试评估。

最佳安全实践
5.1) 建议定期使用如下SSL、TLS 评估工具对TLS配置进行检查评估。
        国外推荐:
        ssllabs : 网站地址(https://www.ssllabs.com),其检测内容非常的详细,包括证书、协议以及客户端模拟和兼容行。
        cdn77 : 网站地址(https://www.cdn77.com/tls-test), 功能单一只针对 TLS 、SSL协议版本进行评估。

国内推荐:

https://myssl.com,这个是国内的检测站点与 ssllabs 相似,但感觉界面更清爽,证书检测的功能更多,访问速度也是快很多,它还可以为您的https站点进行多方面综合的评级,其中包括了证书、SSL协议、加密套件、漏洞、不安全的外链等等,便于网站管理人员排查验证服务器应用证书配置是否正确。

5.2) 建议排查验证配置的TLS服务器是否使用下述相关漏洞所关联的openssl版本、加密套件以及脆弱的SSL、TLS协议。
    DROWN 漏洞
    OpenSSL Padding Oracle 攻击
    FREAK漏洞
    Logjam漏洞
    OpenSSL CCS 注入漏洞
    心血漏洞(Heartbleed)
    POODLE漏洞
    CRIME漏洞

5.3) 了解或者使用 HPKP, 公共密钥固定旨在使网站运营商有权限制哪些 CA 可以为其网站颁发证书。Google 已经部署了这个功能了一段时间(硬编码到他们的浏览器,Chrome),并且已被证明是非常有用的,以防止攻击并使公众了解它们, 但是需要一定的成本,部署需要大量精力和专业知识。

5.4) 建议配置使用 DNSSEC, 全称是域名系统安全扩展(Domain Name System Security Extensions),它是一种增加域名系统完整性的技术,是由IETF提供的一系列DNS安全认证的机制(可参考RFC2535)它提供一种可以验证应答信息真实性和完整性的机制,利用密码技术,使得域名解析服务器可以验证它所收到的应答(包括域名不存在的应答)是否来自于真实的服务器,或者是否在传输过程中被篡改过。通过DNSSEC的部署,可以增强对DNS域名服务器的身份认证,进而帮助防止DNS缓存污染等攻击。(配置示例请参考下小节的实践配置)

    简单的说,DNSSEC依靠数字签名保证DNS应答报文的真实性和完整性:

DNSSEC运作方式

5.5) 建议为电子邮件系统配置使用 DANE , DANE一种将X.509证书绑定到DNS中的机制, 可用于存储自签名证书或者从CA签发的特定X.509证书, 其中, 证书作为DNS资源记录通过DNSSEC来实现其来源验证和完整性保护,根据证书用途的不同, 基于DANE的DNS资源记录也有所不同, DANE协议的动机之一是解决现有的基于X.509的PKI的问题. 例如, DANE在应对欺诈证书、处理证书撤销、创建可全球发布和检索证书的管理机制并允许自签名证书授权等方面提供了很好的解决方式.

实践配置
1.在腾讯云DNSPod控制台开启DNSSEC流程操作。(PS: 收费版DNS套餐提供)
第一步:登陆 DNSPod 控制台开启 DNSSEC 服务。
    [控制台]- DNS 解析 - 我的域名 - 域名设置 - DNSSEC ,点击开启,即可查看该域名的 DS 记录。

第二步:前往域名注册商控制台添加 DS 记录。
    前面拿到的 DS 记录,还需在您域名注册商的控制台进行添加。(如果您的域名同样注册于腾讯云(DNSPod),则该步骤自动完成)
    PS: 该域名注册于腾讯云且属当前账号,系统将自动为您添加 DS 记录(https://docs.dnspod.cn/dns/dnssec-configuration/)
腾讯云中开启DNSSEC服务

第三步: 查看验证DNSSEC是否配置成功, 此处仍然以腾讯云为例.
    [控制台]- 域名注册 - 我的域名 -> 管理 -> 域名安全 -> DNSSEC 设置(点击管理) 
温馨提示: 目前只有少数注册商支持 DNSSEC ,如果您域名所在注册商不支持,可先将域名转入腾讯云,转入后方便一站管理,更可一键开启(带转入链接)

总结说明
描述: HTTPS安全也是网络安全的一个重要点,想要部署 TLS 是非常容易的,但其难点在于如何使用安全的配置来保障站点的安全。尤其是 Protocol 版本和 Cipher 需要小心选择和配置, 然后是一个门户或者其它用途的站点需要根据业务情况、针对用户群体、实际情况制定相应的TLS配置,最大限度的保证在安全的同时下对业务或者用户访问造成的影响越小越好,其次是针对某些严重危害应用或数据安全的应该及时修补,避免造成更大的影响。

0x02 HTTPS安全加固指南

描述: 当你的网站上了 HTTPS 以后,可否觉得网站已经安全了,其实不然前面说过想要部署TLS是非常容易,只需要证书与密钥文件然后根据中间件的配置ssl方法进行配置即可,默认的配置通常不满足https的安全需要,所以我们还需要进一步着重在于 HTTPS 网站的 Header 的相关配置。
1.连接安全性和加密选择

安全加固实践

    1.1) 建议部署配置 (HSTS) HTTP Strict Transport Security (HTTP 严格传输安全HSTS)响应头,它是TLS的安全网旨在确保即使在配置问题和实施错误的情况下安全性仍然保持不变,如果要使用HSTS我们只需要在网站添加一个新的响应头Strict-Transport-Security。再设置该响应头之后将会告诉浏览器只使用 HTTPS 连接到目标服务器,并且还防止一些潜在的中间人攻击,包括 SSL 剥离、会话 cookie 窃取。   

# 语法演示:
Strict-Transport-Security: max-age=<expire-time>Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload

# 配置示例: 浏览器防止指定站点以及将来的子域名都采用 HTTPS,最大年龄为1年(31536000),同时还允许预加载(加快速度):
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

# Nginx
# HSTS (ngx_http_headers_module is required) (63072000 seconds == 两年)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    2.2) 建议部署配置HPKP(HTTP Public Key Pins)响应头, 指示浏览器只与提供的 SSL/TLS 的 HASH 相符或存在于同一证书链的服务器相连接。简单的说如果 SSL/TLS 证书以一种意想不到的方式发生了变化,浏览器就无法连接到主机,这主要是针对受信任证书颁发机构(CA)或流氓 CA 证书颁发的伪造证书,用户可能会被骗安装。

        例如,浏览器连接到 https://mydomain.com,它存在这个头。header 告诉浏览器,如果证书 key 匹配,或者在发出证书链中有一个 key 匹配,那么在将来才会再次连接。其他的指令组合是可能的。它们都极大地减少了攻击者在客户端和合法主机之间模拟主机或拦截通信的可能性。

            Public-Key-Pins: max-age=5184000; pin-sha256="+oZq/vo3Kcv0CQPjpdwyInqVXmLiobmUJ3FaDpD/U6c="; pin-sha256="47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="

温馨提示: 设置 HSTS header Strict-Transport-Security 长的生命周期,即 max-age 的时间不能小于15552000,最好是半年及以上。
温馨提示: 确定是否需要为您的站点使用 PKP, 如果要是使用它请注意在SSL/TLS密钥需要更新时建立备份计划, 优先创建备份密钥和离线存储。

2.站点内容安全(Content security)
安全加固实践

    2.1) 避免混合 HTTPS 和 HTTP 内容(Mixed HTTPS and HTTP Content), 如果 HTTPS 部署在主站上,请将任何地方的所有内容都 HTTPS 化(全站 HTTPS)。

    2.2) 建议配置良好的内容安全策略(CSP - Content Security Policy)响应头, 它可以帮助抵御跨站点脚本(XSS)和其他注入攻击等攻击,现在主流的浏览器都是支持CSP头的。

        一个理想的CSP策略是基于白名单的方法,不允许任何东西,除了明确允许的内容,它还限制了 javascript 的来源和允许操作。

                      # 从限制性策略开始在必要时放松。
        Content-Security-Policy: default-src 'none';

        # 现在让我们允许自托管 scripts、images、CSS、fonts 和 AJAX,以及 jQuery CDN 托管脚本和 Google Analytics 的内容:
        Content-Security-Policy: default-src 'none'; script-src 'self' https://code.jquery.com https://www.google-analytics.com; img-src 'self' https://www.google-analytics.com; connect-src 'self'; font-src 'self'; style-src 'self';

        # 一个不那么严格的策略
        Content-Security-Policy: default-src 'self';

        # 更少的限制性策略,然后添加限制,非常不建议如此使用。
        Content-Security-Policy: default-src '*';

    2.3) 建议配置X-Frame-Options非标准的响应头, 它规定了控制站点是否可以放置在 <iframe>,<frame> 或 <object> 标签, 从而防止了clickjacking (点击劫持)攻击。所以启用它时请确定你的网站是否需要被允许呈现在一个 frame 中。

         # HTTP header: 完全不允许使用 sameorigin 拒绝或允许同源框架的选项
    X-Frame-Options: deny

    # 该响应头可选值
    DENY:不能被嵌入到任何iframe或者frame中。
    SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中
    ALLOW-FROM uri:只能被嵌入到指定域名的框架中

    # Nginx, 允许 music.163.com 放置在站点之中
    add_header X-Frame-Options ALLOW-FROM music.163.com;

    2.4) 建议配置XSS Protection(XSS过滤器) 可选, 跨站点脚本(XSS 或 CSS)的保护被构建到大多数流行的浏览器中,例如Chorme、IE等,但除了 Firefox 浏览器之外。
     
    # HTTP header:
    X-Xss-Protection: 1; block

    # Nginx:
    add_header X-XSS-Protection "1; mode=block";

    2.5) 建议配置Cache Control, 其表示缓存页面输出的首选项,适当的值随网站数据的性质而变化,但强烈推荐使用偏好, 如果允许缓存则应该将 max-age 值包含在 Cache-Control 以及 Etag 头文件中,以允许客户端缓存验证。

          # HTTP header:
    Cache-Control: public*

    # 可选参数:
    其中的一个 public,private,no-cache 或 no-store。

    2.6) 建议配置 Content Type Options,当浏览器以不同的方式处理来自服务器的文件时,MIME 嗅探就是服务器指令,例如当一个网站承载不受信任的内容(如用户提供的)时这是非常危险的。所以我们可以采用非标准的标头 X-Content-Type-Options 选项指示浏览器不做任何模仿指定类型的 MIME。
      
    # HTTP header:
    X-Content-Type-Options: nosniff

    # Nginx
    add_header X-Content-Type-Options nosniff;

    2.7) 建议验证子资源完整性(Subresource Integrity), 浏览器通常从外部域加载大量资源、javascript 和样式表, 例如第三方的js或者css,如果如果外部资源被破坏修改可能导致所以调用的站点存在一系列的脆弱性,所以我们设置外部 javascript 和样式表的完整性属性或者将外部脚本保存到本地路径中进行相对路径调用。
       
    # 完整性校验,该文件的SHA384值
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js" integrity="sha384-6ePHh72Rl3hKio4HiJ841psfsRJveeS+aLoaEf3BWfS+gTF0XdAqku2ka8VddikM"></script>

    # 或者本地相对调用
    <script>window.jQuery || document.write('<script src="/jquery.min.js"><\/script>')</script>

    2.8) 建议配置 Iframe Sandbox,如果你的站点存在iframe标签的使用,建议配置 sandbox 属性允许对 iframe 中可以进行的操作进行限制。
      
    #  设置 iframe 的 sandbox 属性,然后添加所需的权限。
    <iframe src="https://mydomain.com" sandbox="allow-same-origin allow-scripts"></script>

    2.8) 建议配置 TLS服务器时间同步,我们可使用网络时间协议(NTP)来保持服务器时钟的准确性,这是由于服务器包括所有响应的时间戳,不准确的时钟不会给客户机浏览器带来问题。

        ntpdate ntp.aliyun.com
        10 Apr 07:39:18 ntpdate[41371]: adjust time server 203.107.6.88 offset 0.000460 sec

    2.9) 建议配置 Cookie Security, 如果你的站点包含敏感信息的 cookie,特别是会话 id,需要标记为安全的,建议会话 cookie 应该与 HttpOnly 值进行标记 和 正确配置 HSTS 响应头。以防止它们被 javascript 访问,这可以防止攻击者利用 XSS 窃取会话 cookie。

              #  标记所有 cookie 安全为HttpOnly
    Set-Cookie: Key=Value; path=/; secure; HttpOnly, Key2=Value2; secure; HttpOnly

    # 例如, Tomcat7 中进行 HttpOnly 与 secure 配置
    # tomcat/conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" secure="true" />
    # tomcat/conf/web.xml
    <session-config>  
      <session-timeout>30</session-timeout>  
      <cookie-config>  
        <http-only>true</http-only>  
      </cookie-config>
    </session-config>

    2.10) 建议配置X-Robots-Tag,使用Meta Robots标记,可以真正阻止搜索引擎显示想保留在搜索结果之外的页面, 使用X-Robots-Tag HTTP标头可以达到相同的结果,如前所述,X-Robots-Tag还允许控制如何索引特定文件(类型),从而提供了更大的灵活性。
   
    # 防止搜索引擎显示使用PHP生成的文件.
    add_header X-Robots-Tag noindex;

    # 假如一个提供.doc文件的网站,但由于特定的原因,不希望搜索引擎为该文件类型建立索引.
    location ~* \.(doc|docx|pdf)$ {
      add_header X-Robots-Tag noindex, noarchive, nosnippet;
    }

温馨提示: 在Nginx中配置缓存策略非常简单, 我们只需要在指定的location规则下,加入类似于expires关键参数即可;
 
3.避免站点额外信息泄露
安全加固实践

    3.1) 建议将Web服务器的版本号去掉, 例如在 Nginx 中我们可以在 http{} 块中配置加入server_tokens off;, 便可以只包含服务器名称但去掉版本号Server: nginx;

    3.2) 建议取消掉许多 web 框架设置 HTTP 头 以及 识别框架或版本号,虽然可能对我们访问者无实际用途但对于搜索引擎或者其它Hacker攻击者来说这可是个好东西。所以建议从服务器响应中删除这些标头: X-Powered-By, X-Runtime, X-Version 和 X-AspNet-Version。

4.避免Web服务器中间件脆弱性

    4.1) 推荐使用最新稳定的OpenSSL版本, 但是需要注意在升级前请做好回滚措施或者测试,当前2022年4月10日 08:09:17最新的版本为openssl-1.1.1n。
  
    # 编译安装
    # https://www.openssl.org/source/
    wget -c http://www.openssl.org/source/openssl-1.1.1n.tar.gz
    tar -zxf openssl-1.1.1n.tar.gz && cd openssl-1.1.1n
    ./config --prefix=/usr/local/openssl
    make && sudo make install
    # lib 库加载到系统
    echo "/usr/local/openssl/lib" >> /etc/ld.so.conf.d/libc.conf
    ldconfig
    # 可以看到当下系统的Openssl版本已经更新到最新
    # root@weiyigeek-top:/usr/local/openssl/bin# openssl version
    # OpenSSL 1.1.1n  15 Mar 2022

    4.2) 推荐使用最新稳定的Web服务器软件及其版本, 例如 Nginx、Apache、Tomcat等中间件,请选择当前无脆弱性的版本。

     # Nginx 中间件版本查看
    $ nginx -V
    nginx version: nginx/1.21.6
    built by gcc 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04)
    built with OpenSSL 1.1.1n  15 Mar 2022
    TLS SNI support enabled
      configure arguments: --prefix=/usr/local/nginx --with-pcre=../pcre-8.45 --with-zlib=../zlib-1.2.11 --user=ubuntu --group=ubuntu --sbin-path=/usr/sbin/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --lock-path=/var/run/nginx.lock --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_geoip_module --with-threads --with-mail --with-mail_ssl_module --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-compat --with-file-aio --with-cc-opt='-Os -fomit-frame-pointer -g' --with-ld-opt=-Wl,--as-needed,-O1,--sort-common
 
 
0x03 HTTPS安全与兼容性如何抉择
描述: 很多网站HTTPS检测评分都达到了A或者A+, 但在看检测结果的时候发现类似于百度和淘宝这类大用户群的网站居然没有评级到A或者在使用的加密套件上有橙色的加密套件, 这是由于不同的业务侧重点不同,针对于浏览业务不涉及重要敏感信息的系统往往会牺牲一点安全性获取极致的兼容性。

温馨提示: 如果要适配IE6这款浏览器,那么SSL协议就必须得支持SSL2和SSL3(会受到POODLE漏洞问题影响), 所以除去CBC加密套件那就只剩下RC4系列的加密套件,实际上RC4也是不安全只是为了兼容某些老版浏览器的妥协。
温馨提示: 如果要放弃IE6并适配兼容XP上的IE8这款浏览器,唯一比较安全的就是3DES系列的加密套件,这差不多少是一种较好的方式。

如果你的服务器需要支持像IE6这种古董级别的浏览器可以采用方式1, 而如果想在保证相对安全性的同时也具有一定的兼容性可以采用方式2, 如果业务比较敏感为保证其安全性,忽略掉其兼容性,建议采用方式3(随着openssl版本迭代进行最好的安全性进行配置).

ssl_ciphers && ssl_protocols 在Nginx上配置示例
方式1.更好的兼容性(支持IE6老古董)

   ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

方式2.具有相对安全性和一定的兼容性(支持IE8~11)
 
# Nginx
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

# old configuration
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;

ssl_prefer_server_ciphers on;

方式3.建议根据系统中openssl版本中加密套件进行安全性配置,牺牲一定的兼容性。

 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:HIGH:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DES:!3DES:!MD5:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

博主当前配置:
   # Nginx
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE:ECDH:AES:HIGH:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DH:!DES:!MD5:!RC4;

# 以下密码需要明确禁止使用
!aNULL,不包含身份验证的DH密码,可能被中间人攻击
!eNULL,不采取密钥交换,也就是明文传输
!EXPORT,美国当年限制加密产品出口遗留的弱密码
!MD5,!RC4,!DES,这些密码已被证明攻破难度低

温馨提示: 我们可以访问mozilla公司提供的 SSL Configuration Generator 参考进行相应的配置参考(https://ssl-config.mozilla.org/),例如我们生成具有多种客户端的通用服务器Nginx SSL配置。

  # generated 2022-04-10, Mozilla Guideline v5.6, nginx 1.26.1, OpenSSL 1.1.1n, intermediate configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.26.1&config=intermediate&openssl=1.1.1n&guideline=5.6
server {
  listen 80 default_server;
  listen [::]:80 default_server;

  location / {
      return 301 https://$host$request_uri;
  }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  ssl_certificate /path/to/signed_cert_plus_intermediates;
  ssl_certificate_key /path/to/private_key;
  ssl_session_timeout 1d;
  ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
  ssl_session_tickets off;

  # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
  ssl_dhparam /path/to/dhparam;

  # intermediate configuration
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;

  # HSTS (ngx_http_headers_module is required) (63072000 seconds)
  add_header Strict-Transport-Security "max-age=63072000" always;

  # OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;

  # verify chain of trust of OCSP response using Root CA and Intermediate certs
  ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

  # replace with the IP address of your resolver
  resolver 127.0.0.1;
}

温馨提示: 我们可以采用openssl ciphers命令查看套件支持的协议:
 openssl ciphers -V 'ECDHE-RSA-AES128-GCM-SHA256:ECDH:AES:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:CAMELLIA:HIGH:!NULL:!aNULL:!eNULL:!EXPORT:!PSK:!ADH:!DES:!MD5:!RC4' | column -t
 
0x0n 入坑出坑
 
1.通过https证书安全合规检测发现缺少HTTP Strict-Transport-Security响应头.
解决办法: 例如,此处在 Nginx 服务器配置 server 段中添加如下内容 add_header Strict-Transport-Security "max-age=15768000;includeSubDomains;preload"; 以便于让浏览器响应并支持HSTS。

2.利用 myssl 站点的HTTPS安全报告工具检测,出现证书链不完整降级为B提示.
问题描述:
    浏览器的处理流程: 现代的浏览器都有证书自动下载的功能,但很多浏览器在安装后是使用系统内置的证书库,如果你缺失的那张CA证书 (信任的),在系统的内置证书库中不存在的话,用户第一次访问网站时会显示如下情况:(以Chrome为例), 即使你的证书确实是可信的,但依旧会显示成不可信,只有等到浏览器自动把缺失的那张CA证书从网上下载下来之后,访问该网站才会显示成可信状态。
    硬件设备的处理流程: 大量的硬件设备并不会像浏览器一样下载CA证书,如果你缺失的CA证书不再这些硬件设备的内置证书库中,那么使用这些硬件设备访问网站就会一直显示你的域名是不可信状态。

缺少证书链的问题和解决办法: 修复的办法很简单就是在部署证书的时候,把那张缺失的CA证书一并部署。目前一般的证书签发机构在签发证书的时候会把该CA证书一并打包,如果你没有也不同慌,我们可以使用MySSL提供的工具(https://myssl.com/chain_download.html)补全证书链。
# 下载证书链
curl https://myssl.com/api/v1/get_chain/5FFAFB3E5757A13292C4E3C0A045257E915D27DA > full_chain_ecc.crt

# 在 Nginx 中配置证书链
ssl_certificate  /app/ssl/mydomain.com_ecc/full_chain_ecc.crt;
ssl_certificate_key  /app/ssl/mydomain.com_ecc/mydomain.com.key;
 
在www.myssl.com里,可以下载你的域名的证书链文件。 
---------------------------------------------------------------------------------------

提升HTTPS性能的7条优化建议

自2018年7月起,谷歌浏览器开始将“HTTP”网站标记为“不安全”。在过去的几年中,互联网已经迅速过渡到HTTPS,Chrome浏览器的流量超过70%,并且Web排名前100位的网站中有80多个现在默认使用HTTPS,当前Nginx作为最常见的服务器,广泛用于负载均衡(LB)、网关、反向代理。考虑到这一点,让我们看一下Nginx调优技巧,改善Nginx + HTTPS的性能以获得更好的TTFB和更少的延迟。

1. 开启 HTTP/2

HTTP/2最初是在Nginx版本1.9.5中实现的,以取代spdy。在Nginx上启用HTTP/2模块很简单。

原先的配置:

listen 443 ssl;

修改为:

listen 443 ssl http2;

可以通过curl来验证:

curl --http2 -I https://domain.com/

2. 开启 SSL session 缓存

启用 SSL Session 缓存可以减少 TLS 的反复验证,减少 TLS 握手。 1M 的内存就可以缓存 4000 个连接,非常划算,现在内存便宜,尽量开启。

ssl_session_cache shared:SSL:50m; # 1m 4000个,
ssl_session_timeout 1h; # 1小时过期 1 hour during which sessions can be re-used.

3. 禁用 SSL session tickets

由于Nginx中尚未实现SSL session tickets,可以关闭。

ssl_session_tickets off;

4. 禁用 TLS version 1.0

1.3已经出来。1.0可以丢进历史垃圾堆

ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

修改为

ssl_protocols TLSv1.2 TLSv1.3;

5. 启用OCSP Stapling

如果不启用 OCSP Stapling 的话,在用户连接你的服务器的时候,需要去验证证书,这个验证证书的时间不可控,我们开启OCSP Stapling后,可以省掉这一步。

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/full_chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

6. 减小ssl buffer size

ssl_buffer_size 控制在发送数据时的 buffer 大小,默认情况下,缓冲区设置为16k,为了最大程度地减少TTFB(至第一个字节的时间),最好使用较小的值,这样TTFB可以节省大约30 – 50ms。

ssl_buffer_size 4k;

7. 调整 Cipher 优先级

更新更快的 Cipher放前面,这样延迟更小。

# 手动启用 cipher 列表
ssl_prefer_server_ciphers on;  # prefer a list of ciphers to prevent old and slow ciphers
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';









 
















 




















No comments:

Post a Comment