Nginx 配置 HTTP 跳转 HTTPS

本文介绍 Nginx 访问 HTTP 跳转 HTTPS 的 4 种配置方式。

1. rewrite

Nginx rewrite 有四种 flag:

  • break:在一个请求处理过程中将原来的 url 改写之后,再继续进行后面的处理,这个重写之后的请求始终都是在当前这一个 location 中处理
  • last:相当于一个新的 request,需要重新走一遍 server,提供了一个可以转到其他 location 的机会
  • redirect:表示 302 temporarily redirect
  • permanent:表示 301 permanently redirect

要使用 HTTP 跳转 HTTPS,当然是需要 301 跳转,即使用 permanent 这个标签:

rewrite  ^(.*)  https://$server_name$1 permanent;

提醒:以上配置涉及到三个本文并未提及的点:rewrite 用法、全局变量、正则匹配。

2. 301 状态码

Nginx 使用 ruturn ${http_code} 指定对应状态码的处理。这里我们使用 return 301 指定 301 重定向的目标:

return  301  https://$server_name$request_uri;

3. 497 状态码

当 server 只允许 HTTPS 请求时,基于 HTTP 的访问会被 Nginx 返回 497 错误。这时我们使用 error_page 将访问重定向至 HTTPS 上:

error_page  497  https://$server_name$request_uri;

4. meta

还有一种方式是,返回一个写入 meta 标签的 html 页面,让浏览器跳转。和上面三种方式不同,此方案不在 Nginx 上进行跳转,节约服务器资源,而缺点是不能写入 $request_uri 变量,只能跳转到固定地址。

server {
    ...

    index  meta.html;
    error_page 404 meta.html;
}

在要返回的 meta.html 中写入:

<html>
  <meta http-equiv="refresh" content="0; url=${你要跳转的目标地址}">
</html>

本站就使用这个方案,所以我是这样写的:

<html>
  <meta http-equiv="refresh" content="0; url=https://sometimesnaive.org/">
</html>

nginx配置正向代理支持HTTPS

未分类

nginx当正向代理的时候,通过代理访问https的网站会失败,而失败的原因是客户端同nginx代理服务器之间建立连接失败,并非nginx不能将https的请求转发出去。因此要解决的问题就是客户端如何同nginx代理服务器之间建立起连接。有了这个思路之后,就可以很简单的解决问题。我们可以配置两个SERVER节点,一个处理HTTP转发,另一个处理HTTPS转发,而客户端都通过HTTP来访问代理,通过访问代理不同的端口,来区分HTTP和HTTPS请求。

