Cloudflare SSL/TLS部署流程

Posted by noHentai on Wednesday, August 11, 2021

本文简单记录下一次Cloudflare SSL/TLS的部署流程以及踩过的一些坑以便备忘。

前两天在迁移自己的VPS(钱包空空后的消费降级_(:з」∠)_ ),在其他都折腾好后惯例的上一下Cloudflare的免费CDN和TLS。本来还想着导入证书改完Nginx配置文件就完事,结果没想到有一些小坑直接把我这个外行难倒一整天。幸亏最后解决了不然强迫症要犯了,同时意外的发现尽管套CF的教程已经被写烂了,但完整到包含这些坑的教程竟然没有,于是自己动手记录一下权当备忘。

Cloudflare就不多介绍了,大家肯定不陌生,所以首先准备好自己的域名和CF账号,直接进入正题。

一、添加DNS

账号登录后在主页面点击“添加站点”,输入你的域名点添加,进入到站点管理页面。

DNS选项页中,点击“添加记录”,添加一个名称为你的域名(直接输入@就是一级域名,输入任意字符为子域名)、解析到你VPS IP的A类型记录,然后打开“代理”,即多了一个橙云图标。这一步就是所谓的套CF的CDN了,当然这里可以先不急着打开代理,关闭的情况下TTL设置小一点方便调试过程中万一出问题在修改后可以快速生效,待全部配置完毕后再打开代理。

二、设置SSL/TLS选项

进入SSL/TLS选项页,“概述”子选项页内的选项先不要动,“边缘证书”子选项页中暂时先按下图设置。

如果还没对域名下发边缘证书就可以先等一会儿,等到下发有效后再进行后续设置。

进入“源服务器”子选项卡,点击“创建证书”。如果只需要对一级域名及其所有子域名部署证书,那直接全默认创建即可(这里默认私钥类型为RSA)。如果需要对特定子域名部署证书,那就删掉原本的域名,输入需要的子域名即可。

点击创建后就会弹出授予你的源证书(默认为PEM格式)和对应密钥。使用记事本等任意文本编辑工具,或者直接在VPS上使用Vim,复制后分别保存为任意文件名的.pem格式的源证书以及.key格式的密钥。注意备份密钥,关闭页面后将无法再次查看。同时复制粘贴后,要注意检查一下有没有任何多余的空格或者空行。

随后到这个页面:Managing Cloudflare Origin CA certificates,下载Cloudflare Origin RSA PEM。这个是Cloudflare的CA根证书,如果你需要打开到最高安全等级的选项那需要把这个加入到你自己的源证书中形成证书链。

编辑自己域名的pem证书,直接将CF根证书复制到其末尾,同样不要有任何多余的空格和空行。形如下:

-----BEGIN CERTIFICATE-----
AAA
……
BBB
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
Cloudflare Origin RSA PEM
-----END CERTIFICATE-----

随后进入这个页面:Authenticated origin pull,复制“Zone-Level — Cloudflare certificate — Certificate value”中的值,保存为任意文件名的.crt格式证书,这里默认为cloudflare.crt。这个将作为TLS客户端证书用于验证请求是否来自Cloudflare,防止中间人攻击之类的。

现在我们就得到了三个文件:

  • 域名证书及CF根证书合并的.pem格式证书链
  • 域名证书对应的.key密钥
  • Cloudflare的TLS客户端.crt证书

三、Nginx配置

我的VPS是用Nginx,这里就用Nginx举例,其他工具操作也类似。

将上述三个文件放入任意文件夹,这里就将.pem证书放入默认的“/etc/ssl/certs”,.key密钥放入“/etc/ssl/private”,.crt证书放入“/etc/nginx/certs/cloudflare.crt”。

随后修改“/etc/nginx”目录下的nginx.conf配置文件。注意,nginx.conf中可能使用include语法包含了其他目录下的配置文件,ssl相关参数可能在其他配置文件中,自行检查。

