nginx下配置ssl本来是很简单的,无论是去认证中心买SSL安全证书还是自签署证书,但最近公司OA的一个需求,得以有个机会实际折腾一番。一开始采用的是全站加密,所有访问http:80的请求强制转换(rewrite)到https,后来自动化测试结果说响应速度太慢,https比 http慢慢30倍,心想怎么可能,鬼知道他们怎么测的。所以就试了一下部分页面https(不能只针对某类动态请求才加密)和双向认证。下面分节介绍。
免费的ssk证书可以去这里https://buy.wosign.com/申请个
默认nginx是没有安装ssl模块的,需要编译安装nginx时加入--with-http_ssl_module选项。
关于SSL/TLS原理请参考 这里,如果你只是想测试或者自签发ssl证书,参考 这里 。
提示:nignx到后端服务器由于一般是内网,所以不加密。
1. 全站ssl
全站做ssl是最常见的一个使用场景,默认端口443,而且一般是单向认证。
下面是Nginx 里面的配置
server {
listen 443;
server_name example.com;
root /apps/www;
index index.html index.htm;
ssl on;
ssl_certificate ../SSL/ittest.pem;
ssl_certificate_key ../SSL/ittest.key;
# ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
# ssl_prefer_server_ciphers on;
}
如果想把http的请求强制转到https的话:
server {
listen 80;
server_name example.me;
rewrite ^ https://$server_name$request_uri? permanent;
### 使用return的效率会更高
# return 301 https://$server_name$request_uri;
}
ssl_certificate证书其实是个公钥,它会被发送到连接服务器的每个客户端,ssl_certificate_key私钥是用来解密的,所以它的权限要得到保护但nginx的主进程能够读取。当然私钥和证书可以放在一个证书文件中,这种方式也只有公钥证书才发送到client。
ssl_protocols指令用于启动特定的加密协议,nginx在1.1.13和1.0.12版本后默认是ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2,TLSv1.1与TLSv1.2要确保OpenSSL >= 1.0.1 ,SSLv3 现在还有很多地方在用但有不少被攻击的漏洞。
ssl_ciphers选择加密套件,不同的浏览器所支持的套件(和顺序)可能会不同。这里指定的是OpenSSL库能够识别的写法,你可以通过openssl -v cipher 'RC4:HIGH:!aNULL:!MD5'(后面是你所指定的套件加密算法) 来看所支持算法。
ssl_prefer_server_ciphers on设置协商加密算法时,优先使用我们服务端的加密套件,而不是客户端浏览器的加密套件。
https优化参数
ssl_session_cache shared:SSL:10m;: 设置ssl/tls会话缓存的类型和大小。如果设置了这个参数一般是shared,buildin可能会参数内存碎片,默认是none,和off差不多,停用缓存。如shared:SSL:10m表示我所有的nginx工作进程共享ssl会话缓存,官网介绍说1M可以存放约4000个sessions。 详细参考serverfault上的问答ssl_session_cache。
ssl_session_timeout: 客户端可以重用会话缓存中ssl参数的过期时间,内网系统默认5分钟太短了,可以设成30m即30分钟甚至4h。
设置较长的keepalive_timeout也可以减少请求ssl会话协商的开销,但同时得考虑线程的并发数了。
提示:在生成证书请求csr文件时,如果输入了密码,nginx每次启动时都会提示输入这个密码,可以使用私钥来生成解密后的key来代替,效果是一样的,达到免密码重启的效果:
openssl rsa -in ittest.key -out ittest_unsecure.key
回到顶部
导入证书
文章出处:极安全 www.jisec.com
如果你是找一个知名的ssl证书颁发机构如VeriSign、Wosign、StartSSL签发的证书,浏览器已经内置并信任了这些根证书,如果你是自建C或获得二级CA授权,都需要将CA证书添加到浏览器,这样在访问站点时才不会显示不安全连接。各个浏览的添加方法不在本文探讨范围内。
2. 部分页面ssl
一个站点并不是所有信息都是非常机密的,如网上商城,一般的商品浏览可以不通过https,而用户登录以及支付的时候就强制经过https传输,这样用户访问速度和安全性都得到兼顾。
但是请注意不要理解错了,是对页面加密而不能针对某个请求加密,一个页面或地址栏的URL一般会发起许多请求的,包括css/png/js等静态文件和动态的java或php请求,所以要加密的内容包含页面内的其它资源文件,否则就会出现http与https内容混合的问题。在http页面混有 https内容时,页面排版不会发生乱排现象;在https页面中包含以http方式引入的图片、js等资源时,浏览器为了安全起见会阻止加载。
下面是只对example.com/account/login登录页面进行加密的例子
root /apps/www;
index index.html index.htm;
server {
listen 80;
server_name example.com;
location ^~ /account/login {
rewrite ^ https://$server_name:443$request_uri? permanent;
}
location / {
proxy_pass http://localhost:8080;
### Set headers ####
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
}
}
server {
listen 443 ssl;
server_name example.com;
ssl on;
ssl_certificate ../SSL/ittest.pem;
ssl_certificate_key ../SSL/ittest.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location ^~ /account/login {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
### Most PHP, Python, Rails, Java App can use this header -> https ###
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
rewrite ^ http://$server_name$request_uri? permanent;
}
}
WordPress https设置
开启登录和后台的强制 SSL
虽然有了整站的重定向,但我们不妨还是将 WordPress 本身自带的功能打开,以期更完善的兼容体验——毕竟是301重定向。
还是找到你网站根目录里边,这次要修改的文件是 config.php,直接在这个文件的末尾另起一行,追加两行代码:
1
2
3
|
/* 强制后台和登录使用 SSL */
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);
|
四、站内链接支持
最主要的可能就是图片的问题了,你在上传到空间的附件都被 WordPress 标记为了绝对链接,而且全都妥妥的写入了“http://”。一般来讲,是需要用数据库替换的,不过这种方法有点小危险,我这里给你推荐另外一个不错的选择:使用代码让 WordPress 在加载附件之前将链接替换就好了!——毕竟,只是协议的问题,跟路径没有半毛钱的关系~
文章出处:极安全 www.jisec.com
(我希望你使用了 WordPress 的子主题功能……)
找到当前主题下的 function.php 文件,编辑之,在里边代码的末尾追加如下代码:
1
2
3
4
5
6
7
8
|
/* 替换图片链接为 https */
function my_content_manipulator($content){
if( is_ssl() ){
$content = str_replace('http://www.logcg.com/wp-content/uploads', 'https://www.logcg.com/wp-content/uploads', $content);
}
return $content;
}
add_filter('the_content', 'my_content_manipulator');
|
另外,除了这个大头意外,你还需要关心站内的各种内链:
- 修改“菜单”当中的所有“自定义链接”为相对路径;
- 修改“设置”→“常规”里的“站点地址”和“WordPress 地址”为 HTTPS;
- 修改其他自己手贱写入的绝对链接地址……
五、关心一下插件
现在,还剩下最后一个问题:插件的兼容性!
是的没错!并不是所有的插件都会兼容 SSL!(尤其是国内的插件)
对了!关于 CNZZ 这个统计的话你只需要改动一下统计代码就可以,将 HTTP 修改为 HTTPS 即可。不过国内比较常用的 JiaThis 社会化分享插件就无力了,只能割爱停删。
另外,曾今“我爱水煮鱼”开发的相关文章插件:WordPress Related Post,后来卖给了老外,总是会加载一个站外的链接,如今还因为 Girl Friend Wall 的问题导致这个 js 脚本各种菊花,只好果断停删。
你可以使用任意浏览器,打开你的博客页面之后随便打开一篇文章,选择类似于“检查元素”的操作,查看报错就可以了:要求是没有任何红色的错误,黄色的警告“⚠️”可以忽略。
关于删除的插件那功能怎么办?
当然是找替换插件了,这里针对如上的两个插件,路由推荐两个插件:
- anyShare 它是一个功能简洁十分轻量级的社会化分享插件,按钮比较大(你可以稍后在这片文章末尾看到样式),虽然说它已经10个月没有更新,但我向你保证这玩意儿绝对兼容最新版本的 WordPress 并且功能完美。:)
- Yet Another Related Posts Plugin 这个是另外一个相关文章插件,再也没有烦人的站外链接了,免费版功能足够,而且同样支持RSS,而且现在它的配置界面也不再那么让人望而生畏,对了!虽然它同样被提示不兼容最新版——但我保证,这玩意儿同样功能正常~
最后,你可以到这个页面来参考落格都使用了哪些狂拽炫酷吊的 WordPress 插件,这些插件至少都会兼容 SSL 。
文章出处:极安全 www.jisec.com
如需要替换数据库里面的http
可以用这个sql语句
UPDATE article SET
content = replace(content, '解决', '解放')
WHERE ID>0;
article 表名 contrnt 表字段 WHERE 后面是条件
以上是博主亲自测试了才放出来的 亲测可用