#HTTP
server{
resolver 8.8.8.8;
access_log /data/logs/nginx/access_proxy.log main;
listen 80;
location / {
root html;
index index.html index.htm;
proxy_pass $scheme://$host$request_uri;
proxy_set_header HOST $http_host;
proxy_buffers 256 4k;
proxy_max_temp_file_size 0k;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_next_upstream error timeout invalid_header http_502;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#HTTPS
server{
resolver 8.8.8.8;
access_log /data/logs/nginx/access_proxy.log main;
listen 443;
location / {
root html;
index index.html index.htm;
proxy_pass https://$host$request_uri;
proxy_buffers 256 4k;
proxy_max_temp_file_size 0k;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_next_upstream error timeout invalid_header http_502;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

如果访问HTTP网站,可以直接这样的方式: curl –proxy proxy_server:80 http://www.taobao.com/
如果访问HTTPS网站,例如https://www.alipay.com,那么可以使用nginx的HTTPS转发的server:
curl –proxy proxy_server:443 http://www.alipay.com

2013年12月9日补记:

之前nginx配置透明代理的时候,没有特别针对端口的配置,如果之前的url是http://www.test.com:8080/这样的地址过来,通过nginx转发之后实际到了http://www.test.com:80/上面,为了修复这个问题,增加如下配置:

proxy_pass http://$host:$cookie_passport$request_uri;

其中$cookie_是获取请求中cookie的信息,这个passport的cookie值是原URL中端口号。由此可以看出,如果要通过该NGINX转发,需要首先设置一个cookie,这个cookie名为passport,cookie的值为原url中的端口号。

如果使用CURL命令请求链接,可以这样子:

curl -b passport=80 --proxy proxy_server:80 http://www.taobao.com/

其中-b参数是为了添加cookie

Let’s Encrypt配置免费SSL证书建立HTTPS(Ubuntu+Apache)

前言

这段时间在开发微信小程序,需要一个后台服务器,KP小站刚好能够派上用上。不过,微信规定必须使用HTTPS链接,于是按照DigitalOcean的官方教程,利用Let’s Encrypt配置免费SSL简书。过程还是很简单的,虽然遇到了一个小问题,不过Google后也顺利解决了,这里简单分享下心得。

一. 什么是HTTPS?

  1. HTTP表示超文本传输协议(HyperText Transfer Protocol),用来传输客户端(浏览器)和WEB服务器之间的内容。当你访问kplayer.me时,服务器就把html,css,js以及图像等文件通过该协议传输到你的浏览器,你的浏览器解析后就展现主页的内容。

  2. 但是HTTP协议有个问题就是它是明文的,这样就存在安全隐患,如传输内容会被偷窥和窃取;另外在HTTP中通信双方的身份没有进行验证,可能会出现伪装身份的情况,由于任何人都能对服务器发起请求,也使服务器易受DOS攻击;最后客户端无法确定接受报文的完整性,因为中途可能被篡改。

  3. 那么HTTPS呢?它表示HTTP over SSL,其中的S表示SSL:Secure Socket Layer,中文叫“安全套接层”。SSL利用数据加密技术,防止数据在网络传输过程中不会被截取及窃听。它最早为网景公司Netscape所研发,在IETF(国际互联网工程任务组)进行标准化后改名为 TLS(Transport Layer Security),中文叫做“传输层安全协议”,现在我们常能看到二者的合称SSL/TLS。

  4. HTTPS的具体原理是什么?

理解原理之前需要简单介绍几个相关的概念。

4.1 对称密钥和非对称密钥

对称密钥就是客户端和服务器都拥有一把相同的钥匙,用来对报文加解密。打个比方,我有个机密文件想要传给你,但又怕中间被人窃取了,所以我用WinRAR进行口令加密压缩,然后传输给你,你收到文件时输入口令解压即可,这就是对称密钥/口令。但是我怎么安全的告诉你口令是什么呢?至少第一次肯定需要传输口令,这似乎又回到了安全传输的困境,如果这个口令不能安全的传递给你,在过程中被窃取了,那么这种加密方式又有什么意义?

非对称密钥就是加解密使用不同的密钥。那怎么用呢?首先我作为服务器在本地生成一对密钥,一个是公有密钥,一个是私有密钥。我把公有密钥告诉你,你用来进行对文件加密传输,我收到文件后用我的私有密钥进行解密,获得最终文件。相比对称密钥,不必担心密钥的安全传输问题,因为即使公钥被截获,也无法被解密。

4.2 数字摘要与数字签名

有了非对称密钥,有助于客户端和服务端之间的数据不被偷窥和窃取。但是这似乎并不能防止传输的数据被篡改(对于客户端来说),另外如何保证数据是真实服务器发送的而不是被调包过的呢?于是,数字摘要和数字签名技术就被引入了。a) 服务器采用Hash函数对报文生成“摘要”;b) 服务器再用私钥对这个摘要进行加密,作为“数字签名”连同报文发给客户端;c) 客户端收到后,提取数字签名用服务器的公钥进行解密,如果能得到摘要,那说明是真实服务器发送的;d) 客户端再对接收的报文采用与服务器相同的Hash函数处理得到本地摘要,如果与刚刚解密出来的摘要完全一致,那说明报文没有被篡改过。

未分类

4.3 数字证书

有了数字签名,似乎安全性已经得到了保证。真的是这样么?任何存在不可信任风险的地方都有可能被利用。在数字签名中,客户端收到报文后需要用服务器的公钥进行解密,那么如果有不法者偷偷替换了服务器公钥为自己的公钥呢?那么该不法者就可以用自己的私钥生成数字签名发送报文给客户端。因此最大的问题就在于:对于客户端来说,如何确保它所得到的公钥一定是从目标服务器那里发布的,而且没有被篡改过呢?这时候就需要一个权威的第三方机构来统一对外发放公钥,就是所谓的证书权威机构(Certificate Authority, CA),由服务器管理者向CA申请,认证后CA会给服务器管理者颁发“数字证书”(含主机机构名称、公钥等文件),于是服务器在之后发送报文给客户端时只需要加上数字证书即可,客户用CA的公钥验证后就可确认来源的可靠性。

4.4 HTTPS

了解了以上的内容,现在我们来了解下HTTPS的流程:

未分类

a. 客户端使用HTTPS的URL链接向服务器发起请求,如https://kplayer.me;

b. WEB服务器收到请求后将网站的证书信息(含公钥等)发送给客户端;

c. 客户端根据“证书管理器”判断证书是否被冒用,或者公钥是否有效,有问题则发出警告;

d. 如果证书和公钥有效,则客户端首先生成一个随机(对称)数串,并生成客户端版的共享密钥;

