DNS劫持 + 权威机构颁发的伪造证书, 足以毁掉整个互联网.
这不是危言耸听, 而是正在发生...

刚使用StartSSL一个月出头, Mozilla基金会 就公布了关于 WoSign CA 不当行为调查报告. 报告称 WoSign & StartCom 通过故意倒填证书日期, 从而绕过浏览器对SHA-1证书的限制, 并正式提议将停止信任 WoSign & StartCom 一年内新签发的所有证书. 不过正赶上国庆, 闲来无事, 换成 Let’s encrypt 的证书, 顺便支持一下 http2 , 当真是极好的...


在干活之前, 我们先来了解一下这次事件:

事件发展:

  • Mozilla基金会 于2015年3月着手调查 WoSign 签发不再安全的SHA-1证书的问题.
  • WoSign 于2015年11月秘密收购 StartCom .
  • 疑似 StartCom 的前雇员披露 WoSign 秘密收购 StartCom . 以色列企业登记信息表明 StartCom 当前所有人确实为 WoSign CEO王高华.
  • WoSign CEO王高华对先前的纰漏表示非常愤怒, 声称这位前雇员违反了NDA保密协议, 将采取法律行动. 并依然拒绝承认收购 StartCom.
  • WoSign 的母公司 Qihoo 360 承认 WoSign 收购 StartCom.
  • WoSign CEO王高华坚称 StartCom 独立运营, 其原始系统没有发生改变.
  • StartCom 在被收购一个半月后, 其官网 StartSSL.com 于2015年12月18日暂停服务并升级系统, 同月22日重新开放, 并开始使用 WoSign 的基础设施签发证书.
  • Mozilla基金会 于16年9月20日公布了对 WoSign CA 不当行为的调查报告.
  • Qihoo 360 首席安全官 谭晓生 承认 Qihoo 360WoSign 的最大股东, 持有84%股权.

股权关系:

如此看来, "涉事"公司共有这么几个: StartCom / WoSign / Qihoo 360 . 其中, StartComWoSign 100%收购. 而根据Peter Bowen的调查, WoSign 股权分布如下:

WoSign 股权持有者持有比例
Qihoo 360 Software (Beijing) Co., Ltd.25.61%
Beijing Qifutong Technology Co., Ltd.29.77%
Beijing Yuan Tu Technology Co., Ltd.28.62%
WoSign CEO Gaohua Wang (an individual)12.00%
       Ganfu Zhang (an individual) |  4.00% 


值得注意的是: Beijing Qifutong Technology Co., Ltd.(奇付通) & Beijing Yuan Tu Technology Co., Ltd. [属 Qihoo 360 的可变利益实体的附属公司]6. Qihoo 360 分别占股 100% & 70%.
也就是说: 在股权方面, Qihoo 360 直接或间接持有 StartCom 75% 以上的股份. 而实际运作方面, 管理 WoSign & StartCom 中国区所有业务的, 正是 Qihoo 360 (对外称为技术支持).

StartCom / WoSign 做错了什么:

  • WoSign 在没有审核域名归属的情况下, 给申请者颁发了一张 GitHub 根域名的SSL证书.
  • StartCom & WoSign 伪造证书签发日期, 试图规避 SHA-1 停用政策.
  • 即使有充分的技术证据证明 WoSign 已经100%收购 StartCom , WoSign CEO王高华仍然拒绝承认收购 StartCom .
  • 即使有充分的技术证据证明 StartCom 使用 WoSign 的基础设施签发证书, WoSign CEO王高华仍坚称 StartCom 独立运营, 其原始系统没有发生改变.

可能会发生什么:

试想: 我要截获你发送给你朋友的快递(数据包), 需要几个步骤?

  1. 篡改收件地址(DNS劫持), 使包裹发送到错误的地点.
  2. 拿着你朋友的身份证(权威机构颁发的伪造证书), 假装我是你朋友, 收下邮件.

那么, 反观中国互联网, 第一道防线已经被我大天朝特有的 中国长城防火墙 (DNS劫持 & DNS污染)攻破. 而 StartCom & WoSign (可能还有 CNNIC )这么一搞, 第二道防线(权威机构颁发的证书)也不能保证数据的安全了. 即使这些组织义正言辞地说:"我们不会监控大家的数据"/ "我们不会泄露隐私"/ "我们是为了大家的信息安全着想". 我们也会有些许不自在: 毕竟当某个机构可以监控互联网上的所有讯息和数据, 谁知道他们会拿去做什么? 如果这个组织混有图谋不轨的成员, 后果可想而知...

不容忽略的事实:

  • WoSign 不光通过了通过了 微软认证 / Google Chrome认证 / Android 国际认证 , 还通过了 WebTrust 国际认证 , 甚至成为了中国大陆唯一一家加入 国际CA/浏览器产业联盟 的成员单位. 但到目前为止, 除了 Mozilla基金会 , 其余认证机构均没有对这次事件做出回应.
  • 此次事件中 Mozilla基金会 站在了道德制高点, 指出 StartCom / WoSign 的种种罪行并加以处罚. 但值得注意的是: 现有的免费SSL证书提供商一共有两家: StartCom & Let's encrypt . 如果 StartCom 已经不被大众信任, 大多数人(包括我)则会投入 Let's encrypt 的怀抱. 而 Mozilla基金会 正是 Let's encrypt 的主要赞助商之一.

