Skip to content

Instantly share code, notes, and snippets.

@miyouzi
Last active May 3, 2024 14:05
Show Gist options
  • Star 35 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save miyouzi/3e3d57cde402b829aeb1d865b14eaa1a to your computer and use it in GitHub Desktop.
Save miyouzi/3e3d57cde402b829aeb1d865b14eaa1a to your computer and use it in GitHub Desktop.
配置 Nginx 通过代理访问反代目标(B站代理解析)

简介

众所周知,有些服务存在着地区限制,我们可以通过在服务所属地区搭建代理服务来解决,其中在其服务范围内部署 Nginx 反代服务是个有效且流行的办法。

但如果区域很多,每个区域都布置一台服务器那成本会有些高昂且利用率很低,通常我们只是需要该地区的 IP 而已,如果手头上正好有这些地区的代理池的话,那我们就可以只用一台服务器部署Nginx反向代理结合服务所在地区的代理实现相同的效果。

本文着重介绍的就是如何让 Nginx 通过代理访问上游服务。(即 proxy_pass 的目标)

详细图文说明可以参见《Nginx 如何与 Socat 配合使用》

PS:本配置兼容 《哔哩漫游》《解除b站区域限制》

注意

代理请自备,本文是使用 SSR Python 版的客户端(local.py),监听本地 1080 端口,协议 socks5。

请先检查自己的代理服务是否正常。

curl --socks5-hostname 127.0.0.1:1080 cip.cc

期望返回参考

IP      : 【代理出口IP】
地址    : 中国  台湾  台北市
运营商  : cht.com.tw

数据二  : 台湾省台北市 | 中华电信

数据三  : 中国台湾 | 中华电信

URL     : http://www.cip.cc/【代理出口IP】

参考

安装支持 socks5 的 socat

sudo apt install -y autoconf git yodl curl make 
# 拉取源码
git clone https://github.com/runsisi/socat.git
# 进入目录
cd socat
# 处理配置
autoconf
./configure --prefix=/usr
# 编译
make
# 安装
sudo make install
# 检查是否成安装
socat -h 

测试(开启两个终端):

socat TCP4-LISTEN:1081,reuseaddr,fork SOCKS5:127.0.0.1:cip.cc:80,socks5port=1080    # 测试完成后 Ctrl+C 终止运行
# 在另一个终端用 curl 测试
curl -v -H "Host: cip.cc" 127.0.0.1:1081

安装 socat systemd 服务

cd /etc/systemd/system    # 进入目录
sudo vim socat-tw.service    # 这里文件名随意,你好记就行,文件名就是服务名,但是后缀得是 .service

建议 ExecStart 使用绝对路径,通过 which socat 可以查询 socat 的路径。

输入以下内容(用于反代B站接口):

[Unit]
Description=socat-tw
After=network.target

[Service]
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/socat TCP4-LISTEN:1081,reuseaddr,fork SOCKS5:127.0.0.1:api.bilibili.com:443,socks5port=1080

[Install]
WantedBy=multi-user.target

(可选)再新建一个用于测试代理

sudo vim socat-cip.service 

输入以下内容(用于测试代理是否正常):

[Unit]
Description=socat-cip
After=network.target

[Service]
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/socat TCP4-LISTEN:1082,reuseaddr,fork SOCKS5:127.0.0.1:cip.cc:80,socks5port=1080

[Install]
WantedBy=multi-user.target

重载与启动服务

sudo systemctl daemon-reload	# 重新加载服务
sudo systemctl start socat-tw	# 启动服务(这里的 socat-tw 就是上面的文件名)
sudo systemctl enable socat-tw 	# 设置开机启动
sudo systemctl status socat-tw	# 检查状态
# 如果上面没有建 socat-cip 下面就不用了
sudo systemctl start socat-cip
sudo systemctl enable socat-cip
sudo systemctl status socat-tw

Nginx 安装与配置

sudo apt install -y nginx    # 安装 Nginx
cd /etc/nginx    # 进入 Nginx 配置目录
sudo mkdir vhosts    # 建立虚拟主机配置目录
sudo vim nginx.conf    # 编辑 Nginx 主配置

nginx.confhttp{ } 中添加

