Cloudflare 四种 SSL/TLS 加密模式的功能解析及实践

在没套 Cloudflare 之前有在 Nginx 中配置 HTTP 访问 301 重定向到 HTTPS 的习惯,但是在套了 CF 之后常常出现 301 重定向次数过多的情况,不明白原理地瞎调试走了很多弯路,重新实践一遍并整理为笔记方便自己回顾。


这里就以各模式作为区分,总共 4 种模式就分为 4 个小章节。
注意:这四种模式仅在开启了 Cloudflare 的 CDN 后才有效,仅把 Cloudflare 作 DNS 使用时以下加密模式均不会生效! 各模式

1、模式:关闭(不安全)
这个模式会将所有用户对你站点的 HTTPS 请求重定向到 HTTP,官方描述:

Setting your encryption mode to Off (not recommended) redirects any HTTPS request to plaintext HTTP.

优点:没有
缺点:

  • 容易遭受到中间人攻击
  • Chrome 等浏览器会显示该网站不安全
  • 影响搜索引擎收录

实践:
① HTTP 访问(未在 Nginx 配置中开启 HTTP 访问重定向到 HTTPS):
1-1
② HTTPS 访问(未在 Nginx 配置中开启 HTTP 访问重定向到 HTTPS):
注:这里我已经手动改为 https://ssl.ceshiku.cn 但是被重定向回了 HTTP。
1-2
③ HTTP 访问(已经在 Nginx 配置了 HTTP 访问重定向到 HTTPS):
注:循环重定向了,比较好理解:HTTP 访问到 Nginx 被重定向到了 HTTPS,HTTPS 到 Cloudflare 又被重定向到了 HTTP,循环往复……
1-3
④ HTTPS 访问(已经在 Nginx 配置了 HTTP 访问重定向到 HTTPS):
注:同 HTTP 访问一样循环重定向。
1-4

2、模式:灵活
这个灵活并不是指 Cloudflare 会自动辨别对源站使用 HTTP 或 HTTPS 访问,而是指:用户到 Cloudflare 的访问是强制 HTTPS 加密的,证书由 Cloudflare 提供;而 Cloudflare 到源服务器的访问是强制 HTTP 的,因此源站不需要配置证书。
我觉得翻译为半程加密会更合理一些,官方描述:

Setting your encryption mode to Flexible makes your site partially secure. Cloudflare enforces HTTPS between your visitor and Cloudflare, but all connections between Cloudflare and your origin are made through HTTP. As a result, an SSL certificate is not required on your origin.

优点:

  • 简单,源站不需要配置 HTTPS 证书

缺点:

  • 在 Cloudflare 到源站中仍存在中间人攻击的风险

实践:
① HTTP 访问(未在 Nginx 配置中开启 HTTP 访问重定向到 HTTPS):
注:成功变成了 HTTPS 访问,证书是 Cloudflare 提供的。
2-1
② HTTPS 访问(未在 Nginx 配置中开启 HTTP 访问重定向到 HTTPS):
注:源站配置了证书但未使用。
2-2
③ HTTP 访问(已经在 Nginx 配置了 HTTP 访问重定向到 HTTPS):
注:循环重定向:Cloudflare 到源站的 HTTP 请求被 Nginx 重定向到了 HTTPS,接着 HTTPS 请求经过 Cloudflare 又变回了对源站的 HTTP 请求……
2-3
④ HTTPS 访问(已经在 Nginx 配置了 HTTP 访问重定向到 HTTPS):
注:同 HTTP 访问一样循环重定向。
2-4

3、模式:完全
全程加密但不完全:如果用户发出的是 HTTP 请求,那么用户到 Cloudflare 和 Cloudflare 到源站均会使用 HTTP 协议;如果用户发出的是 HTTPS 请求,那么用户到 Cloudflare 会使用 Cloudflare 提供的证书进行加密,而 Cloudflare 到源站会使用源站的证书进行加密。
官方描述:

When you set your encryption mode to Full, Cloudflare enforces HTTPS between your visitor and Cloudflare and makes connections to the origin using the scheme requested by the visitor. If your visitor uses http, then Cloudflare connects to the origin using plaintext HTTP and vice versa.

优点:

  • 使用此模式可以兼容 Nginx 配置 HTTP 重定向到 HTTPS
  • 源站可以使用自签证书

缺点:

  • 在 Cloudflare 到源站中仍存在中间人攻击的风险(包括通过证书劫持和伪造等方式,不同于严格模式,Cloudflare 不会对源站的证书进行审核)

实践:
① HTTP 访问(未在 Nginx 配置中开启 HTTP 访问重定向到 HTTPS):
3-1
② HTTPS 访问(未在 Nginx 配置中开启 HTTP 访问重定向到 HTTPS):
注:源站配置了证书,但在浏览器端显示的是用户和 Cloudflare 之间加密所用的证书。
3-2
③ HTTP 访问(已经在 Nginx 配置了 HTTP 访问重定向到 HTTPS):
注:跳转到了 HTTPS。
3-3
④ HTTPS 访问(已经在 Nginx 配置了 HTTP 访问重定向到 HTTPS):
3-4

4、模式:完全(严格)
和完全模式实现的功能一样,但是新增了对证书的认证:源站如果配置了自签证书、非可信证书或过期证书,那么 Cloudflare 会回复客户端访问失败并返回 526 响应代码
官方描述:

When you set your encryption mode to Full (strict), Cloudflare does everything in Full mode but also enforces more stringent requirements for origin certificates.

优点:

  • 使用此模式可以兼容 Nginx 配置 HTTP 重定向到 HTTPS
  • 安全,只要用户使用 HTTPS 访问可以完全杜绝中间人攻击

缺点:

  • 四种模式中工作量最大,需要维护服务器端的证书

实践结果和第 3 种模式完全一样,不放上来了。

5、总结
① 如果你还在困惑该选哪种模式,我帮你整理了常用需求对应的模式,请参照:
总结

② 还有需要注意的会出现 301 重定向次数过多的 2 种情况:

  1. 关闭模式下在 Nginx 开启了强制重定向(HTTPS -(Cloudflare)-> HTTP -(Nginx)-> HTTPS -(Cloudflare)-> HTTP……)
  2. 灵活模式下在 Nginx 开启了强制重定向(HTTP -(Cloudflare)-> HTTP -(Nginx)-> HTTPS -(Cloudflare)-> HTTP……)

③ 最后放上完全完全(严格)模式下可以参考的 Nginx 配置:

...
...
    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        include /etc/nginx/default.d/*.conf;

        # 证书申请用
        location ~ /.well-known {
            root /usr/share/nginx;
            allow all;
        }

        # 强制重定向到 HTTPS
        location / {
            return 301   https://$host$request_uri;
        }
    }

    server {
        listen          443 ssl;
        server_name     _;
        root            /usr/share/nginx/html;

        # SSL 配置
        ssl_certificate             /etc/letsencrypt/live/ssl.ceshiku.cn/fullchain.pem;
        ssl_certificate_key         /etc/letsencrypt/live/ssl.ceshiku.cn/privkey.pem;
        ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers                 ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;

        # 以下填你的反代等配置
        ...
        ...
    }
...
...

结束。