Cloudflare 代理自签名 HTTPS 证书的源站
源站使用 Cloudflare 的 CDN 服务非常方便,只要将 DNS 托管在 Cloudflare 平台,然后设置 DNS 记录时,代理状态勾选「已代理」就行了。不过这一步操作无法选择源站使用的是 HTTP 协议还是 HTTPS 协议,依稀记得有个地方是可以设置的。翻了一遍操作菜单,在左侧导航菜单的「STL/TLS > 概述」里找到了,加密模式有如下四个选项:
- 关闭(不安全)
未应用加密。关闭 SSL 将禁用 HTTPS,浏览器同时会显示警告,指出您的网站不安全。 - 灵活
仅在访问者与 Cloudflare 之间启用加密。这可以避免浏览器发出安全警告,但 Cloudflare 与您的源服务器之间的所有连接均通过 HTTP 建立。 - 完全
启用加密端到端。当您的源服务器支持 SSL 认证但未使用有效的公开可信的证书时,使用此模式。 - 完全(严格)
(推荐模式)启用端到端加密,对源服务器证书强制执行验证。使用 Cloudflare 的源服务器 CA 为您的源服务器生成证书。
不过这个设置是全局的,更改后会对当前站点下所有的 DNS 记录生效。Cloudflare 不支持针对每条 DNS 记录设置单独的加密模式,也不支持 HTTPS -> HTTP 的 Fallback 策略。
此前该站点下的所有二级域名对应的源站都是仅 HTTPS 协议的,这次要添加的二级域名源站是仅 HTTP 协议的。如果将加密模式设置为「灵活」的话,势必要启用所有源站的 HTTP 端口。最好的解决办法就是为这次添加的源站开启 HTTPS 协议。只要将加密方式设置为“完全”,就可以使用自签名证书的 HTTPS 服务。
源站建立在一台 CentOS 7 系统的小型 VPS 上,使用 Nginx 提供 HTTP 服务。打开 Nginx 默认配置文件 /etc/nginx/nginx.conf,去掉下面配置的注释(如果没有则添加):
nginxserver {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _;
root /usr/share/nginx/html;
ssl_certificate "/etc/pki/nginx/server.crt";
ssl_certificate_key "/etc/pki/nginx/private/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
使用 OpenSSL 创建站点证书:
sh# 不对外服务,密钥长度选择 1024 足够了
openssl genrsa -out server.key 1024
# 下行命令需要填写一些信息
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -signkey server.key -out server.crt
# 如果 /etc/pki/nginx 目录不存在则手动创建
mv server.key /etc/pki/nginx/private/server.key
mv server.crt /etc/pki/nginx/server.crt
完成配置后使用 systemctl reload nginx
命令使 Nginx 配置生效。
问题一
如果发生以下错误:
[emerg] cannot load certificate "/etc/pki/nginx/server.crt": BIO_new_file() failed (SSL: error:0200100D:system library:fopen:Permission denied:fopen('/etc/pki/nginx/server.crt','r') error:2006D002:BIO routines:BIO_new_file:system lib)
错误原因多半是因为开启了 SELinux,使用 sestatus
命令,如果返回如下信息则表示 SELinux 已启用:
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
使用 ls --scontext /etc/pki/nginx/server.crt
命令查看文件的 security context:
unconfined_u:object_r:admin_home_t:s0 /etc/pki/nginx/server.crt
由于证书之前是在 /root 目录下创建的,因此证书类型是 admin_home_t
。现在只要重置文件 scontext 类型就可以了:
shrestorecon -v -R /etc/pki/nginx/server.crt
ls --scontext /etc/pki/nginx/server.crt
显示信息如下则表示重置成功:
unconfined_u:object_r:cert_t:s0 /etc/pki/nginx/server.crt
对 /etc/pki/nginx/private/server.key 进行同样操作。最后重启 Nginx 服务即可。
问题二
当站点配置为 proxy_pass http://127.0.0.1:8000;
时,访问服务器出现 502 网关错误:
connect() to 127.0.0.1:8000 failed (13: Permission denied) while connecting to upstream
同样是因为开启了 SELinux 导致的。运行如下命令允许 Nginx 访问网络:
shsetsebool -P httpd_can_network_connect 1