MENU

【歪门邪道】从零开始的GelBooru反向代理

February 2, 2020 • 瞎折腾

原来的手机因为电池鼓起来把后盖顶开了,没法用了。遂启用了备用机的备用机(备用机因为2019-nCov的影响,发货时间尚不可知),是HTC M8,运行安卓6.0系统,实测没法安装科学上网的app,由此很不方便,而且好像也没法手动设定DNS服务器等设置,不然就可以做SNI反代了。遂在无奈之下,考虑按照网站架设反向代理。

本文以https://gelbooru.com为例,因为该网站本身涵盖了诸如登陆(涉及cookies处理)、URL替换等事宜,算是比较涉及方面比较多的了。

2020年3月2日更新

文中提到的反代地址已经停用了。但方法还是适用的。

准备

必备项目:

  • 一台可以访问Gelbooru并且在国内可以访问到的服务器
  • 服务器上安装了Nginx
  • 了解一定的Nginx使用方法(诸如多域名解析)
  • 一个域名,做好的必要的DNS解析
  • 域名对应的SSL证书
  • 必要的服务器管理工具

    • 诸如WinSCP、PuTTY之类的

此处我使用的域名是gelbooru.skyblond.info,可以单击此处访问。

配置Nginx

反向代理主站

修改对应域名的配置文件。

对于80端口,设定301重定向到443,同时关闭访问日志:

server
    {
        listen 80;
        server_name gelbooru.skyblond.info;
        rewrite ^(.*)$ https://gelbooru.skyblond.info$1 permanent;
        access_log off;
    }

对于443端口,开启SSL并配置转发:

server
    {
        listen 443 ssl http2;
        server_name gelbooru.skyblond.info;

        ssl_certificate 【证书CRT文件的路径】;
        ssl_certificate_key 【证书KEY文件的路径】;

        ssl_session_timeout 5m;
        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
        ssl_prefer_server_ciphers on;

        charset  utf-8;

        location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Referer https://gelbooru.com;
            proxy_set_header Host gelbooru.com;
            proxy_pass https://gelbooru.com;
        }

        access_log off;
    }

此时保存文件后重载Nginx,访问服务器发现主页已经能够打开了。但是当你进行搜索时还是跳回了Gelbooru的站点,从而离开了反代服务器。

这时候需要反代服务器将传输给客户端的内容作出修改。将原本指向gelbooru.com的url修改为指向gelbooru.skyblond.info(即你的反代地址)从而保证页面内的超链接不会使客户端离开反代服务器。

内容替换

要做出内容替换,需要对443端口的location /代码块做出如下修改:

location / {
    #原有内容
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Referer https://gelbooru.com;
    proxy_set_header Host gelbooru.com;
    proxy_pass https://gelbooru.com;
    
    #服务器默认返回Gzip压缩的页面,需要设置让Gelbooru服务器返回没有压缩过的原文,Nginx才能直接替换
    proxy_set_header Accept-Encoding "";
    #关闭一次替换,默认是开启的
    sub_filter_once off;
    #替换
    sub_filter gelbooru.com gelbooru.skyblond.info;
}

保存后重载,再次访问反代服务器。这次就正常多了。但是搜索后点进一张图片,发现大图加载不出来。使用Chrome调试发现图片请求了如下URL:https://img2.gelbooru.skyblond.info/simples/...,Gelbooru请求的URL是:https://img2.gelbooru.com/simples/...。因此需要对img2.gelbooru.com这个域名同样进行反代。

方法有二,其一是占用另一个域名,诸如img2gelbooru.skyblond.info,需要注意的是SSL证书对于二级域名的支持问题。我的证书签发的是*.skyblond.info,但是用在img2.gelbooru.skyblond.info上时Chrome就提示有问题。而且这种方法需要额外占用一个域名,并不那么简洁,故弃用。

处理图片反代

如上说的法二,便是将img2.gelbooru.com的请求替换到gelbooru.skyblond.info/img2下面,截止目前https://gelbooru.com/img2路径返回的是404,并且正文中并没有返回该路径相关的URL,可以认为这个路径是原站没有使用的,反向代理可以安全的占用之。

对443端口的location /代码块上面追加如下代码块:

location /img2/ {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Referer http://img2.gelbooru.com;
    proxy_set_header Host img2.gelbooru.com;
    proxy_pass http://img2.gelbooru.com/;
    proxy_set_header Accept-Encoding "";
}

值得注意的是这里使用了http来访问img2.gelbooru.com,截止目前实测使用https时Nginx返回502错误,查看日志发现Nginx直接请求了该域名对应的IP地址,此时Gelbooru服务器返回了一个不被支持的SSL协议,而浏览器直接访问域名则没有问题。

我暂时不知道问题的原因,还烦请诸位在评论区指导一下。但是使用http协议,Gelbooru服务器会内部重定向到https并且功能正常。我猜测可能是与Nginx的内部实现有关。

同时还需要对原本的location /进行如下修改:

