Nginx的全套HTTPS部署

星間飛行 发布于

搞到证书

找Let’s Encrypt去申请个证书,他们官网推荐使用Certbot,用了一下感觉还不错,整体简单易懂全自动很舒服
但后面为了还是用了acme.sh,这个脚本支持更多自定义的项目

使用acme.sh

他们有中文使用说明,普通用的话跟着走就行很简单
在terminal里面先下载
curl https://get.acme.sh | sh
脚本会安装在~/.acme.sh/
网站用的是nginx所以用nginx方式安装,nginx开着也没关系
acme.sh --issue -d mydomain.com --nginx -k ec-384
后接-k表示选择秘钥,可选ec-256 、ec-384、2048、3072、4096、8192
ec表示ECC证书,不写ec代表RSA证书,安全性上ec-256和3072位的RSA差不多

稍微等一下,秘钥会被放到~/.acme.sh/网站名
接下来用把秘钥和CA验证塞到需要的地方,我这里在nginx下新建了一个ssl文件夹
acme.sh --installcert -d example.com --key-file /path/to/keyfile/in/nginx/fullchain.pem --cert-file /path/to/cert/cert.pem --fullchain-file /path/to/fullchain/nginx/fullchain.pem --reloadcmd "service nginx force-reload"
如果nginx报错,试试删掉最后的--reloadcmd然后手动重启nginx
之后每60天会自动更新秘钥,如果需要手动更新(ECC证书需要添加–ecc)
acme.sh --renew -d example.com --force --ecc

Diffie–Hellman (D-H) DH秘钥

这个秘钥提供安全的信息交换,注意长度必须大于1024
可以使用Mozilla提供的秘钥但是我喜欢自己生成一个更长的(比如4096位但其实可能没必要)
openssl dhparam -out /path/to/dhparam.pem 4096
秘钥越长生成时间也越长,4096位感觉快10分钟才搞定,可能在自己电脑上生成好了再扔到服务器上好点

nginx配置

我的配置是这样,nginx需要ngx_http_v2_module(http2支持)和ngx_http_ssl_module(SSL支持),在nginx编译时加入–with-http_ssl_module –with-http_v2_module
Mozilla提供一个网站可以快速配置server,在Mozilla的wiki上也有相关推荐配置,我这里改了一部分以提高安全性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#user  nobody;
worker_processes 1;

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;

# generated 2020-04-28, Mozilla Guideline v5.4, nginx 1.18.10, OpenSSL 1.1.1g, modern configuration
# https://ssl-config.mozilla.org/#server=nginx&version=1.18.10&config=modern&openssl=1.1.1g&guideline=5.4
events {
worker_connections 1024;
}

http {
include mime.types;
charset utf-8;
sendfile on;
keepalive_timeout 120;

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;

gzip on; #禁止gzip压缩输出防止BREACH攻击

log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';

#80端口自动301跳转
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
if ($host != "a-wsl.com") {
return 404; #禁止ip直接访问
}
return 301 https://$host$request_uri;
}

#443的https配置
server {
listen 443 ssl http2; #开启http2
listen [::]:443 ssl http2;

ssl_certificate /path/to/keyfile/in/nginx/cert.pem; #几个重要的
ssl_certificate_key /path/to/keyfile/in/nginx/key.pem; #证书位置
ssl_trusted_certificate /path/to/keyfile/in/nginx/ca.pem; #自己改
ssl_dhparam /usr/local/nginx/ssl/dhparam.pem; #dhparam证书
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets on;

# modern configuration
ssl_protocols TLSv1.3 TLSv1.2; #允许TLS1.3 如果需要兼容性开启TLSv1.2也好
ssl_prefer_server_ciphers on; #优先使用服务器侧秘钥防止BEAST攻击
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

ssl_ecdh_curve auto; #等同于 x25519:secp256r1:x448:secp521r1:secp384r1;
ssl_stapling on; #开启SSL装订
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=31560000; includeSubDomains" always; #强制https

resolver 1.1.1.1; #DNS解析地址,1.1.1.1是cloudflare的,国内服务器可以换一个

add_header X-Frame-Options DENY; #禁止xframe
add_header X-Content-Type-Options nosniff; #禁止MIME嗅探

access_log /usr/local/nginx/logs/host.access.log compression;
access_log /usr/local/nginx/logs/host.access.404.log;

if ($host != "a-wsl.com") {
return 404;
}

location / {
root /usr/local/etc/homepage;
index index.html;
}
}
}

网站安全性检查

nginx -t检查下配置文件对不对,没报错就重启一下 nginx -s reload
然后把CDN关了,Cloudflare的TLS加密关了,准备去SSL Lab跑个分
close_cdn
close_cdn_tls

上去把自己网址输上去等一会儿就能看到结果,A+评分,最近排行第一,可以
ssllab_result
ssllab_rank
之后再把CDN打开,端到端加密也打开确保安全,就万事OK啦

参考

  1. https://www.cyberciti.biz/faq/how-to-configure-nginx-with-free-lets-encrypt-ssl-certificate-on-debian-or-ubuntu-linux/
  2. https://gist.github.com/plentz/6737338