如今随着网上交易规模不断扩大及API驱动的互联网的出现(如 https://strip.com ),互联网的安全性越来越受到重视。本文简单讲述如何将你的nginx配置成支持https的web server。当然,理论上一个合格的https server需要从CA那里获得正式的SSL certificate,但如何购买SSL certificate不在本文讨论之列。本文仅从技术上讨论如何在你的服务器上使能https。
首先生成本地的RSA key,我们使用1024 bit的密钥。pass phrase一定要输入,并且输入的pass phrase在接下来的步骤中要使用。
sudo mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
$ sudo openssl genrsa -des3 -out myserver.key 1024
[sudo] password for tchen:
Generating RSA private key, 1024 bit long modulus
.....++++++
.++++++
e is 65537 (0x10001)
Enter pass phrase for myserver.key:
Verifying - Enter pass phrase for myserver.key:
`
CSR包含能够鉴别证书申请人的信息。关于CSR及X.509证书的详细说明,请参考:http://en.wikipedia.org/wiki/Certificate_signing_request。
$ sudo openssl req -new -key myserver.key -out myserver.csr
Enter pass phrase for myserver.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg, city) []:BJ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Coderena
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:myserver.com
Email Address []:tchen@myserver.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
首先要把刚才生成的RSA密钥的pass phrase移除:
$ sudo openssl rsa -in myserver.key.org -out myserver.key
Enter pass phrase for myserver.key.org:
writing RSA key
对CSR进行为期一年(365 days)的授权,生成证书:
$ sudo openssl x509 -req -days 365 -in myserver.csr -signkey myserver.key -out myserver.crt
Signature ok
subject=/C=CN/ST=Beijing/L=BJ/O=Coderena/CN=myserver.com/emailAddress=tchen@myserver.com
Getting Private key
在当前目录下,把证书相关文件的权限改为只可自己读,防止他人使用或篡改。
$ sudo chmod 600 *
接下来就是设置网站使用证书。一般我们的app server(如nodejs或gunicorn)都部署在nginx或apache后,所以SSL可以在用户端和web server端使能,这样免去了为每个app server支持SSL的麻烦。这样做在web server和app server之间存在一定的安全风险,但一般而言,web server / app server都在同一个受信任的网络内,所以问题不大。
本文将讨论在nginx下配置SSL。假设在site-available下你有如下virtual host:
server {
listen 80;
server_name myserver.com;
set $current_root "/home/dev/deployment/myserver";
access_log /var/log/nginx/myserver.access.log;
error_log /var/log/nginx/myserver.error.log;
location ~* ^/media/ {
autoindex off;
root $current_root;
expires max;
}
location ~* ^/static/ {
autoindex off;
root $current_root;
expires 30d;
}
location / {
proxy_pass http://localhost:7010;
include /etc/nginx/proxy_params;
}
}
要对其使能https,首先,将所有http请求都跳转到https:
server {
listen 80;
server_name myserver.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
接着配置https:
server {
listen 443;
ssl on;
ssl_certificate /etc/nginx/ssl/myserver.crt;
ssl_certificate_key /etc/nginx/ssl/myserver.key;
server_name myserver.com;
set $current_root "/home/dev/deployment/myserver";
client_max_body_size 32m;
access_log /var/log/nginx/myserver.access.log;
error_log /var/log/nginx/myserver.error.log;
location ~* ^/media/ {
autoindex off;
root $current_root;
expires max;
}
location ~* ^/static/ {
autoindex off;
root $current_root;
expires 30d;
}
location / {
proxy_pass http://localhost:7010;
include /etc/nginx/proxy_ssl_params;
}
}
我们之前使用的proxy params在 proxy_params
文件中:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
对于https,我们需要一个单独的 proxy_ssl_params
文件:
proxy_redirect off;
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_set_header X-Forwarded-Proto https;
两者有一些差别。
至此,整个证书的生成及使用就完成了,重启nginx后打开浏览器就可以尝试。注意由于我们的证书是在本地签名的,不属于一个合法的CA授权的证书,所以浏览器会报警,继续浏览即可。虽然浏览器认为其安全性存在问题,但整个访问过程都是通过SSL进行加密的。
如果要购买被验证的证书,需要花费一大笔美刀(比如Symantac的单服务器任意子域名3年有效的证书要$5095)。这么贵是有原因的:
当然,如果你付不起这么多钱,很想使用https保护你的用户(但根本不需要巨额的保险),可以购买那些二三线的CA的证书。几美金到几十美金一年就可以搞定。这就跟把传家宝藏在瑞士银行的保险柜里和放在本地农商行的保险柜一个道理,一分钱一分货。
送上小宝照片一枚:
如果您对本站的文章感兴趣,欢迎订阅我的微博公共账号:程序人生。每次博文发表时,您都能获得通知。此外,公共账号还会不定期推送一些短文,技术心得,供您参考。