Let's encrypt 证书的申请 & 使用

Let's encrypt 的申请证书过程很简便:

  1. 打开 Let's encrypt 官网
  2. 点击 Get Started
  3. 根据实际需求和说明文档, 我选择使用 Certbot 来管理证书.
  4. 选择Web服务器软件和操作系统, 这里我用 Nginx & Ubuntu 16.04 .
  5. putty链接服务器, 输入命令: (如果不把lnmp关掉的话是不能正确获取到证书的)
lnmp stop
sudo apt install letsencrypt
letsencrypt certonly --standalone -d 8023.moe -d www.8023.moe
  1. 根据提示, 证书已经放在了 /etc/letsencrypt/live/8023.moe .
  2. 修改Nginx配置文件 /usr/local/nginx/conf/vhost/8023.moe.conf , 添加/ 修改代码(注释部分为不再使用的 StartSSL 证书):
ssl on;
ssl_certificate /etc/letsencrypt/live/8023.moe/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/8023.moe/privkey.pem;
#ssl_certificate /usr/local/nginx/certs/8023.moe/1_8023.moe_bundle.crt;
#ssl_certificate_key /usr/local/nginx/certs/8023.moe/8023moe.key;
  1. 执行第一条命令添加计划任务(软件有Bug, 有几率提示 letsencrypt.client:Registering without email! , 不影响使用.) 但我选择隔三个月手动输入第二条命令续期:
letsencrypt renew --dry-run --agree-tos
letsencrypt renew
  1. 重启Nginx( lnmp restart )或重启服务器( reboot now ).

Http2

关于 Http2 的相关知识网上已经有很多, 在此不多赘述. 大体就是 安全性更佳 & 性能大幅度的提升. 如果你想知道自己的浏览器是否支持 Http2 , 或想直观的感受 Http2Http1.1 的差距, 可以打开这个网页进行体验.

Http2 配置

注意: 我使用的 LNMPA 1.3 一键安装包已经默认支持 Http2 , 如果您使用其他的一键安装脚本或自行安装运行环境, 请先自行升级 Nginx 到 1.9.5 以上版本 / Apache 到 2.4.17 以上版本. 并自行搜索安装相关组件.

修改Nginx配置文件 /usr/local/nginx/conf/vhost/8023.moe.conf , 将 listen 443; 改为 listen 443 ssl http2 default_server; , 启用 Http2 支持.
打开 Qualys SSL Labs , 输入网址进行测试:
Test1.png
OH, 得分并不理想, 根据提示, 应该是支持弱DH密钥交换参数. 下面也给出了相关的解决方案, 只需要按照它给的步骤做就行了:

  1. 生成DH参数: openssl dhparam -out /etc/letsencrypt/live/8023.moe/dhparams.pem 2048
  2. 修改Nginx配置文件 /usr/local/nginx/conf/vhost/8023.moe.conf 添加如下内容:
ssl_session_timeout 5m;

ssl_session_cache shared:SSL:5m;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_dhparam /etc/letsencrypt/live/8023.moe/dhparams.pem;

ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

ssl_prefer_server_ciphers on;

这段配置文件大意分别是:

  • 设置会话超时时间为5分钟
  • 设置会话缓存时间为5分钟
  • 设置 SSL 协议为 TLSv1 TLSv1.1 TLSv1.2
  • 设置 SSL 加密密码类型, 其实写成 ssl_ciphers 'AES128+EECDH:AES128+EDH'; 也可, 但对WinXP和IE6的兼容性不佳.
  • 加密密码类型由服务器选择而不是客户端浏览器选择.

改完了之后文件就成了下面这样:

server
    {
        listen 443 ssl http2 default_server;
        #listen [::]:80;
        server_name 8023.moe *.8023.moe;
        index index.html index.htm index.php;
        root /home/wwwroot/8023.moe;

        if ( $host != '8023.moe' ) {
            rewrite "^/(.*)$" https://8023.moe/$1 permanent; 
        } 

        ssl on;
        ssl_certificate /etc/letsencrypt/live/8023.moe/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/8023.moe/privkey.pem;
        ssl_session_timeout 5m;
        ssl_session_cache shared:SSL:5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_dhparam /etc/letsencrypt/live/8023.moe/dhparams.pem;
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_prefer_server_ciphers on;

        #ssl_certificate /usr/local/nginx/certs/8023.moe/1_8023.moe_bundle.crt;
        #ssl_certificate_key /usr/local/nginx/certs/8023.moe/8023moe.key;

        #error_page   404   /404.html;
        include proxy-pass-php.conf;

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }

        location ~ .*\.(js|css)?$
        {
            expires      12h;
        }

       location ~ /\.
       {
           deny all;
       }

        access_log off;
    }

server
    {
       listen 80;
       #listen [::]:80;
       server_name 8023.moe *.8023.moe;
       rewrite ^(.*)$ https://8023.moe$1 permanent;
    }

再跑个分?

Test2.png

Perfect!~ Http2的配置到此结束~