e. 客户端再用公钥对数串进行对称密钥加密,之后发送给服务器;

f. 服务器收到这个加密后的随机数串,只需要用私有密钥就能解密出该随机数串;

g. 服务器以随机数串生成服务器端的共享密钥;

h. 至此,客户端和服务端拥有相同共享密钥,则可以利用共享密钥进行安全通信。

从以上流程可以看出HTTPS采用HTTP+SSL的方式使得网站的访问更加安全,但它也使得通信信息量增加,速率降低,消耗更多的服务器资源,而且向认证机构购买证书也是一笔开销,因此在HTTP和HTTPS的选择上要视网站的功能和需求而定。

二、Let’s Encrypt是什么?

SSL证书按大类一般可分为DV SSL、OV SSL、EV SSL证书,也叫做域名型、企业型、增强型证书。

域名型SSL证书(DV SSL):信任等级普通,只需验证网站的真实性便可颁发证书保护网站;

企业型SSL证书(OV SSL):信任等级强,须要验证企业的身份,审核严格,安全性更高;

增强型SSL证书(EV SSL):信任等级最高,一般用于银行证券等金融机构,审核严格,安全性最高,同时可以激活绿色网址栏。

对于个人博客和站点,申请个免费的DV型SSL证书最划算。Let’s Encrypt 是一个免费、开放,自动化的证书颁发机构,由 ISRG(Internet Security Research Group)运作。

https://letsencrypt.org/

ISRG 是一个关注网络安全的公益组织,其赞助商从非商业组织到财富100强公司都有,包括 Mozilla、Akamai、Cisco、Facebook,密歇根大学等等。ISRG 以消除资金,技术领域的障碍,全面推进加密连接成为互联网标配为自己的使命。

三、如何使用Let’s Encrypt配置SSL证书?

官方教程在此:

https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-16-04

1. 安装Let’s Encrypt客户端

a) 新增软件包目录:

sudo add-apt-repository ppa:certbot/certbot

并按回车ENTER确认

b) 更新新增的目录信息

sudo apt-get update

c) 安装官方客户端Cerbot

sudo apt-get install python-certbot-apache

2. 配置SSL证书

sudo certbot –apache -d kplayer.me

根据提示输入对应指令即可,过程中会要求提供Email用于丢失密钥恢复和相关通知,也会让你选择同时启用http和https访问,或者强制所有请求重定向到https。

另外,如果想要证书对对多个域名或子域名有效,可以增加参数,如下(建议第一个是主域名):

sudo certbot –apache -d kplayer.me -d http://www.kplayer.me

如果有多个域名的话,可以多次调用cerbot命令。

安装完成后,可以在浏览器输入以下地址,确认是否成功:

https://www.ssllabs.com/ssltest/analyze.html?d=kplayer.me&latest

成功的话,就可以使用https://kplayer.me来访问小站啦。

不过KP君在执行时收到如下报错信息:

Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.

一阵Google后,原来由于安全问题,Let’s Encrypt已经停止提供Certbot的Apache和Nginx插件所用的机制,计划在接下来的日子里发布一个新版本的Certbot,如果急需要用的话,可以采用临时的方法:

sudo certbot –authenticator standalone –installer apache -d kplayer.me –pre-hook "systemctl stop apache2" –post-hook "systemctl start apache2"

详情参见:https://github.com/certbot/certbot/issues/5405

3. 验证Certbot自动更新

Let’s Encryp只提供加密90天的证书。然而,我们安装的certbot软件包通过一个systemd定时器每天运行两次certbot进行更新。在非systemd发行版中,此功能由位于/etc/cron.d中的cron脚本提供。 该任务每天运行两次,并将在续期30天内更新。

可以通过如下命令验证:

sudo certbot renew –dry-run

如果没有报错,那就大功告成。如有必要,Certbot将更新证书并重新加载Apache。如果自动更新失败,Let’s Encrypt将向我们提供的电子邮件发送一封邮件,并在证书即将到期时发出警告。

后记

配置完HTTPS,兴奋地在微信小程序后台提交网址,结果提示需要域名备案。在我纠结了一天后,决心乖乖接受监督,可惜在备案的过程中告诉我.me域名暂时无法备案,欲哭无泪,那我就好好的用来写我的博客吧。

注:以上文字和图片部分整理自网络。

Apache配置http跳转https教程

用我的步骤前,请一定要保证自己的网站能够用https正常打开;方法也是非常的简单,具体步骤如下:

一、登陆服务器

