又拍云有一篇文章突破这5个技术难点,HTTPS会好用到飞起来~ ,总结的五个技术难点,HSTS、HTTP/2、OSCP stapling、Session ID、SNI技术。现在基本我都解决了。

目前在ssllabs上的评分:
sslbals上的评分已经达到A+,不过还有一点东西需要处理。然而在HTTP Security Report上测出来,问题还很多:
现在开始一块块地优化细节。

DNS CAA

sslbals测试出来Server Key and Certificate这一块DNS CAA是NO。
关于CAA的介绍这里有个链接https://sslmate.com/labs/caa/;大概就是说CAA是一种DNS记录类型,可以让你控制哪些证书颁发机构可以为您的域颁发证书。这个应该是跟CA方的支持有关系的:
我的证书CA是Symantec,从这里看确实是不支持,而且还是unknown policy。那这个可以不管了。

Session resumption

sslbals测试出来Protocol Details这里,Session resumption (caching)是No (IDs assigned but not accepted)。
这个是ssl_session配置的问题,主要是这两个配置:

ssl_session_cache 设置储存SSL会话的缓存类型和大小。
默认值:ssl_session_cache off
off为关闭,还有一些其它的缓存类型,不过这里建议使用shared共享缓存类型,这种方法更为有效。

ssl_session_timeout 客户端能够反复使用储存在缓存中的会话参数时间

看了一下session这一部分我的配置:

ssl_session_timeout 5m;

我把它改为:

ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;

共享缓存,缓存大小为50m,缓存时间1天。
修改后这一项就没问题了。现在ssllabs上测试出来,该绿的都绿了。剩下一些SNI,比如XP系统下的IE6IE8什么的,可能无法支持ssl,不过我觉得这个可以忽略了。现在用xp的ie的估计不多了,然后用这玩意访问我的博客的,估计可以忽略了。

X-Frame-Options 响应头

X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 <frame>, <iframe> 或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。
X-Frame-Options 有三个值:

DENY
表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。

SAMEORIGIN
表示该页面可以在相同域名页面的 frame 中展示。

ALLOW-FROM uri
表示该页面可以在指定来源的 frame 中展示。
就是说,如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载;如果设置为 SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。我们只需要设置为 SAMEORIGIN 就好。

配置 Apache
配置 Apache 在所有页面上发送 X-Frame-Options 响应头,需要把下面这行添加到 ‘site’ 的配置中:
Header always append X-Frame-Options SAMEORIGIN

配置 nginx
配置 nginx 发送 X-Frame-Options 响应头,把下面这行添加到 ‘http’, ‘server’ 或者 ‘location’ 的配置中:
add_header X-Frame-Options SAMEORIGIN;

CSP Level 2 规范中的 frame-ancestors 指令会替代这个非标准的 header。CSP 的 frame-ancestors 会在 Gecko 4.0 中支持,但是并不会被所有浏览器支持。然而 X-Frame-Options 是个已广泛支持的非官方标准,可以和 CSP 结合使用。

X-Content-Type-Options

X-Content-Type-Options响应HTTP头是服务器用来指示MIME类型Content-type头部不能被改变的标记。这允许不参加MIME类型探查法,换句话说就是网站管理员知道他们在说什么。
Nginx中配置:

add_header X-Content-Type-Options nosniff;

Public Key Pins

公钥固定(Public Key Pinning)是指一个证书链中必须包含一个白名单中的公钥,也就是说只有被列入白名单的证书签发机构(CA)才能为某个域名*.example.com签发证书,而不是你的浏览器中所存储的任何 CA 都可以为之签发。

从已知的密钥对(*.key)生成 pin-sha256:
openssl rsa -in /usr/local/nginx/cert/gzpblog.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

从EC 私钥文件生成 pin-sha256:
openssl ec -in my-ecc-key-file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64

从已知的证书申请文件(*.csr)生成 pin-sha256:
openssl req -in my-signing-request.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

从已知的证书(*.crt)生成 pin-sha256:
openssl x509 -in my-certificate.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

生成域名的 pin-sha256:
openssl s_client -servername www.gzpblog.com -connect www.gzpblog.com:443 | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

nginx配置:
add_header Public-Key-Pins ‘pin-sha256=”第一个base64″; pin-sha256=”备用base64″; max-age=时长; includeSubDomains’;

Server Banner

服务器版本号不应该存在在响应头中。
Nginx增加以下配置
server_tokens off;
就会去除版本号,比如nginx/1.10.3就变成了ningx

Web framework Information头部框架信息

移除一些头部信息,比如X-Powered-By, X-Runtime, X-Version and X-AspNet-Version等。

Nginx中加配置:

proxy_hide_header X-Powered-By;

PHP移除版本号,php.ini中设置expose_php:

expose_php = off

加入HSTS preload列表

HSTS preload预加载列表,这个列表之前也提过了,需要科学上网才能访问。

需要提交根域名:

注意一下提交之后,所有的子域名都会生效:

如果不符合要求会提示你,按提示修改就行;提交成功:

优化完成

HTTP Security Report上的评分:

现在就差HSTS预加载列表生效了,这个一般不会那么快,我们需要等一断时间。其它的基本都搞定了。