Skip to content

Instantly share code, notes, and snippets.

@miyouzi
Last active May 3, 2024 14:05
Show Gist options
  • 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

Copy link

ghost commented Dec 30, 2020

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

@miyouzi
Copy link
Author

miyouzi commented Dec 30, 2020

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

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

Copy link

ghost commented Dec 30, 2020

和@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.

Copy link

ghost commented Jan 2, 2022 via email

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