不管你的服务器是linux还是windos,原理都是一样的,我拿windos服务器来举例吧!
登陆windos服器方法很简单,需要“远程桌面连接”。
我们直接点击左下角“开始” =》 “运行”,(或使用“WIN+R”快捷键),再输入”mstsc”即可打开远程桌面连接,输入你的IP+用户名+密码即可远程连接成功;

二、打开url重定向伪静态规则支持

1、打开Apache/conf/httpd.conf;

2、找到 #LoadModule rewrite_module modules/mod_rewrite.so;

3、去掉前面的#号;#LoadModule rewrite_module modules/mod_rewrite.so

未分类

三、修改网站目录的段:Directory

1、打开Apache/conf/httpd.conf;

2、找到你网站目录的段,例如我的是:“C:phpStudyPHPTutorialWWW”

3、修改其中的 AllowOverride None 为 AllowOverride All;

未分类

四、保存并重启apache服务

五、设置重定向伪静态规则

1、在你网站目录下放一个.htaccess文件。注意:windows环境下,不能把文件直接改名为.htaccess,会提示你必须输入文件名。所以我们先新建一个“新建文本文档.txt”文档,再用记事本打开,选择另存为,保存类型选择“所有文件(.)”,文件名输入“.htaccess”,保存。这样便生成了一个.htaccess文件。

2、打开并编辑.htaccess文件,写入如下规则:

RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} !^/tz.php
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R]

解释:

%{SERVER_PORT} —— 访问端口
%{REQUEST_URI} —— 比如如果url是 https://www.fujieace.com/tz.php,则是指 /tz.php
%{SERVER_NAME} —— 比如如果url是 https://www.fujieace.com/tz.php,则是指 www.fujieace.com

以上规则的意思是:

如果访问的url的端口不是443,且访问页面不是tz.php,则应用RewriteRule这条规则。
这样便实现了:访问了 https://www.fujieace.com/index.php 或者 https://www.fujieace.com/admin/index.php 等页面的时候会自动跳转到 https://www.fujieace.com/index.php 或者 https://www.fujieace.com/admin/index.php,
但是访问 https://www.fujieace.com/tz.php 的时候就不会做任何跳转,也就是说 https://www.fujieace.com/tz.php 和 https://www.fujieace.com/tz.php 两个地址都可以访问。

apache https配置

1、修改httpd.conf,将以下注释项放开

#LoadModule ssl_module modules/mod_ssl.so
#LoadModule socache_shmcb_module 
#modules/mod_socache_shmcb.so
#Include conf/extra/httpd-mpm.conf
#Include conf/extra/httpd-ssl.conf

2、修改httpd-ssl.conf,配置以下配置项

SSLCertificateKeyFile “”    //服务器私钥位置
SSLCertificateFile “”   //服务器证书位置
SSLCACertificatePath “”  //CA根证书位置

3、放开将注释项

#SSLVerifyClient require
#SSLVerifyDepth  10
修改SSLVerifyDepth 为1

4、执行httpd.exe

-t检查语法配置是否有误,一般都是文件路径的问题。
重新配置vhost,端口改443,重启apache,验证是否生效。

使用nginx或tomcat搭建https环境

前言

最近在做一个服务端和手机端相结合的项目,已接近尾声。

手机最初安装app是通过扫描二维码来下载安装的,这个方式在当下也较为流行。用此方法Android自然是没有问题,但是ios实现起来就没这么简单了。

因为是企业app使用的是企业证书不上appstore,所以只能使用safari来安装,步骤大致如下:

  • 安装证书,这里的证书必须安装,否则在连接下面的xxx.plist文件地址时会提示连不上服务器。

  • 访问xxx.plist文件,一般就是用户看到的安装按钮,地址就像这样:itms-services://?action=download-manifest&url=https://xxx.xxx/download/xxx.plist

  • 具体的安装操作是由xxx.plist文件中描述指定的,当然这步用户不会感觉到。xxx.plist文件ios开发人员会提供这里就不多说了。

我们要做的就是解决前面两步,本来是相当简单的事,但是苹果在ios7之后要求xxx.plist文件的地址必须是https的,这个就是麻烦的所在,因为我们原来没有https环境。

本来想着网上找个开放的https环境,把xxx.plist文件往上一放就解决了事,比如git.oschina.net实测就可以支持,但是领导要求这玩意不能放在别人那里,好吧,只能自己搭建一个了。

首先看了红薯的这篇: http://www.oschina.net/question/12_23148?fromerr=SUotMsG2

看来也挺简单的,按照说明搭建成功,浏览器也访问正常,可ios就是用不了。

后来折腾过才知道原来ios要求安装的证书是ssl的证书,并非ios开发者的证书,可上面的教程中并没有提供给ios安装的证书文件啊,看样子没这么简单搞定了,还是老老实实一步步来吧。