这里就直接放出我的配置文件中需要修改的有关参数,注意修改域名和文件路径为自己的。

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name your.domain;

    location /.well-known {
      alias /srv/.well-known;
      allow all;
      default_type "text/plain";
      autoindex    on;
    }
    
    client_max_body_size 40M;
    server_tokens off;
    root /srv/;

    index index.html index.php index.htm;

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
    }

    include /etc/nginx/apps/*;

    location ~ /\.ht {
        deny all;
    }

    location /fancyindex {

    }
}

# SSL configuration
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name your.domain;
    ssl_certificate /etc/ssl/certs/your.pem;
    ssl_certificate_key /etc/ssl/private/your.key;
    ssl_client_certificate /etc/nginx/certs/cloudflare.crt;
    ssl_verify_client on;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_ecdh_curve secp384r1;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    sresolver 127.0.0.1 valid=300s;
    sresolver_timeout 5s;
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    client_max_body_size 40M;
    server_tokens off;
    root /srv/;

    index index.html index.php index.htm;
    

    # resolve multi-redirect
    if ($request_uri ~ "^[^?]*?//") {
    rewrite "^" $scheme://$host$uri permanent;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
    }

    include /etc/nginx/apps/*;

    location ~ /\.ht {
        deny all;
    }

    location /fancyindex {

    }
}

当然,我毕竟是外行,这些配置不一定是最好的,但至少能用,可以参考一些其他教程的配置以及Nginx官方的文档,同时注意保留自己需要的配置,以避免常见的无限重定向等错误。

这里解释一下部分参数:

  • server_name、ssl_certificate、ssl_certificate_key、ssl_client_certificate 分别为域名、证书路径、密钥路径、客户端证书路径,这些自不必说设置为自己对应的值;
  • 设置了客户端证书,就需要搭配ssl_verify_client on;来开启;
  • ssl_dhparam 用于保护密钥交换过程,可以使用openssl的相应命令自行生成,也可以删去不设置。
  • ssl_protocols 和 ssl_ciphers 分别是协议和算法,基本决定了网页在SSL/TLS上的兼容性。如果你需要在安全性和兼容性上权衡,就需要修改这两个参数的设置。这里注意,ssl_protocols 需要加上“TLSv1.3”这个值,原因后述。

配置文件修改完毕后,保存,执行以下命令验证配置文件语法无报错后,重新启动Nginx即可生效。

ngingx -t   #验证配置文件
nginx -s reload    #重新载入配置文件

四、收尾

回到Cloudflare里的SSL/TLS页面。如果你遵照了上述的配置,那么理论上所有的安全选项都可以顺利开启。如果刚才没有在DNS选项页中打开代理,想套CF CDN的话记得回头打开。以下总结一些注意点,即一些坑。

  • 概述”选项卡中可以直接选择“完全(严格)”;
  • 在“边缘证书”选项卡中,如果你刚才没有在ssl_protocols中加入TLS 1.3,那么这里就务必不要开启TLS 1.3,否则必然会出现525的SSL握手错误(这也是我折腾了一天没发现的地方);
  • 最低TLS版本保持默认TLS 1.0即可,如需修改注意修改对应Nginx配置文件;
  • 如果需要开启HSTS,那么请在Nginx配置文件中利用“add_header”加入“Strict-Transport-Security”这个HTTP头部信息;
  • 在“源服务器”子选项卡中,开启“经过身份验证的源服务器拉取”,如果不开启这一选项会出现400错误,不想开启的话去配置文件中删去“ssl_client_certificate”和“ssl_verify_client on;”这两个参数。

以上就是网站部署免费Cloudflare SSL/TLS证书以及CDN的全部流程。

全部部署完毕后,可以去SSL/TLS安全评估报告中测试网站的SSL/TLS安全性,并根据报告修改相应设置。安全与兼容性相关设置可以参考这篇博文