准备工作
1.一台没被P站屏蔽的主机
众所周知 Vultr 大部分IP段都被P站屏蔽
2.一个新的域名
其实随意啦,用自己域名的二级来弄也可,只是域名会变得比较长
后续均以example.com来指代我们使用的域名,请灵性代换
3.使用“不需要通过验证站点文件来签发/续签”并且最好还支持泛域名的 SSL 证书
这里我们自然首推 Let’s Encrypt,这是看起来唯一符合所有需求并且还免费的证书
域名及证书
需要使用哪些域?
在反代时我们需要用到以下几个域
如果你愿意使用一个全新域名专门反代:
1 2 3 |
example.com *.example.com *.pximg.example.com |
- example.com
随意,你可以放点自己的东西做一些伪装或者说明,或者直接 301 到www.example.com
- *.example.com
用于反代对齐*.pixiv.net
- *.pximg.example.com
用于反代对齐*.pximg.net
,其实该域名中的pximg
也可以替换成其他的字符串,只要不与P站的二级域名服务产生冲突即可
如果你想用一个自己正在使用的域名反代并且不想影响该域名的其他服务:
1 2 3 |
pixiv.example.com *.pixiv.example.com *.pximg.example.com |
各自作用同上,在后续配置上灵性修改即可
获取证书
使用 acme 的 DNS API 方式进行挑战验证来签发证书是最方便的
参考以下文章
在配置好 API 之后我们使用这样的命令即可签发一个我们想要的三域名合一的证书了,并且还能自动续签,岂不美哉
1 |
~/.acme.sh/acme.sh --issue --dns dns_cx -d example.com -d '*.example.com' -d '*.pximg.example.com' |
Nginx
不要使用 Tengine 等 Nginx 分支版本,在某些模块上可能会有一些奇怪的差异与问题
基础配置
这里仅列出关键配置,通常配置例如listen
、expires
、cache
以及 SSL 之类的不会写出,自行添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# *.example.com server { server_name ~^([^.]+)\.example\.com$; set $domain $1; resolver 8.8.8.8; location ~ .* { proxy_set_header Host $domain.pixiv.net; proxy_set_header Referer "https://www.pixiv.net"; proxy_cookie_domain pixiv.net example.com; proxy_pass https://$domain.pixiv.net; proxy_set_header Accept-Encoding ""; sub_filter "pixiv.net" "example.com"; sub_filter "pximg.net" "pximg.example.com"; sub_filter_once off; sub_filter_types *; } } # *.pximg.example.com server { server_name ~^([^.]+)\.pximg\.example\.com$; set $domain $1; resolver 8.8.8.8; location ~ .* { proxy_set_header Host $domain.pximg.net; proxy_set_header Referer "https://www.pixiv.net"; proxy_pass https://$domain.pximg.net; proxy_set_header Accept-Encoding ""; sub_filter "pixiv.net" "example.com"; sub_filter "pximg.net" "pximg.example.com"; sub_filter_once off; sub_filter_types *; } } |
详解
- server_name 与 set
使用正则表达式匹配以方便直接提取出我们要反代的二级域名 - resolver
必要,指定域名解析所用 DNS,因为在后续proxy_pass
中我们要反代的域名是由$domain
决定,本身是不定的,Nginx 必须被指定 DNS 才能处理域名解析 - proxy_cookie_domain
改变反代后返回的 header 中 set-cookie 里 cookie 对应的域名,只在*.example.com
中需要,是解决登陆问题的关键,如想了解后续文章会解释 - proxy_set_header Referer
设置 header 中的 Referer,只在*.pximg.example.com
中需要,目的是解决i.pximg.net
的防盗链问题 - proxy_set_header Accept-Encoding
将接受的压缩编码设为空,即不接受压缩,因为sub_filter
无法对压缩过的内容起效 - sub_filter
将反代后得到的内容进行字符串替换,以保证链接域名等与反代域名一致 - sub_filter_types
必须设置为*
,否则默认对于 API 返回的 json 内容等不会进行替换,会导致依靠 ajax 运作的一些功能的异常
增强隐蔽性(强烈建议)
防止被搜索引擎收录
在 Nginx 配置中向每个 server 添加此句
1 2 3 |
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot|^$") { return 403; } |
请加到set $domain $1;
这句之后,因为该配置也使用了正则表达式,会导致$1
改变
屏蔽P站的所有谷歌服务
包括谷歌广告、谷歌统计等,防止可能的暴露行为
在配置中两个 server 内的sub_filter
处追加一条
1 |
sub_filter "www.google" "(此处脸滚键盘即可)"; |
禁止大陆外IP访问
由于反代P站的受众只可能为大陆内用户,因此我们完全可以禁止大陆外IP访问反代站,同时还能防止P站检测投诉
但请注意,这个方案是对整台 VPS 的80
与443
端口生效,这意味着你如果同时在 VPS 上布置了其他站点,他们也将无法被大陆外用户访问(如果需要仅对反代站点生效,请自行百度参考“nginx geoip”)
参考步骤:
1.安装 ipset
1 2 3 4 |
# Debian / Ubuntu apt-get -y install ipset # CentOS yum -y install ipset |
2.创建一个 ipset 并添加大陆IP作为白名单
1 2 3 4 |
ipset -N cnip hash:net for i in $(curl https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt); do ipset -A cnip $i; done # 如果你想要添加单个IP x.x.x.x 进此白名单 ipset -A cnip x.x.x.x/32 |
3.写入防火墙规则(顺序十分重要,请不要改变执行顺序)
1 2 3 |
iptables -I INPUT -p tcp --dport 443 -j DROP iptables -I INPUT -p tcp --dport 80 -j DROP iptables -I INPUT -p tcp -m set --match-set cnip src -j ACCEPT |
局限性
- 不能使用绑定的社交账号的登录方式
- 广告显示不出(这算哪门子局限性x),因为广告是另一个域名所以懒得再开一个证书了
可能存在尚未发现的问题,不过常用的功能都是没有问题的