include /etc/nginx/vhosts/*.conf;
cd vhosts    # 进入配置目录
sudo vim example.com.conf   # 建议使用域名作为配置文件名

写入如下配置

server {
    server_name example.com  # 填写自己的域名

    listen 80;
    listen [::]:80;  # 监听IPv6,根据需要取舍

    client_max_body_size 128M;

    location /pgc/player/api/playurl {  # 用于 APP 解析
        proxy_set_header Host api.bilibili.com;
        proxy_pass https://127.0.0.1:1081;  # 通过代理连接到 api.bilibili.com
        # 模块请求都会带上X-From-Biliroaming的请求头,为了防止被盗用,可以加上请求头判断
        # 这里还需要给油猴脚本使用,因此不启用了
        # if ($http_x_from_biliroaming ~ "^$") {
        #	return 403;
        # }
    }

    location /pgc/player/web/playurl {  # 为油猴脚本做准备
        proxy_set_header Host api.bilibili.com;
        proxy_pass https://127.0.0.1:1081;
    }

    location /cip/ {  # 用于测试代理是否正常
        proxy_set_header Host www.cip.cc;
        proxy_pass http://127.0.0.1:1082/;
    }
}

重载 Nginx

sudo systemctl start nginx    启动 Nginx
sudo systemctl enable nginx    设置 Nginx 开机启动
sudo nginx -s reload    重新加载 Nginx 配置

添加 SSL

安装请前往 https://certbot.eff.org/instructions 查看相应文档

# 为 Nginx 站点添加 SSL,会给出域名列表,选择相应域名的序号即可
sudo certbot --nginx	

完成后,记得前往 https://example.com/ 检查 SSL 是否启用成功。

@CmmmmmmLau
Copy link

启动服务的时候提示Exec format error.

● socat-cn.service - socat-cn
   Loaded: error (Reason: Exec format error)
   Active: inactive (dead)

Dec 20 19:26:49 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:1: Assignme
Dec 20 19:26:49 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:2: Assignme
Dec 20 19:26:49 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:3: Assignme
Dec 20 19:26:49 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:8: Executab
Dec 20 19:27:37 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:1: Assignme
Dec 20 19:27:37 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:2: Assignme
Dec 20 19:27:37 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:3: Assignme
Dec 20 19:27:37 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:8: Executab
Dec 20 19:29:18 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:8: Executab
Dec 20 19:33:41 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:8: Executab
Dec 20 19:33:58 VM-8-14-ubuntu systemd[1]: /etc/systemd/system/socat-cn.service:8: Executab

配置文件也没写错

[Unit]
Description=socat-cn
After=network.target

[Service]
Restart=on-failure
RestartSec=5s
ExecStart=socat TCP4-LISTEN:1081,reuseaddr,fork SOCKS5:127.0.0.1:api.bilibili.com:443,socks5port=1080

[Install]
WantedBy=multi-user.target

请问是哪里出问题了?

@miyouzi
Copy link
Author

miyouzi commented Dec 20, 2020

@qq512065439 前面手动运行测试都正常吗?

另外说明一下系统版本

@CmmmmmmLau
Copy link

CmmmmmmLau commented Dec 20, 2020

测试的时候没问题的

* Rebuilt URL to: 127.0.0.1:1081/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 1081 (#0)
> GET / HTTP/1.1
> Host: cip.cc
> User-Agent: curl/7.58.0
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
curl: (52) Empty reply from server

不过终端返回 E connect(5, AF=2 127.0.0.1:1080, 16): Connection refused
所以我也不是很懂是不是测试成功了(

@miyouzi
Copy link
Author

miyouzi commented Dec 20, 2020

测试的时候没问题的

* Rebuilt URL to: 127.0.0.1:1081/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 1081 (#0)
> GET / HTTP/1.1
> Host: cip.cc
> User-Agent: curl/7.58.0
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
curl: (52) Empty reply from server

curl: (52) Empty reply from server 这个返回不应该呀,这个返回应该是显示你代理的 IP 和位置,检查一下你的代理服务

@CmmmmmmLau
Copy link

测试的时候没问题的

* Rebuilt URL to: 127.0.0.1:1081/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 1081 (#0)
> GET / HTTP/1.1
> Host: cip.cc
> User-Agent: curl/7.58.0
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
curl: (52) Empty reply from server

curl: (52) Empty reply from server 这个返回不应该呀,这个返回应该是显示你代理的 IP 和位置,检查一下你的代理服务

代理问题解决了,不过启动服务的时候依旧提示Exec format error.
错误信息跟之前一样
系统版本是Ubuntu 18.04.4 x86_64

@miyouzi
Copy link
Author

miyouzi commented Dec 21, 2020

测试的时候没问题的

```
  • Rebuilt URL to: 127.0.0.1:1081/
  • Trying 127.0.0.1...
  • TCP_NODELAY set
  • Connected to 127.0.0.1 (127.0.0.1) port 1081 (#0)

GET / HTTP/1.1
Host: cip.cc
User-Agent: curl/7.58.0
Accept: /

  • Empty reply from server
  • Connection #0 to host 127.0.0.1 left intact
    curl: (52) Empty reply from server

curl: (52) Empty reply from server 这个返回不应该呀,这个返回应该是显示你代理的 IP 和位置,检查一下你的代理服务

代理问题解决了,不过启动服务的时候依旧提示Exec format error.
错误信息跟之前一样
系统版本是Ubuntu 18.04.4 x86_64

sudo netstat -lntp 看看端口占用情况

这个帖子你参考看看 https://ubuntuforums.org/showthread.php?t=2429498

@SakuraAkino
Copy link

和@512065439 的情况一样,系统版本都一样,不过我懒得查问题了,直接nohup......

@miyouzi
Copy link
Author

miyouzi commented Dec 30, 2020

和@512065439 的情况一样,系统版本都一样,不过我懒得查问题了,直接nohup......

如果把 ExecStart 后面的 socat 换成绝对路径呢?( which socat 可以查路径)

@SakuraAkino
Copy link

和@512065439 的情况一样,系统版本都一样,不过我懒得查问题了,直接nohup......

如果把 ExecStart 后面的 socat 换成绝对路径呢?( which socat 可以查路径)

可行

@miyouzi
Copy link
Author

miyouzi commented Dec 30, 2020

和@512065439 的情况一样,系统版本都一样,不过我懒得查问题了,直接nohup......

如果把 ExecStart 后面的 socat 换成绝对路径呢?( which socat 可以查路径)

可行

好的,文档更新了使用绝对路径。

@BitBotM
Copy link

BitBotM commented Jan 9, 2021

cip 测试成功,返回了出口地址,但使用脚本时仍然显示“代理服务器临时不可用”。

我是在其他端口搭的服务,在脚本设置中填写 https://xxx.xxx.xxx:8088 ,这是否会影响工作?

另一方面,我使用 clash 做代理,socat 服务里是这么写的:

socat TCP4-LISTEN:1081,reuseaddr,fork PROXY:127.0.0.1:api.bilibili.com:443,proxyport=7890

除了这两点,我和文中的配置方法并没有大的区别,不知道是怎么回事。nginx access.log 里确实是返回了 498 bytes 数据,但我不会调试Tampermonkey,不知道具体获得了什么信息

@miyouzi
Copy link
Author

miyouzi commented Jan 9, 2021

cip 测试成功,返回了出口地址,但使用脚本时仍然显示“代理服务器临时不可用”。

我是在其他端口搭的服务,在脚本设置中填写 https://xxx.xxx.xxx:8088 ,这是否会影响工作?

另一方面,我使用 clash 做代理,socat 服务里是这么写的:

socat TCP4-LISTEN:1081,reuseaddr,fork PROXY:127.0.0.1:api.bilibili.com:443,proxyport=7890

除了这两点,我和文中的配置方法并没有大的区别,不知道是怎么回事。nginx access.log 里确实是返回了 498 bytes 数据,但我不会调试Tampermonkey,不知道具体获得了什么信息

也就说你的代理协议不是 socks5 是么,你说的 cip 成功了,会不会是 SSL 证书的问题?

@BitBotM
Copy link

BitBotM commented Jan 9, 2021

cip 测试成功,返回了出口地址,但使用脚本时仍然显示“代理服务器临时不可用”。
我是在其他端口搭的服务,在脚本设置中填写 https://xxx.xxx.xxx:8088 ,这是否会影响工作?
另一方面,我使用 clash 做代理,socat 服务里是这么写的:

socat TCP4-LISTEN:1081,reuseaddr,fork PROXY:127.0.0.1:api.bilibili.com:443,proxyport=7890

除了这两点,我和文中的配置方法并没有大的区别,不知道是怎么回事。nginx access.log 里确实是返回了 498 bytes 数据,但我不会调试Tampermonkey,不知道具体获得了什么信息

也就说你的代理协议不是 socks5 是么,你说的 cip 成功了,会不会是 SSL 证书的问题?

可能是 ssl 的问题,但情况复杂,搞不清问题所在,我放弃了。还是老老实实搭在 443 端口。

@zhj9709
Copy link

zhj9709 commented Jul 26, 2021

请教一个问题,我以前一直用nginx+socat+xray,然后用油猴脚本都是正常的,xray日志也能看到如下内容
image
但不知道从什么时候开始,播放番剧时,已经失效了,然后xray没有这样的日志。
使用curl测试时才有上面那样的日志,一直找不到什么原因

curl测试结果如下
image
image

@miyouzi
Copy link
Author

miyouzi commented Jul 26, 2021

@zhj9709 curl 来测试 https 需要加上 -k 参数忽略证书错误,在测试 api.bilibili.com 时,应该如下返回:
image

你提到的 播放番剧时,已经失效了 ,先在番剧播放页看下控制台,看你的服务器的 Nginx 返回什么

@zhj9709
Copy link

zhj9709 commented Jul 26, 2021

@zhj9709 curl 来测试 https 需要加上 -k 参数忽略证书错误,在测试 api.bilibili.com 时,应该如下返回:
image

你提到的 播放番剧时,已经失效了 ,先在番剧播放页看下控制台,看你的服务器的 Nginx 返回什么

加-k后输出的信息一样的
console里这样的
image

@miyouzi
Copy link
Author

miyouzi commented Jul 26, 2021

CONNECTION_CLOSED 应该问题不在 socat 上,你上个梯子看能不能访问你的域名(可能被墙了?),

在 Network 那边,右键你的域名从新标签打开

@zhj9709
Copy link

zhj9709 commented Jul 26, 2021

CONNECTION_CLOSED 应该问题不在 socat 上,你上个梯子看能不能访问你的域名(可能被墙了?),

在 Network 那边,右键你的域名从新标签打开

我用不用梯子都可以访问

@miyouzi
Copy link
Author

miyouzi commented Jul 26, 2021

CONNECTION_CLOSED 应该问题不在 socat 上,你上个梯子看能不能访问你的域名(可能被墙了?),
在 Network 那边,右键你的域名从新标签打开

我用不用梯子都可以访问

就是直接访问能出来数据,但是脚本请求异常是么?

@zhj9709
Copy link

zhj9709 commented Jul 26, 2021

CONNECTION_CLOSED 应该问题不在 socat 上,你上个梯子看能不能访问你的域名(可能被墙了?),
在 Network 那边,右键你的域名从新标签打开

我用不用梯子都可以访问

就是直接访问能出来数据,但是脚本请求异常是么?

用脚本就是受限状态,正常应该是我xray上能看到访问api.bilibili.com的日志记录的
image

@zhj9709
Copy link

zhj9709 commented Jul 26, 2021

image
image
image

@miyouzi
Copy link
Author

miyouzi commented Jul 26, 2021

@zhj9709 我这边测你域名的 tcp 端口都不通,检查一下防火墙设置,nginx 是否在正常运行,nginx监听端口设置是否正确,端口是否被其他占用,域名解析是否正确

image

@miyouzi
Copy link
Author

miyouzi commented Jul 26, 2021

@zhj9709 已清除域名相关的回复内容,由于 Github 的楼层能看历史记录,我楼层直接删了

@zhj9709
Copy link

zhj9709 commented Jul 26, 2021

@zhj9709 已清除域名相关的回复内容,由于 Github 的楼层能看历史记录,我楼层直接删了

感谢

@yubanmeiqin9048
Copy link

已经失效了吗?搭建好 之后提示这个:Access to XMLHttpRequest at ' 反代地址 'from origin 'https://www.bilibili.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

@SakuraAkino
Copy link

SakuraAkino commented Jan 2, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment