玩转 nginx 反向代理 Google

好久没写博客了。国庆后一直不知道写点什么,加上半个月没碰了,于是就一直晾着。

最近 Github Education 活动挺火的,我也趁乱搞了几个邮箱换了几套码,主要是拿了 DigitaloceanNamecheap 的。DO 的100刀需要验证学生身份加上各种封,我是没打算继续搞了。倒是 Namecheap 管的比较松,于是拿着 NC 的码注册了一个短域名 g4w.me,以及对应的 SSL 证书。

对于我来说,短域名的好处就是用来做 xss 平台,毕竟越短越幸福 ⊙﹏⊙ 。但之前已经注册过 lxy.pw,长度一样没必要换来换去的。

另外一个的选择是做短地址跳转。前几天确实是找了套 PHP 源码搭了一个,但不去推广的话用处确实不大,而且已经有新浪的接口了。

这两天想了一下做个反向代理(简称“反代”)其实也不错,一是这个域名本身自带 SSL 证书,访问起来更安全;另外晚上在家里 ss 各种不给力,搞个反代起码能上 Google。于是就尝试在 DO 的 VPS 上搭了个 nginx 反代 Google。

根据配置的不同以及服务器台数的不同,下面的教程分为两种玩法:


✨初级玩法✨

❉ 最简单的反代

nginx 本身就是一个基于反向代理的 web server,因此要反代 Google 很简单,代码如下:

