要保证Web浏览器到服务器的安全连接,HTTPS几乎是唯一选择。HTTPS其实就是HTTP over SSL,也就是让HTTP连接建立在SSL安全连接之上。
SSL使用证书来创建安全连接。有两种验证模式:
-
仅客户端验证服务器的证书,客户端自己不提供证书;
-
客户端和服务器都互相验证对方的证书。
显然第二种方式安全性更高,一般用网上银行会这么搞,但是,普通的Web网站只能采用第一种方式。客户端如何验证服务器的证书呢?服务器自己的证书必须经过某“权威”证书的签名,而这个“权威”证书又可能经过更权威的证书签名,这么一级一级追溯上去,最顶层那个最权威的证书就称为根证书。根证书直接内置在浏览器中,这样,浏览器就可以利用自己自带的根证书去验证某个服务器的证书是否有效。下图为chrome的系统根证书:
下面简单介绍如何创建一个自签名的SSL证书。
创建自签名证书需要安装openssl,使用以下步骤:
-
创建Key;
-
创建签名请求;
-
将Key的口令移除;
-
用Key签名证书。
为HTTPS准备的证书需要注意,创建的签名请求的CN必须与域名完全一致,否则无法通过浏览器验证。
以上步骤命令繁琐,所以我做了一个shell脚本:
#!/bin/sh # create self-signed server certificate: read -p "Enter your domain [www.example.com]: " DOMAIN echo "Create server key..." openssl genrsa -des3 -out $DOMAIN.key 1024 echo "Create server certificate signing request..." SUBJECT="/C=US/ST=Mars/L=iTranswarp/O=iTranswarp/OU=iTranswarp/CN=$DOMAIN" openssl req -new -subj $SUBJECT -key $DOMAIN.key -out $DOMAIN.csr echo "Remove password..." mv $DOMAIN.key $DOMAIN.origin.key openssl rsa -in $DOMAIN.origin.key -out $DOMAIN.key echo "Sign SSL certificate..." openssl x509 -req -days 3650 -in $DOMAIN.csr -signkey $DOMAIN.key -out $DOMAIN.crt echo "TODO:" echo "Copy $DOMAIN.crt to /etc/nginx/ssl/$DOMAIN.crt" echo "Copy $DOMAIN.key to /etc/nginx/ssl/$DOMAIN.key" echo "Add configuration in nginx:" echo "server {" echo " ..." echo " listen 443 ssl;" echo " ssl_certificate /etc/nginx/ssl/$DOMAIN.crt;" echo " ssl_certificate_key /etc/nginx/ssl/$DOMAIN.key;" echo "}"
$ ./gencert.sh
Enter your domain [www.example.com]: www.test.com
Create server key...
Generating RSA private key, 1024 bit long modulus
.................++++++
.....++++++
e is 65537 (0x10001)
Enter pass phrase for www.test.com.key:输入口令
Verifying - Enter pass phrase for www.test.com.key:输入口令
Create server certificate signing request...
Enter pass phrase for www.test.com.key:输入口令
Remove password...
Enter pass phrase for www.test.com.origin.key:输入口令
writing RSA key
Sign SSL certificate...
Signature ok
subject=/C=US/ST=Mars/L=iTranswarp/O=iTranswarp/OU=iTranswarp/CN=www.test.com
Getting Private key
TODO:
Copy www.test.com.crt to /etc/nginx/ssl/www.test.com.crt
Copy www.test.com.key to /etc/nginx/ssl/www.test.com.key
Add configuration in nginx:
server {
...
ssl on;
ssl_certificate /etc/nginx/ssl/www.test.com.crt;
ssl_certificate_key /etc/nginx/ssl/www.test.com.key;
}
红色部分是输入,注意4次输入的口令都是一样的。
在当前目录下会创建出4个文件:
- www.test.com.crt:自签名的证书
- www.test.com.csr:证书的请求
- www.test.com.key:不带口令的Key
- www.test.com.origin.key:带口令的Key
Web服务器需要把www.test.com.crt
发给浏览器验证,然后用www.test.com.key
解密浏览器发送的数据,剩下两个文件不需要上传到Web服务器上。
以Nginx为例,需要在server {...}
中配置:
server {
...
ssl on;
ssl_certificate /etc/nginx/ssl/www.test.com.crt;
ssl_certificate_key /etc/nginx/ssl/www.test.com.key;
}
访问:https://www.test.com
标记此证书为受信任的证书。
注:访问https://www.test.com时出现如下页面:
是因为本地电脑开启了vpn,关了vpn后一切正常。