使用openssl生成证书

mac已经自带了openssl可以直接使用,如果没有请自行安装。

创建根证书

1、创建根证书私钥文件

openssl genrsa -out dexcoder.key 2048

2、创建根证书dexcoder.cer,机构名称为Dexcoder CA

openssl req -new -x509 -key dexcoder.key -out dexcoder.cer -days 3650 -subj /CN="Dexcoder CA"

创建自签名的ssl证书

1、创建一个私钥server.key

openssl genrsa -out server.key 2048

2、创建CSR,我这里是本地所以是:localhost,也可以改成IP,输出文件为server.csr

openssl req -new -out server.csr -key server.key -subj /CN=localhost

3、用CSR创建SSL证书,有效期为10年,输出文件为server.cer,序号文件为server.serial(撤销证书时使用)

openssl x509 -req -in server.csr -out server.cer -CAkey dexcoder.key  -CA dexcoder.cer -days 3650 -CAcreateserial -CAserial server.serial

配置nginx

到上面为止,证书就已经生成完成了,如果使用nginx,只需要进行如下配置:

server {
    listen       8443 ssl;
    server_name  localhost;
    ssl_certificate      /Users/liyd/testssl/server.cer;
    ssl_certificate_key  /Users/liyd/testssl/server.key;
}

重启nginx后就可以使用地址:https://localhost:8443 来访问了。

因为是自签名证书而非第三方认证机构签发,所以浏览器会出现以下提示:

未分类

但这并不影响我们ios应用的下载,就不管它了。

配置tomcat

上面nginx的配置已经完成了,但因为线上已经有一台tomcat,所以想着能不能并到一起,方便也节省资源。

tomcat要使用上面的证书,还需要做一下加工,因为tomcat使用的一般只有一个.keystore文件。

1、将.key 和.cer 文件导出为.p12 证书,需要输入证书密码。这里密码设为123456。输出文件名为server.p12。

selflydeMacBook-Pro:testssl liyd$ openssl pkcs12 -export -in server.cer -inkey server.key -out server.p12 -name "server"
Enter Export Password:
Verifying - Enter Export Password:
selflydeMacBook-Pro:testssl liyd$

2、用keytool将.p12文件导入到.keystore中,这里srcstorepass后面的123456为server.p12的密码,deststorepass后的12356为.keystore的密码。

selflydeMacBook-Pro:testssl liyd$ keytool -importkeystore -v -srckeystore server.p12 -srcstoretype pkcs12 -srcstorepass 123456 -destkeystore server.keystore -deststoretype jks -deststorepass 123456
已成功导入别名 server 的条目。
已完成导入命令: 1 个条目成功导入, 0 个条目失败或取消
[正在存储server.keystore]
selflydeMacBook-Pro:testssl liyd$

3、使用ssl证书

打开Tomcat安装目录,修改conf目录下的server.xml,增加下面内容,原来注释部分应该有类似标签内容,可以参考:

<Connector SSLEnabled="true" protocol="org.apache.coyote.http11.Http11Protocol"  
            scheme="https" secure="true" sslProtocol="TLS"
            keystoreFile="/Users/liyd/testssl/server.keystore" keystorePass="123456"
            maxThreads="150" port="8443" clientAuth="false" 
            />

这里设置了端口为8443,启动tomcat,打开浏览器访问:https://localhost:8443/ 成功打开tomcat主页,说明服务已经可用。

ios安装证书

上面做了这么多,现在才是我们的最终目的,将dexcoder.cer放到部署的tomcat中,供ios访问下载,例如:

https://localhost:8443/app/dexcoder.cer

这个证书下载不一定要是https的,在安装好证书之后,再访问plist文件安装:

itms-services://?action=download-manifest&url=https://xxx.xxx/download/xxx.plist

这里的xxx.plist文件地址才必须是https。

结束语

到这里我们要的功能就都已经搞定了。不足之处是证书是自签名的,浏览器在访问时会出现安全警告。

如果想要去掉这个警告,可以申请第三方CA机构的证书,这个可以自己网上找找。

以下是摘自网上的一段关于CA机构及证书的说明:

要获取受浏览器信任的证书,则需要到证书提供商处申请。证书授证中心,又叫做CA机构,为每个使用公开密钥的用户发放一个数字证书。浏览器在默认情况下内置了一些CA机构的证书,使得这些机构颁发的证书受到信任。VeriSign即是一个著名的国外CA机构,工行、建行、招行、支付宝、财付通等网站均使用VeriSign的证书,而网易邮箱等非金融网站采用的是中国互联网信息中心CNNIC颁发的SSL证书。一般来说,一个证书的价格不菲,以VeriSign的证书为例,价格在每年8000元人民币左右。