server
{
    listen          80;
    server_name     g4w.me;  #你的域名
    location / {
        proxy_pass          http://www.google.com/;  #需要反代的域名
        proxy_redirect      off;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

这样设置后我们访问 http://g4w.me 就能看到 Google 的界面了。

❉ 使用 SSL 的反代

因为已经在 Namecheap 那里申请到了 PositiveSSL 的证书,于是把证书也配置进去,顺便把 http rewrite https

# HTTP

server { listen 80; server_name www.g4w.me g4w.me; location / { rewrite ^/(.*)$ https://g4w.me$1 permanent; } }

# HTTPS

server { listen 443; server_name www.g4w.me g4w.me;

    <span class="kn">if</span> <span class="s">(</span><span class="nv">$host</span> <span class="p">=</span> <span class="s">&#39;www.g4w.me&#39;)</span> <span class="p">{</span>
        <span class="kn">rewrite</span> <span class="s">^/(.*)</span>$ <span class="s">https://g4w.me</span><span class="nv">$1</span> <span class="s">permanent</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kn">ssl_certificate</span> <span class="s">/root/ssl/g4w.me.crt</span><span class="p">;</span>
    <span class="kn">ssl_certificate_key</span> <span class="s">/root/ssl/g4w.me.key</span><span class="p">;</span>
    <span class="kn">ssl_protocols</span>   <span class="s">TLSv1</span> <span class="s">TLSv1.1</span> <span class="s">TLSv1.2</span><span class="p">;</span>
    <span class="kn">ssl_ciphers</span> <span class="s">ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:RC4-SHA:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!DSS:!PKS</span><span class="p">;</span>
    <span class="kn">ssl_prefer_server_ciphers</span>  <span class="no">on</span><span class="p">;</span>
    <span class="kn">ssl_session_cache</span>       <span class="s">shared:SSL:10m</span><span class="p">;</span>
    <span class="kn">ssl_session_timeout</span>     <span class="mi">5m</span><span class="p">;</span>

    <span class="kn">location</span> <span class="s">/</span> <span class="p">{</span>
        <span class="kn">proxy_redirect</span> <span class="no">off</span><span class="p">;</span>
        <span class="kn">proxy_pass</span> <span class="s">https://www.google.com/</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">Host</span> <span class="s">www.google.com</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">User-Agent</span> <span class="nv">$http_user_agent</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">Referer</span> <span class="s">http://www.google.com</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">Accept-Encoding</span> <span class="s">&quot;&quot;</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">X-Real-IP</span> <span class="nv">$remote_addr</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
        <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-Proto</span> <span class="s">https</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

PS. 鉴于前不久发生的 SSLv3 - Poodle 攻击事件,上面的 SSL 配置已经禁用 SSLv2SSLv3 两种协议,以及使用 CBC 进行加密的相关算法。

这时候我们就可以通过 https://g4w.me 对 Google 进行访问啦。


✨高级玩法✨

❉ 使用 subs_filter 优化网页请求

借用 nginx 的 proxy_pass 模块,我们已经能搭建一个简单反向代理服务器。但在使用的过程中会发现,网页中仍然会有一些直接访问 Google 的请求。这是因为 proxy_pass 只会转发页面中相对路径的请求,如:/images/srpr/logo11w.png;而对于绝对路径的请求就无能为力了。

为了提高我们的访问速度,我们要把页面中的绝对路径中的 www.google.com 都替换成 g4w.me。要实现这样的效果,我们需要借用第三方模块 ngx_http_substitutions_filter_module

首先从 git 上下载最新的代码:

git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git 

然后重新编译 nginx:

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-ipv6 --add-module=/path/to/ngx_http_substitutions_filter_module
make
make install  

最后把 filter 语句写入 nginx 配置相应的位置中,如:

location / {
    proxy_redirect off;
    proxy_pass https://www.google.com/;
    proxy_set_header Host www.google.com;
    proxy_set_header User-Agent $http_user_agent;
    proxy_set_header Referer http://www.google.com;
    proxy_set_header Accept-Encoding "";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;

<span class="kn">subs_filter</span> <span class="s">www.google.com</span> <span class="s">g4w.me</span><span class="p">;</span>
<span class="kn">subs_filter_types</span> <span class="s">text/css</span> <span class="s">text/xml</span> <span class="s">text/javascript</span><span class="p">;</span>

}

简单说明一下用法:

1、 subs_filter $1 $2

把$1的内容替换成$2,支持正则匹配,如:

subs_filter www.google.com g4w.me;
subs_filter st(\d*).example.com $1.example.com ir;

2、 subs_filter_types mime-type [mime-types]

是指需要替换的文件类型,默认是 text/html

PS. 网上还有不少教程推荐使用 nginx 的官方模块 ngx_http_sub_module。然后他们实现的功能是一样的,但上面介绍的插件明显更强大。

按照上面的步骤进行配置后,此时访问 https://g4w.me 就不会再出现 www.google.com 的请求了。

但是,页面上除了 www.google.com 的请求以外,还有 Google 存放静态文件的 CDN 请求,ssl.gstatic.com。要处理这个域名的请求,只需要新建一个子域(如:gstatic.g4w.me)进行反代,然后在 nginx 配置中加入下面一段 filter 即可:

subs_filter ssl.gstatic.com gstatic。g4w.me;

由于目前使用的 SSL 证书不是 Wildcard SSL,其它子域无法使用该证书,所以这一部分我就没实现了,有条件的亲可以试试。

❉ 使用 proxy_cache 提高响应速度

当网站的访问人数达到一定后,我们就要启用缓存来提高网页请求的速度,nginx 自带的 proxy_cache 模块就能实现这个需求。

首先在 HTTP 层加入下面代码:

proxy_connect_timeout      5;
proxy_read_timeout         60;
proxy_send_timeout         5;
proxy_buffer_size          16k;
proxy_buffers              4 64k;
proxy_busy_buffers_size    128k;
proxy_temp_file_write_size 128k;
proxy_temp_path            /home/cache/temp;
proxy_cache_path           /home/cache/g4w levels=1:2 keys_zone=cache_g4w:3m inactive=7d max_size=5g; #7d是7天无访问删除,5g是缓存占具硬盘空间

然后在需要使用缓存的 Location 中插入下面的代码:

proxy_cache_key "$scheme://$host$request_uri"; #缓存key规则,用于自动清除缓存。
proxy_cache cache_g4w; #缓存区名称,必须与前面定义的相同
proxy_cache_valid  200 304 3h; #200 304状态缓存3小时
proxy_cache_valid 301 3d;  #301状态缓存3天
proxy_cache_valid any 1m;  #其他状态缓存(如502 404)1分钟
proxy_cache_use_stale invalid_header error timeout http_502;  #当后端出现错误、超时、502状态时启用过期缓存

重启 nginx 并访问网站,如果缓存目录的大小有变化,则设置成功。

« 返回