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/