据说也有免费的证书可以申请。和VeriSign一样,StartSSL也是一家CA机构,它的根证书很久之前就被一些具有开源背景的浏览器支持(Firefox浏览器、谷歌Chrome浏览器、苹果Safari浏览器等)。后来StartSSL竟然搞定了微软:在升级补丁中,微软更新了通过Windows根证书认证(Windows Root Certificate Program)的厂商清单,并首次将StartCom公司列入了该认证清单。现在,在Windows 7或安装了升级补丁的Windows Vista或Windows XP操作系统中,系统会完全信任由StartCom这类免费数字认证机构认证的数字证书,从而使StartSSL也得到了IE浏览器的支持。

https双向验证-nginx实例

简介

一般的web服务器都是https单向认证,双向认证大部分用于企业对接,信任对方身份。比如该网站的接口不是所有人都可以访问,只允许一个或者部分持有证书的人访问。就需要双向认证

环境准备

ubuntu 16.4
nginx或者OpenResty, 本文用的OpenResty 版本为:openresty-1.11.2.1

创建目录

  1. 修改/etc/ssl/openssl.cnf配置文件(如果不知道openssl配置文件可以查找一下,后者使用locate openssl.cnf命令)
  2. 找到[CA_default]标签
  3. 修改dir对应的工作目录,我的目录为 /home/用户名/ca
  4. cd 到工作目录

生成CA证书

openssl genrsa -aes256 -out private/ca.pem 1024
openssl rsa -in private/ca.pem -out private/ca.key
openssl req -new -key private/ca.pem -out private/ca.csr
openssl x509 -req -days 365 -sha1 -signkey private/ca.pem -in private/ca.csr -out certs/ca.cer

生成服务端证书

用根证书签发server端证书

openssl genrsa -aes256 -out private/server.pem 1024
openssl rsa -in private/server.pem -out private/server.key
openssl req -new -key private/server.pem -out private/server.csr
openssl x509 -req -days 365 -sha1 -CA certs/ca.cer -CAkey private/ca.pem -CAserial ca.srl -in private/server.csr -out certs/server.cer

生成客户端证书

openssl genrsa -aes256 -out private/client.pem 1024
openssl rsa -in private/client.pem -out private/client.key
openssl req -new -key private/client.pem -out private/client.csr
openssl x509 -req -days 365 -sha1 -CA certs/ca.cer -CAkey private/ca.pem -CAserial ca.srl -in private/client.csr -out certs/client.cer

导出证书

openssl pkcs12 -export -clcerts -inkey private/client.pem -in certs/client.cer -out certs/client.p12
openssl pkcs12 -export -clcerts -inkey private/server.pem -in certs/server.cer -out certs/server.p12

安装证书

  1. 安装CA证书,在谷歌浏览器中点击设置->高级选项->证书管理->授权中心,点击导入,然后选择生成的ca.cer证书文件。
  2. 安装客户端证书,在谷歌浏览器中点击设置->高级选项->证书管理->您的证书 点击导入,选择生成的client.p12证书文件

未分类

未分类

需要注意的地方

在生成客户端证书的时候在填写CN的时候不要和生成CA证书和服务端证书一样。测试好多次如果subj和CA,server一样的话浏览器一直是400错误。

配置nginx启动

server {
        listen       443 ssl;
        server_name  www.soaer.com;
        ssl on;
        ssl_certificate      /home/sunny/ca/certs/server.cer;
        ssl_certificate_key  /home/sunny/ca/private/server.key;
        ssl_client_certificate /home/sunny/ca/certs/ca.cer;
        ssl_verify_client on;
        ssl_prefer_server_ciphers on;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        location / {
            root   html;
            index  index.html index.htm;
        }
}

测试

浏览器中输入https://www.soaer.com, 如图所示,需要你选择发送给服务端的证书,此时选择client.p12证书文件

未分类

结果(成功)

未分类

Nginx支持HTTPS并且支持反爬虫

自己写了若干爬虫, 但是自己的网站也有人爬, 呵呵, 这里介绍一种Nginx反爬.我在阿里云只开放80端口, 所有一般端口都通过Nginx进行反向代理. 通过Nginx, 我们还可以拦截大部分爬虫.

然后我们再给自己的网站加上HTTPS支持.

Nginx安装

我的系统如下:

jinhan@jinhan-chen-110:~/book/Obiwan/bin$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:    16.04
Codename:   xenial

