0x01 前言
我建站都适用Wordpress ,而无论是Wordpress 本体还是模版甚至是插件或多或少都有使用Google 的fonts 库与ajax 库。其实Wordpress 正常情况下是很快的、效率是很高的,因为使用了Google 某些服务的原因而导致某些资源不断处于加载状态。
如果你的网站并没有使用HTTPS协议,也可以选择免费的360的前端公共库服务。如果你启用了HTTPS协议,又不想自己配置反向代理,请选用由中国科学技术大学ustclug 提供的服务。地址如下:
还有一种选择就是像我一样,在有足够资源的情况下自行配置反向代理。
0x02 链接结构
0x02.1 fonts.googleapis.com
首先来看看Google 的字体库,以下是这次用来做分析的链接:
https://fonts.c4.hk/css?family=Open+Sans #前面是固定的链接结构 https://fonts.c4.hk/css?family= #"family=" 后跟随的就是请求的字体,这里请求Open Sans Normal 400 这个字体 Open+Sans
如果你需要别的字体,可以到以下地址去自行配置并获取相应的引用地址:
0x02.2 fonts.googleapis.com 返还内容
/* cyrillic-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/K88pR3goAWT7BTt32Z01m4X0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
}
/* cyrillic */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/RjgO7rYTmqiVp7vzi-Q5UYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/LWCjsQkB6EMdfHrEVqA1KYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/xozscpT2726on7jbcb_pAoX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
unicode-range: U+0370-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/59ZRklaO5bWGqF5A9baEEYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/u-WUoqrET9fUeobQW7jkRYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2');
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.c4.hk/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
注意里面的url 引用地址:fonts.gstatic.com ,正是这个地址,在某些地区被禁止访问,我们需要对其进行替换。
这样一来,我们需要用一个域名对两个Google 地址进行反向代理,有点复杂,但不难。
0x02.3 ajax.googleapis.com
ajax 的情况比fonts 要好,直接通过代理就好了,并不需要过多分析:
ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver=3.4.2
0x03 反向代理 fonts.googleapis.com
因为我所配置的所有的网站都使用HTTPS 协议,所以配置文件中包含有nginx SSL 部分。但这里并不对nginx SSL 展开分析说明,请注意。
0x03.1 逻辑
- 用户浏览访问https://fonts.odin.org.cn/css?family=Open+Sans ;
- nginx 检测到/css 这个路径适配其中一个location ,将请求转发到fonts.googleapis.com;
- nginx 接收fonts.googleapis.com 返还的内容,并将其中的https://fonts.c4.hk 替换为 //fonts.odin.org.cn ,并将内容重新打包转发给用户;
- 用户接收到修改过的内容并按需获取字体文件,但地址访问的地址是修改过的fonts.odin.org.cn;
- nginx 再次接受到用户的请求并检测到路径/ 适配其中一个location ,所以将这个请求转发到https://fonts.c4.hk;
- nginx 接收到fonts.gstatic.com 返还的内容,原封不动地转发给用户。
0x03.2 配置server 块
server {
#监听https 端口
listen 443 ssl http2;
#监听http 端口
listen 80;
#绑定域名
server_name fonts.odin.org.cn;
#启用SSL 模块
ssl on;
#SSL 数字证书位置
ssl_certificate /your ssl crt. path/odin.org.cn.crt;
#SSL 数字证书密钥路径
ssl_certificate_key /usr/local/nginx/ssl/odin.org.cn.key;
#SSL 缓存
ssl_buffer_size 16k;
#SSL 算法
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:DES-CBC3-SHA;
#
ssl_prefer_server_ciphers on;
#SSL 协议
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#
ssl_session_cache builtin:20480 shared:SSL:10m;
#
ssl_session_timeout 10m;
#
ssl_stapling on;
#
ssl_session_tickets on;
}
0x03.3 反向代理 fonts.googleapis.com
需要先获取fonts.googleapis.com 返还的内容,才能对其中的内容作出修改,所以先配置反向代理fonts.googleapis.com 的location 块。
因为要通过一个私有地址代理两个Google 地址,所以要通过链接结构进行区分,而所有字体都在(fonts.googleapis.com/css )css 目录下,所以对css 目录下的文件进行反向代理:
#设定路径
location /css {
#设定Host 头部,告知源服务器要访问那个域名的资源
proxy_set_header Host fonts.googleapis.com;
#将css 目录下的所有请求转发到https:\/\/fonts.googleapis.com
#请忽略转义符,因为我配置文件的原因,要在正文内加入转义符才能正常显示某些地址
proxy_pass https:\/\/fonts.googleapis.com;
#保留源站的响应头
proxy_pass_header Server;
#因为要替换返还的内容,通过Accept-Encoding 防止源站返回压缩过的内容。压缩过的内容不能被替换!
proxy_set_header Accept-Encoding '';
#将用户的真实IP 包含在请求内容中
proxy_set_header X-Real-IP $remote_addr;
#将请求协议包含在请求内容中,其实这行可以去掉
proxy_set_header X-Scheme $scheme;
#禁止跳转
proxy_redirect off;
#默认sub_filter_once 是处于on ,关闭它以便一次替换多行
sub_filter_once off;
#允许替换内容的文件类型,其实这里只有text/css 这一种类型,但我为了方便而实用通配符*
sub_filter_types *;
#将返还回来的内容里匹配https://fonts.c4.hk 的字符替换为 //fonts.odin.org.cn
#因为我要适配http 的使用情况,而不得不设置为 //fonts.odin.org.cn 。
#如果你确定只用于http 或 https ,也可以加上协议:http://fonts.odin.org.cn 或 https//fonts.odin.org.cn
sub_filter 'https://fonts.c4.hk' '//fonts.odin.org.cn';
}
注意:请将上面代码中的地址fonts.odin.org.cn 替换为你自己的地址!
0x03.4 反向代理fonts.gstatic.com
#设定路径
location / {
#设定Host 头部,告知源服务器要访问那个域名的资源
proxy_set_header Host fonts.gstatic.com;
#将/ 目录下的所有请求转发到https://fonts.c4.hk
proxy_pass https://fonts.c4.hk;
#保留源站的响应头
proxy_pass_header Server;
#将用户的真实IP 包含在请求内容中
proxy_set_header X-Real-IP $remote_addr;
#将请求协议包含在请求内容中,其实这行可以去掉
proxy_set_header X-Scheme $scheme;
#禁止跳转
proxy_redirect off;
}
0x04 反向代理ajax.googleapis.com
通过同样的方法对ajax.googleapis.com 进行反向代理:
server {
listen 443 ssl http2;
listen 80;
server_name ajax.odin.org.cn;
ssl on;
ssl_certificate /your ssl crt. path/odin.org.cn.crt;
ssl_certificate_key /usr/local/nginx/ssl/odin.org.cn.key;
ssl_buffer_size 16k;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:DES-CBC3-SHA;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache builtin:20480 shared:SSL:10m;
ssl_session_timeout 10m;
ssl_stapling on;
ssl_session_tickets on;
location / {
proxy_set_header Host ajax.googleapis.com;
#请忽略转义符,因为我配置文件的原因,要在正文内加入转义符才能正常显示某些地址
proxy_pass https:\/\/ajax.googleapis.com;
proxy_pass_header Server;
proxy_set_header Accept-Encoding '';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_redirect off;
sub_filter_once off;
sub_filter_types *;
sub_filter 'fonts.googleapis.com' 'fonts.odin.org.cn';
sub_filter 'fonts.gstatic.com' 'fonts.odin.org.cn';
sub_filter 'ajax.googleapis.com' 'ajax.odin.org.cn';
}
}
0x05 缓存
因为以上内容都是静态内容,并不会因为请求时间或地点的不同而不同,每个链接都对应唯一的响应内容,所以缓存是极其重要的。缓存可以减少对Google 服务器访问的次数,从而减少响应时间。
首先要在nginx.conf 的http 块中添加以下内容:
#proxy_cache_path 缓存文件存放路径,请根据需要自行设置并自行建立文件夹
#levels 定义文件夹的级数,例如:
/*
proxy_cache_path /var/tmp/nginx/proxy_cache levels=1:2 keys_zone=one:10m;
#路径和文件名像这样:
/var/tmp/nginx/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c
*/
#keys_zone 定义缓存区域名称与大小
#inactive 缓存有效期,当文件在设定的时间内没有被访问将被删除
#最大容量,如果超出,将删除使用率最低的文件
proxy_cache_path /var/tmp/nginx/proxy_cache levels=1:2 keys_zone=content:10g inactive=30d max_size=15g;
#为每一个缓存文件建立唯一的key
proxy_cache_key $host$proxy_host$uri$is_args$args;
然后在每个location 添加以下内容:
#定义要使用的缓存区域 proxy_cache content; #给对应的状态码设置缓存有效期,这里的状态码是指源站返回的状态码 proxy_cache_valid 200 304 301 302 30d; proxy_cache_valid any 30s;
0x06 结语
我将我自己反向代理fonts.gstatic.com 、ajax.googleapis.com 和gravatar.com 的配置文件放在Github ,有需要的朋友请到以下链接查看:
0x07 相关视频
https://www.bilibili.com/video/av11438151/





















