Nginx 反向代理 Apache SSL
笔者的 VPS 上运行了一个 Apache 的 PHP 服务,采用 HTTP 协议。现在打算为这个服务升级为 HTTPS,所以借用了 Nginx 反向代理实现目标。
环境
- RHEL 7.4
- Apache 2.4
- Nginx 1.10.1
前提
- 安装 Apache Web Server,若没安装则参考安装指南。
- 安装 Nginx(开启 SSL 模块)。
注:如果之前为 Apache Web Server 配置过 SSL,则需要通过移除
mod_ssl
的方式关闭 Apache 的 SSL 功能:
1
$ sudo yum -y remove mod_ssl
Apache 更改默认端口
Nginx 替代 Apache 作为最外层,所以需要腾出 Apache 的 80 端口,改为任意的空闲端口,仅供内网使用,如改为 7890。
取得 root 权限,修改配置文件 /etc/httpd/conf/httpd.conf
,把 Listen 80
改为 Listen 7890
。
SELinux 规则开放新端口 7890
:
1
$ sudo semanage port -a -t http_port_t -p tcp 7890
确认端口 7890
已添加:
1
2
$ sudo semanage port -l | grep -w http_port_t
http_port_t tcp 7890, 80, 81, 443, 488, 8008, 8009, 8443, 9000
重启 Apache:
1
$ sudo systemctl restart httpd
检查新端口是否生效:
1
2
$ sudo netstat -ntlp |grep httpd
tcp6 0 0 :::7890 :::* LISTEN 18000/httpd
安装 certbot
对于 RHEL 7,需要下载存 EPEL 7 储包,才可提供 certbot 的依赖项:
1
$ sudo wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
安装 EPEL 7:
1
$ sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
启用 EPEL:
1
$ sudo yum-config-manager --enable epel*
确认开启 EPEL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sudo yum repolist all
...
repo id repo name status
epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 enabled: 12607
epel-debuginfo/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 - Debug enabled: 2791
epel-source/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 - Source enabled: 0
epel-testing/x86_64 Extra Packages for Enterprise Linux 7 - Testing - x86_64 enabled: 702
epel-testing-debuginfo/x86_64 Extra Packages for Enterprise Linux 7 - Testing - x86_64 - Debug enabled: 110
epel-testing-source/x86_64 Extra Packages for Enterprise Linux 7 - Testing - x86_64 - Source enabled: 0
...
安装依赖及开启 channel:
1
2
$ sudo yum -y install yum-utils
$ sudo yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
安装 certbot:
1
$ sudo yum -y install python2-certbot-nginx
获取 certbot 证书
确保 VPS 对外开放端口 80 及 443,为指定域名获取证书,如本例域名为 api.cotes.info
:
1
$ sudo certbot certonly --standalone -d api.cotes.info
获取成功的输出信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
tls-sni-01 challenge for api.cotes.info
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/api.cotes.info/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/api.cotes.info/privkey.pem
Your cert will expire on 2018-09-27. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
其中包含了证书文件的目录:
/etc/letsencrypt/live/api.cotes.info/fullchain.pem
/etc/letsencrypt/live/api.cotes.info/privkey.pem
另外还有证书的到期时间 2018-09-27
。
修改 Nginx 配置
在配置文件 nginx.conf
的 http
模块里添加两个 server
模块:
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
http {
...
# Https for Apache
server {
listen 443 ssl;
ssl on;
server_name api.cotes.info;
ssl_certificate /etc/letsencrypt/live/api.cotes.info/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.cotes.info/privkey.pem;
location / {
proxy_pass http://127.0.0.1:7890;
proxy_redirect off;
proxy_set_header Host api.cotes.info;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~ /\.ht {
deny all;
}
}
## Apache http port 80
server {
listen 80;
server_name api.cotes.info;
rewrite ^(.*) https://$server_name$1 permanent;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
# other settings ...
}
修改配置后执行语法检测:
1
$ nginx -t
通过检测后重新加载配置文件:
1
$ nginx -s reload
certbot 自动更新
更新前必须先确保申请机的 443 端口保持空闲状态,因为 Let's Encrypt 服务器会访问申请机器的 443 端口。上述运行着的 Nginx SSL/TLS 反代服务会占用 443 端口,所以必须暂时关闭 Nginx,再使用 certbot 命令执行更新,完毕后重新开启 Nginx 服务。
将上述原理写成 Shell 脚本,命名为 certbot-updater.sh
。添加内容:
1
2
3
4
5
6
7
#!/bin/bash
if [[ $(certbot certificates |grep "INVALID: EXPIRED") ]]; then # Check if the certificaties has expired.
nginx -s stop && \
certbot renew --no-self-upgrade && \ # Update certificaties
nginx
fi
if
中判断证书是否过期的逻辑,是通过 certbot 证书状态输出信息做判断,更加严谨点可以根据具体的过期日期转换为时间,和当前查询时间对比作为判断依据。
现在上述脚本文件放置到心仪的目录下,由 crontab 添加定时调用任务即可。
在系统文件 /etc/crontab
添加一行内容:
1
39 1,13 * * * root /usr/bin/bash /path/to/certbot-updater.sh
上述定时计划表示,每天 01:39 和 13:39,以 root 身份运行 certbot 的证书更新脚本。
最后,重启 cron 守护进程:
1
$ sudo systemctl restart crond
Comments powered by Disqus.