安装(如果有apache服务器, 建议卸载了, 或者改Nginx的默认端口):

sudo apt-get install nginx

此时已经开启了80端口, 并且配置处在etc/nginx

lsof -i:80

cd /etc/nginx

Nginx服务一般配置

将配置放于conf.d/*

PHP配置(可忽视)

server{
    listen 80;
    server_name php.lenggirl.com;
    charset utf-8;
    access_log /data/logs/nginx/www.lenggirl.com.log;
    #error_log /data/logs/nginx/www.lenggirl.com.err;

    location / {
            root   /data/www/php/blog;
        index index.html index.php;
        #访问路径的文件不存在则重写URL转交给ThinkPHP处理
        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /index.php/$1  last;
            break;
        }
    }

    ## Images and static content is treated different
    location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {

        access_log        off;
        expires           30d;
        root /data/www/php/blog;
     }

    location ~.php/?.*$ {
    root        /data/www/php/blog;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        #加载Nginx默认"服务器环境变量"配置
        include        fastcgi.conf;

        #设置PATH_INFO并改写SCRIPT_FILENAME,SCRIPT_NAME服务器环境变量
        set $fastcgi_script_name2 $fastcgi_script_name;
        if ($fastcgi_script_name ~ "^(.+.php)(/.+)$") {
            set $fastcgi_script_name2 $1;
            set $path_info $2;
        }
        fastcgi_param   PATH_INFO $path_info;
        fastcgi_param   SCRIPT_FILENAME   $document_root$fastcgi_script_name2;
        fastcgi_param   SCRIPT_NAME   $fastcgi_script_name2;        
    }
}

Go配置

通过server_name, 用域名访问, 全部会到80端口, 根据域名会转发到8080

域名请A记录到该机器IP地址.

vim /etc/nginx/conf.d/www.lenggirl.com.conf

server{
    listen 80;
    # 本地测试时可以将域名改为: 127.0.0.1
    server_name www.lenggirl.com;
    charset utf-8;
    access_log /root/logs/nginx/www.lenggirl.com.log;
    #error_log /data/logs/nginx/www.lenggirl.com.err;
    location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://localhost:8080;

    # 这个就是反爬虫文件了
    include /etc/nginx/anti_spider.conf;
    }   
}

日志文件要先建立:

sudo mkdir -p /root/logs/nginx

查看配置是否无误, 并重启:

sudo nginx -t
sudo service nginx restart
sudo nginx -s reload

访问127.0.0.1会发现502错误, 因为8080端口我们没开! 此时访问localhost会发现, 这时Nginx欢迎页面出来了, 这是默认80端口页面!

反爬虫配置

增加反爬虫配额文件:

sudo vim /etc/nginx/anti_spider.conf

#禁止Scrapy等工具的抓取  
if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {  
     return 403;  
}  

#禁止指定UA及UA为空的访问  
if ($http_user_agent ~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|Java|Feedly|Apache-HttpAsyncClient|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|BOT/0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) {  
     return 403;               
}  

#禁止非GET|HEAD|POST方式的抓取  
if ($request_method !~ ^(GET|HEAD|POST)$) {  
    return 403;  
}  

#屏蔽单个IP的命令是
#deny 123.45.6.7
#封整个段即从123.0.0.1到123.255.255.254的命令
#deny 123.0.0.0/8
#封IP段即从123.45.0.1到123.45.255.254的命令
#deny 124.45.0.0/16
#封IP段即从123.45.6.1到123.45.6.254的命令是
#deny 123.45.6.0/24

# 以下IP皆为流氓
deny 58.95.66.0/24;

在网站配置server段中都插入include /etc/nginx/anti_spider.conf, 见上文. 你可以在默认的80端口配置上加上此句:sudo vim sites-available/default

重启:

sudo nginx -s reload

爬虫UA常见:

FeedDemon             内容采集  
BOT/0.1 (BOT for JCE) sql注入  
CrawlDaddy            sql注入  
Java                  内容采集  
Jullo                 内容采集  
Feedly                内容采集  
UniversalFeedParser   内容采集  
ApacheBench           cc攻击器  
Swiftbot              无用爬虫  
YandexBot             无用爬虫  
AhrefsBot             无用爬虫  
YisouSpider           无用爬虫(已被UC神马搜索收购,此蜘蛛可以放开!)  
jikeSpider            无用爬虫  
MJ12bot               无用爬虫  
ZmEu phpmyadmin       漏洞扫描  
WinHttp               采集cc攻击  
EasouSpider           无用爬虫  
HttpClient            tcp攻击  
Microsoft URL Control 扫描  
YYSpider              无用爬虫  
jaunty                wordpress爆破扫描器  
oBot                  无用爬虫  
Python-urllib         内容采集  
Indy Library          扫描  
FlightDeckReports Bot 无用爬虫  
Linguee Bot           无用爬虫  

使用curl -A 模拟抓取即可,比如:

# -A表示User-Agent
# -X表示方法: POST/GET
# -I表示只显示响应头部
curl -X GET -I -A 'YYSpider' localhost

HTTP/1.1 403 Forbidden
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 08 Dec 2017 10:07:15 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive

模拟UA为空的抓取:

curl -I -A ' ' localhost

模拟百度蜘蛛的抓取:

curl -I -A 'Baiduspider' localhost

支持https

见: https://certbot.eff.org/#ubuntuxenial-other

首先执行:

apt-get update
apt-get install software-properties-common
add-apt-repository ppa:certbot/certbot
apt-get update
apt-get install python-certbot-nginx 

然后执行这个按说明操作:

certbot --authenticator standalone --installer nginx --pre-hook "nginx -s stop" --post-hook "nginx"

之前/etc/nginx/conf.d/www.lenggirl.com.conf文件变更如下:

server{
        listen 80;
        # 本地测试时可以将域名改为: 127.0.0.1
        server_name www.lenggirl.com;
        charset utf-8;
        access_log /root/logs/nginx/www.lenggirl.com.log;
        #error_log /data/logs/nginx/www.lenggirl.com.err;
        location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://localhost:4000;

        # 这个就是反爬虫文件了
        # include /etc/nginx/anti_spider.conf;
        #
}

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/www.lenggirl.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.lenggirl.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    } # managed by Certbot

}

NGINX服务器网站升级HTTPS

要让网站升级成HTTPS,首先要申请或者购买ssl证书.

证书的获得

证书可以自己在服务器生成,但是这种证书的兼容性以及安全性都会存在比较大的问题.我们可以从专门的证书机构获取比较好的证书,比如可以通过阿里云去申请证书,但是这种证书有要求限制,只能免费使用一年.

NGINX配置

server {
        listen 443;
        server_name www.vstary.com
        ssl on;
        root html;
        index index.html index.htm;
        ssl_certificate   /home/test/cert/test.pem;
        ssl_certificate_key  /home/test/cert/test.key;
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        location / {
                root html;
                index index.html index.htm;
        }
}

重启服务器.

测试下你的域名,https://www.vstary.com,是否可以访问.

在证书正确的情况下,如果无法访问,可以查看下防火墙是否开放了端口,ssl貌似只能监听443接口.

修改允许端口参考: https://www.vstary.com/article/198

强制HTTP的也走HTTPS

修改服务器配置:

server {
        listen  80;
        server_name  www.vstary.com;
        rewrite ^(.*)$  https://$host$1 permanent;
}

同时允许HTTP跟HTTPS协议访问

    server {
            listen 80
            listen 443 ssl;
            server_name www.vstary.com
            ssl on;
            root html;
            index index.html index.htm;
            ssl_certificate   /home/test/cert/test.pem;
            ssl_certificate_key  /home/test/cert/test.key;
            ssl_session_timeout 5m;
            ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            ssl_prefer_server_ciphers on;
            location / {
                    root html;
                    index index.html index.htm;
            }
    }

WordPress全站添加SSL免费证书开启HTTPS

大家好,最近把achair教程网全站添加了SSL,网址从http://www.xiaored.net,变成了https://www.xiaored.net 前缀变成了https,并且在谷歌浏览器地址栏前面变成了绿色的“安全”,如图:

未分类

简单的说https是安全的http,是经过加密的,百度,淘宝,京东,苹果这些网站都是https的,特别是在线购物的网站建议使用https。下面说说为什么要安装https?

1. 百度搜索排名:
从相关性的角度,百度搜索引擎认为权值相同的站点,采用https协议的页面更加安全,排名上会优先对待。

2. 谷歌浏览器:
从2017年1月份起,Chrome浏览器将会把采用HTTP协议的网站标记为“不安全”网站。

3. 谷歌搜索排名:
谷歌早已宣布采用HTTPS加密协议的网站将会在搜索结果中优先显示。

4. 等等

下面分享下我的网站是如何操作的,先说下我的网站配置以及使用到的工具:

  1. 阿里云ECS的服务器,Nginx

  2. 七牛云的SSL和CDN

  3. WordPress网站,BeTheme主题,Super Cache缓存

  4. DNSPod域名解析,WinSCP服务器管理工具

具体操作经验分享,请到《WordPress公共课》查看:

https://www.xiaored.net/wordpress-commonality/