标题写到了打造顶级安全网站,不知道有没有夸张,不过目前网站评级确实已经是最高了,如果有错请指出。
先上一波评测图:
当网站刚刚建立时,默认只支持HTTP协议,此时我们需要做的第一步就是先升级HTTPS:
证书和私钥的生成:
1.创建服务器私钥,该命令会让你输入一个口令 server.key:
openssl genrsa -des3 -out server.key 1024
输入密码,确认密码,自己随便定义,但是要记住,后面会用到。
2创建签名请求的证书(CSR) server.csr
openssl req -new -key server.key -out server.csr
输出内容为:
Enter pass phrase for root.key: ← 输入前面创建的密码
Country Name (2 letter code) [AU]:CN ← 国家代号,中国输入CN
State or Province Name (full name) [Some-State]:BeiJing ← 省的全名,拼音
Locality Name (eg, city) []:BeiJing ← 市的全名,拼音
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany Corp. ← 公司英文名
Organizational Unit Name (eg, section) []: ← 可以不输入
Common Name (eg, YOUR name) []: ← 此时不输入
Email Address []:admin@mycompany.com ← 电子邮箱,可随意填
Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []: ← 可以不输入
An optional company name []: ← 可以不输入
4.备份一份服务器密钥文件
cp server.key server.key.org
5.在加载SSL支持的Nginx并使用上述私钥时除去必须的口令
openssl rsa -in server.key.org -out server.key
6.最后标记证书使用上述私钥和CSR server.crt
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
将证书配置到Nginx:
server{
#比起默认的80 使用了443 默认 是ssl方式 多出default之后的ssl
listen 443 default ssl;
#default 可省略
#开启 如果把ssl on;这行去掉,ssl写在443端口后面。这样http和https的链接都可以用
ssl on;
#证书(公钥.发送到客户端的)
ssl_certificate /home/server.crt;
#私钥,
ssl_certificate_key /home/server.key;
location ~ /\.
{
deny all;
}
}
将旧的地址重定向到HTTPS(避免以前被搜索引擎收录的页面继续使用HTTP请求):
server{
#兼容HTTP与HTTPS
listen 80;
listen 443 ssl;
ssl_certificate /home/server.crt;
ssl_certificate_key /home/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
if ($server_port = 80 ) {
return 301 https://$host$request_uri;
}
location ~ /\.
{
deny all;
}
}
此时网站已经支持HTTPS了,但是这样就安全吗?答案是否定的,请看下图:
此时浏览器提示不安全的链接,可能的原因有很多,比如你生成的证书和你目前使用的域名不匹配或者你是自己签发的CA,我们目前就是因为自己签发的证书导致的这个问题,所以要想拿到一个绿色通行证需要大家去找一些证书签发机构申请一个证书,证书有免费的只是限制比较多,具体大家百度,选择很多,所以这里就不再赘述了,拿到申请的证书后,访问就是绿色标识了。
此时网站已经有了绿色通道了,但是这里有个重点,你需要确认你的网站下所有访问全部使用HTTPS,否则你的网站评级最高是B,具体操作是使用浏览器F12进入调试模式,然后刷新网页,观察是否有HTTP请求,我这里就有一张图片是使用了外链,这个外链有一张图片是HTTP请求,此时编辑网站页面,将图片下载下来并上传至自己的站点,在引用外链的地方将src资源指向自己刚才上传的图片,由于我们的服务器已经使用了HTTPS,所以网站加载这张图片的时候会用HTTPS加载自己站点内的图片。
完成以上步骤,站点评级已经是A-了,要怎样让我们的站点达到最高评级呢?答案是开启HSTS,下面引用一下百度词库:
HSTS(HTTP Strict Transport Security)作用
HSTS可以用来抵御SSL剥离攻击。SSL剥离攻击是中间人攻击的一种,由Moxie Marlinspike于2009年发明。他在当年的黑帽大会上发表的题为“New Tricks For Defeating SSL In Practice”的演讲中将这种攻击方式公开。SSL剥离的实施方法是阻止浏览器与服务器创建HTTPS连接。它的前提是用户很少直接在地址栏输入https://,用户总是通过点击链接或3xx重定向,从HTTP页面进入HTTPS页面。所以攻击者可以在用户访问HTTP页面时替换所有https://开头的链接为http://,达到阻止HTTPS的目的。
HSTS可以很大程度上解决SSL剥离攻击,因为只要浏览器曾经与服务器创建过一次安全连接,之后浏览器会强制使用HTTPS,即使链接被换成了HTTP。
另外,如果中间人使用自己的自签名证书来进行攻击,浏览器会给出警告,但是许多用户会忽略警告。HSTS解决了这一问题,一旦服务器发送了HSTS字段,用户将不再允许忽略警告。
HSTS不足
用户首次访问某网站是不受HSTS保护的。这是因为首次访问时,浏览器还未收到HSTS,所以仍有可能通过明文HTTP来访问。解决这个不足目前有两种方案,一是浏览器预置HSTS域名列表,Google Chrome、Firefox、Internet Explorer和Spartan实现了这一方案。二是将HSTS信息加入到域名系统记录中。但这需要保证DNS的安全性,也就是需要部署域名系统安全扩展。截至2014年这一方案没有大规模部署。
由于HSTS会在一定时间后失效(有效期由max-age指定),所以浏览器是否强制HSTS策略取决于当前系统时间。部分操作系统经常通过网络时间协议更新系统时间,如Ubuntu每次连接网络时,OS X Lion每隔9分钟会自动连接时间服务器。攻击者可以通过伪造NTP信息,设置错误时间来绕过HSTS。解决方法是认证NTP信息,或者禁止NTP大幅度增减时间。比如Windows 8每7天更新一次时间,并且要求每次NTP设置的时间与当前时间不得超过15小时。
总结下来就是,当我们在浏览器敲入我们的域名进行加载的时候,浏览器默认会以HTTP方式访问,此时我们通过返回响应头的方式告诉浏览器服务器只允许HTTPS访问,然后当我们下次再加载这个域名的时候就是以HTTPS的方式访问了,然后上面提到了不足是指第一次访问的时候,还是HTTP的方式访问,相当于请求仅会在第2+N次后才会使用HTTPS请求,但是如果你足够细心的话,应该能注意到上面Nginx的配置,原理上讲应该可以弥补上面提到的不足:
if ($server_port = 80 ) {
return 301 https://$host$request_uri;
}
一台新的电脑会默认使用HTTP请求我们的服务器,也就是通过80端口请求,但是通过上面的配置,将80端口重定向到HTTPS,就避免了第一次通过HTTP请求的问题,并且由于我们开启了HSTS,我们第一次请求会给浏览器返回一个响应头让浏览器下次使用HTTPS请求,刚好又避免了服务器频繁重定向的问题,说了这么多,下面讲讲如何开启HSTS,在我们的ssl配置下面添加如下配置:
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
add_header X-Frame-Options "DENY";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
配置说明:
- ssl_ciphers 密码套件规则
- ssl_protocols 启动特定的加密协议
- ssl_prefer_server_ciphers 设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。