お久しぶり!好久没有写过新东西啦~

最近使用 Internet Explorer 和 Microsoft Edge 访问博客首页的时候发现特别慢。

打开 Developer Tools 对网站做了 Profiler 后发现 Google Fonts 所占用的 Waiting 时间实在是太长,虽然说现在 googleapis 是能够正常解析了,但是速度还是相当的不忍直视。

解决办法有三:

  1. 禁用 Google Fonts
  2. 使用国内镜像
  3. 使用国外 VPS 做反代

第一种办法无疑是得不偿失的,为了速度而牺牲了整个网页的美观性。

第二种办法看起来挺理想,但是

  1. 大多数国内镜像不支持 HTTPS(对于追求小绿锁的我来说这是绝对不能忍的)
  2. 大多国内访问优秀,国外速度堪忧
  3. 反代在别人服务器上,稳定性没有保障

由于最近博客迁移到了 Azure 上,响应时间和速度还是比较有保证的,最终我选择了第三种方案。


特此声明,本文仅适用于带宽充裕,响应时间较短,速度较快的国外 VPS ,国内机基本免谈

设立反向代理的条件如下:

  1. nginx-extra(Ubuntu 里 apt-get install nginx 出来的 Nginx 并不支持 SSL)
  2. 域名(其实没有域名的话随意弄个免费的 tk 域名也可以)
  3. (可选)SSL 证书(假如你不需要 HTTPS,可以不要)

  • 关于 Nginx 如何安装,点击这里有传送门直达
  • 接下来我要暴力贴出配置,并在必要的地方加上注释,跟着修改即可使用

第一步,创建让 Nginx 存放反代缓存的目录

sudo mkdir -p /var/cache/nginx/cache
sudo mkdir -p /var/cache/nginx/temp

第二步,暴力复制、修改配置文件