location / {
    #原有内容
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Referer https://gelbooru.com;
    proxy_set_header Host gelbooru.com;
    proxy_pass https://gelbooru.com;
    proxy_set_header Accept-Encoding "";
    sub_filter_once off;

    #替换是有顺序的,需要先替换掉img2.gelbooru.com,再处理余下的gelbooru.com
    sub_filter img2.gelbooru.com gelbooru.skyblond.info/img2;

    #原有内容
    sub_filter gelbooru.com gelbooru.skyblond.info;
}

此时重载Nginx,刷新页面,应该可以看到图片正常加载了。

但是关闭代理,网页开打的速度还是很慢,通过Chrome控制台可以发现页面中引用了来自www.google.com(reCaptcha)、maxcdn.bootstrapcdn.com(bootStrap)、ajax.googleapis.com的内容,导致页面加载过程缓慢。同样可以利用sub_filter功能将他们替换为国内的CDN:

location / {
    #原有内容
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Referer https://gelbooru.com;
    proxy_set_header Host gelbooru.com;
    proxy_pass https://gelbooru.com;
    proxy_set_header Accept-Encoding "";
    sub_filter_once off;
    sub_filter img2.gelbooru.com gelbooru.skyblond.info/img2;
    sub_filter gelbooru.com gelbooru.skyblond.info;
    
    #新内容
    sub_filter www.google.com/recaptcha recaptcha.net/recaptcha;
    sub_filter maxcdn.bootstrapcdn.com/ cdn.bootcss.com/twitter-;
    sub_filter ajax.googleapis.com/ajax/libs cdn.bootcss.com;
}

重载Nginx后刷新,除了recaptcha.net不稳定外,其余内容皆能迅速加载出来。但是当需要登陆账户对于图片进行编辑时,发现登陆后页面没有反应,登不上去。

这里还要额外说明的一点是Nginx默认只对html类型的数据进行替换,如果你要做js的反代,需要对js文件进行修改,推荐一行一劳永逸的代码:sub_filter_types *;

处理Cookies代理

对于登陆使用的Cookies,Gelbooru服务器传来的Cookies的作用域(Domain)是gelbooru.com,自然反代服务器gelbooru.skyblond.info是读取不到gelbooru.com的Cookies的。因此需要对Cookies的作用域同样做出替换。另外为了最大限度的保证兼容性,当Gelbooru服务器发出重定向时,也应当重写到反代服务器的地址上。故对443端口的location /代码块做出如下修改:

location / {
    #原有内容
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Referer https://gelbooru.com;
    proxy_set_header Host gelbooru.com;
    proxy_pass https://gelbooru.com;
    proxy_set_header Accept-Encoding "";
    sub_filter_once off;
    sub_filter img2.gelbooru.com gelbooru.skyblond.info/img2;
    sub_filter gelbooru.com gelbooru.skyblond.info;
    sub_filter www.google.com/recaptcha recaptcha.net/recaptcha;
    sub_filter maxcdn.bootstrapcdn.com/ cdn.bootcss.com/twitter-;
    sub_filter ajax.googleapis.com/ajax/libs cdn.bootcss.com;
    
    #新内容
    proxy_cookie_domain gelbooru.com gelbooru.skyblond.info;
    proxy_redirect gelbooru.com gelbooru.skyblond.info;
}

保存后重载,反代服务器应当能够正常工作了。

总结

整个配置文件如下所示:

server
    {
        listen 80;
        server_name gelbooru.skyblond.info;
        rewrite ^(.*)$ https://gelbooru.skyblond.info$1 permanent;
        access_log off;
    }

server
    {
        listen 443 ssl http2;
        server_name gelbooru.skyblond.info;

        ssl_certificate ...;
        ssl_certificate_key ...;

        ssl_session_timeout 5m;
        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
        ssl_prefer_server_ciphers on;

        charset  utf-8;

        location /img2/ {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Referer http://img2.gelbooru.com;
            proxy_set_header Host img2.gelbooru.com;
            proxy_pass http://img2.gelbooru.com/;
            proxy_set_header Accept-Encoding "";
        }

        location / {
            sub_filter www.google.com/recaptcha recaptcha.net/recaptcha;
            sub_filter maxcdn.bootstrapcdn.com/ cdn.bootcss.com/twitter-;
            sub_filter ajax.googleapis.com/ajax/libs cdn.bootcss.com;
            sub_filter img2.gelbooru.com gelbooru.skyblond.info/img2;
            sub_filter gelbooru.com gelbooru.skyblond.info;
            sub_filter_once off;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Referer https://gelbooru.com;
            proxy_set_header Host gelbooru.com;
            proxy_pass https://gelbooru.com;
            proxy_set_header Accept-Encoding "";
            proxy_cookie_domain gelbooru.com gelbooru.skyblond.info;
            proxy_redirect gelbooru.com gelbooru.skyblond.info;
        }

        access_log off;
    }

目前为止文中提早的反代服务器在这里https://gelbooru.skyblond.info

2020年3月2日更新

文中提到的反代地址已经停用了。但方法还是适用的。

-全文完-


知识共享许可协议
【歪门邪道】从零开始的GelBooru反向代理天空 Blond 采用 知识共享 署名 - 非商业性使用 - 相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 https://skyblond.info/about.html 处获得。

Last Modified: March 2, 2020
Archives QR Code
QR Code for this page
Tipping QR Code