正常情况下 Nginx 会在配置文件中 include /etc/nginx/sites-enabled/* 和 include /etc/nginx/conf.d/*.conf

(评论中的 dant 菊苣指出,Debian 系的 Nginx 才有 sites-{enabled,available},RH 系是没有的)

我们选择在 sites-enabled 里头创建配置

sudo vim /etc/nginx/sites-enabled/fonts-proxy.conf

复制粘贴并且根据注释修改以下内容

proxy_temp_file_write_size 128k;
proxy_cache_path  /var/cache/nginx/cache levels=1:2 keys_zone=fonts:300m inactive=7d max_size=10g;
proxy_temp_path   /var/cache/nginx/temp;

upstream google {
    server fonts.googleapis.com:443;
}

upstream gstatic {
    server fonts.gstatic.com:443;
}

server {
    listen 80;
    #将下面的 font.lawrencexs.xyz 替换成你要做反代用的域名
    server_name font.lawrencexs.xyz;
    #限制引用的域名。按需改成自己要用到字体库的域名。做公益服务需要去掉下面的一行以及if
    valid_referers server_name *.lawrencexs.xyz *.winooxx.tk;
    if ($invalid_referer) {
        return 404;
    }

    resolver 8.8.8.8;

    location /css {
    #将下面的 font.lawrencexs.xyz 替换成你要做反代用的域名
        sub_filter 'fonts.gstatic.com' 'font.lawrencexs.xyz';
        sub_filter_once off;
        sub_filter_types text/css;
        proxy_pass_header Server;
        proxy_set_header Host fonts.googleapis.com;
        proxy_set_header Accept-Encoding '';
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass https://google;
        proxy_cache fonts;
        proxy_cache_valid  200 304 365d;
        proxy_cache_key $host$uri$is_args$args;
        expires max;
    }

    location /icon {
    #将下面的 font.lawrencexs.xyz 替换成你要做反代用的域名
        sub_filter 'fonts.gstatic.com' 'font.lawrencexs.xyz';
        sub_filter_once off;
        sub_filter_types text/css;
        proxy_pass_header Server;
        proxy_set_header Host fonts.googleapis.com;
        proxy_set_header Accept-Encoding '';
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass https://google;
        proxy_cache fonts;
        proxy_cache_valid  200 304 365d;
        proxy_cache_key $host$uri$is_args$args;
        expires max;
    }

    location / {
        proxy_pass_header Server;
        proxy_set_header Host fonts.gstatic.com;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass http://gstatic;
        proxy_cache fonts;
        proxy_cache_valid  200 304 365d;
        proxy_cache_key $host$uri$is_args$args;
        expires max;
    }
}

#如果你没有证书或者不需要 HTTPS 访问,那么下面这部分你不需要再看了

server {
    #监听 443 端口
    listen 443 ssl spdy;

    #打开 HTTPS
    ssl on;

    #替换下面的证书
    ssl_certificate /etc/ssl/certs/lawrencexs.xyz.crt;
    ssl_certificate_key /etc/ssl/private/lawrencexs.xyz.key;

    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
    keepalive_timeout 70;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    #将下面的 font.lawrencexs.xyz 替换成你要做反代用的域名
    server_name font.lawrencexs.xyz;

    #限制引用的域名。按需改成自己要用到字体库的域名。公益服务需要去掉下面的一行以及if
    valid_referers server_name *.lawrencexs.xyz *.winooxx.tk;
    if ($invalid_referer) {
        return 404;
    }

    resolver 8.8.8.8;

    location /css {
    #将下面的 font.lawrencexs.xyz 替换成你要做反代用的域名
        sub_filter 'fonts.gstatic.com' 'font.lawrencexs.xyz';
        sub_filter_once off;
        sub_filter_types text/css;
        proxy_pass_header Server;
        proxy_set_header Host fonts.googleapis.com;
        proxy_set_header Accept-Encoding '';
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass https://google;
        proxy_cache fonts;
        proxy_cache_valid  200 304 365d;
        proxy_cache_key $host$uri$is_args$args;
        expires max;
    }

    location /icon {
    #将下面的 font.lawrencexs.xyz 替换成你要做反代用的域名
        sub_filter 'fonts.gstatic.com' 'font.lawrencexs.xyz';
        sub_filter_once off;
        sub_filter_types text/css;
        proxy_pass_header Server;
        proxy_set_header Host fonts.googleapis.com;
        proxy_set_header Accept-Encoding '';
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass https://google;
        proxy_cache fonts;
        proxy_cache_valid  200 304 365d;
        proxy_cache_key $host$uri$is_args$args;
        expires max;
    }

    location / {
        proxy_pass_header Server;
        proxy_set_header Host fonts.gstatic.com;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass https://gstatic;
        proxy_cache fonts;
        proxy_cache_valid  200 304 365d;
        proxy_cache_key $host$uri$is_args$args;
        expires max;
    }
}

最后一步,让 Nginx 重载配置文件

sudo nginx -s reload

如果中间不出差错,那么你就可以使用你新设的反代地址去替换 fonts.googleapis.com 了。

Enjoy! お楽しみください!

开启 SSL

首先我们先启用 SSL

listen 443 ssl;
server_name www.example.com;
ssl on;
ssl_certificate /etc/ssl/certs/example.crt;
ssl_certificate_key /etc/ssl/private/www_example_com.key;

其中 example.crt 是网站证书,www_example_com.key 是证书私钥.

需要注意的是,大部分 CA 提供的证书都是多级,所以可能需要我们把多个证书合并成一个,这样可以减少浏览器额外下载中间证书的次数。

合并方法其实非常简单,使用记事本一类的文本编辑软件打开 example.crt ,然后根据 CA 提供给你的证书链,逐个打开证书,按照顺序依次粘贴到 example.crt 的末尾就可以啦。

生成并配置 dhparam.pem

$ openssl dhparam -out dhparam.pem 4096

将 dhparam.pem 配置到 Nginx

ssl_dhparam /etc/ssl/certs/dhparam.pem;

协议和 ciphers 的选择和配置

对于不在意评分和安全性的人们,这方面倒是不必要考虑这么多。

但是对于想拿 A+ 评分的来说,我们必须抛弃一些不安全的 ciphers 和协议。

这个配置中的 ciphers 支持大多数浏览器,但不支持 XP/IE6 。

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_stapling on;
ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384: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: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 Session 配置

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

HSTS 配置

这个对评分影响也比较大,但如果开启这个,需要全站开启 HTTPS 。

HSTS(HTTP Strict Transport Security)国际互联网工程组织IETE正在推行一种新的Web安全协议,其作用是强制客户端(如浏览器)使用HTTPS与服务器创建连接。

采用HSTS协议的网站将保证浏览器始终连接到该网站的 HTTPS 加密版本,不需要用户手动在 URL 地址栏中输入加密地址。

该协议将帮助网站采用全局加密,用户看到的就是该网站的安全版本。

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

完整配置

server {
        listen 443 ssl;
        server_name www.example.com;
        ssl on;
        ssl_certificate /etc/ssl/certs/ssl-bundle.crt;
        ssl_certificate_key /etc/ssl/private/www_example_com.key;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_stapling on;
        ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384: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: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;
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
}