Nginx 如何与 Socat 配合使用
米柚子
2020年12月20日 09:28

前言

socat 是一个多功能的网络工具,其主要特点就是在两个数据流之间建立通道,它可以帮助 Nginx 访问需要中转的服务。

本文着重介绍的就是如何让 Nginx 通过 socat 访问 proxy_pass 的目标。

由于专栏代码块已损坏不可使用(会吞换行),因此下文涉及代码均会用截图,相关代码会在评论区放出 Gist 链接,请不用担心复制问题。

本文所使用环境:

  • HK GCP 服务器

  • Ubuntu 20.04.1 LTS (64bit)

  • 所用中转为 socks5 协议,监听本地端口 1080(台湾出口)

  • proxy_pass 目标为 cip.cc,这是一个 IP 查询网站,可以帮助我们判断 Nginx 是否通过中转访问了反代目标。


思路解析

由于 Nginx 的 proxy_pass 并不支持中转,因此转变一下想法把目标网站映射到本地(端口),再让 Nginx 去访问本地映射的端口。

socat 就是负责目标网站/服务映射到本地的工具,我们要用的是它能够通过中转服务器将目标网站/服务映射到本地。

PS:本文使用的 socat 是打过 socks5 支持补丁的版本,如果你需要用到的协议是 socks5,那么请按照本文编译安装而不要使用 yum / apt 安装


开始行动

socat 安装与配置

编译安装 socat (支持 socks5 的版本):

安装 socat

安装成功后应后如下效果:

后面还有巴拉巴拉很长

开启两个终端,一个运行 socat 一个运行 curl 做测试。

首先,先检查中转服务器是不是好的:

如果中转本来就是坏的,那后面就没得玩了

运行 socat

参数格式:

  • socat TCP4-LISTEN:<本地端口>,reuseaddr,fork PROXY:<中转服务器IP>:<远程地址>:<远程端口>,proxyport=<中转服务器端口>

  • 远程地址请依据实际需求替换域名及端口(http 为 80,https 为 443)

  • 加上 -d -d 参数,可以看见详细信息,适用于调试:

参数介绍:

  • TCP4-LISTEN:在本地 IPv4 上建立一个监听端口,也可也说是转发端口。这里监听 1081 端口。

  • reuseaddr:绑定一个本地端口。

  • fork:指定转发的目的地,我们这里先写中转服务器的IP,英文 : 分割然后写目标网站地址。这里就是通过中转访问 cip.cc (一个查询 IP 工具站)

  • PROXY:中转协议。

  • socks5port:使用 socks5 的中转服务端口。(这里是中转服务是监听本地 1080 端口)

使用 curl 进行测试

访问上面监听的 1081 端口(记得 header 补充 Host,Host 要和上面写的目标网站域名一致)

不要漏了 -H "Host: 域名&#​34;

如果要测试 https 站点,那么 curl 需要加上 -k 参数忽略证书错误

对于 https 站点,加上 -k 后就不会出现认证错误

测试没问题后,接着为 socat 做开机启动及进程守护:

这里推荐使用 systemd 。

注意:

上面的 cip.cc 是作为测试,实际请根据自己需要更换,下面将以我的需要进行举例。

也可以再建一个连接 www.cip.cc  的 socat 服务方便通过 Web 来检查中转是否正常(监听端口不得相同)。

cd /etc/systemd/system 进入目录

sudo vim socat-tw.service 这里文件名随意,你好记就行,文件名就是服务名,但是后缀得是 .service

参数解释:

  • Description:说明这个服务是干嘛的,可以自定义。

  • After:在某项服务后再运行,这里是等网络准备好后再运行。

  • Restart=on-failure:如果进程意外退出则重启,正常停止(比如 systemctl stop)不重启。

  • RestartSec:重启服务需要等待的时间

  • ExecStart:需要执行的命令

sudo systemctl daemon-reload  重新加载服务

sudo systemctl start socat-tw 启动服务(这里的 socat-tw 就是上面的文件名)

上面的 start 还可以是 restartstop,分别是重启和停止服务,按需使用。

sudo systemctl status socat-tw 查看服务状态

重载服务到启动服务

sudo systemctl enable socat-tw  设置开机启动

需要关闭开机启动将上面的 enable 换成 disable 即可。

可选项:

上面提到可以新建一个连接 cip.cc  的 socat 服务用于测试(中转是否正常),如有需要,将上面的文件复制一份然后修改,同理按照上面的方法重新加载服务、启动服务即可。

如果有多个地区中转(不同地区中转监听不同端口),那么方法也类似,修改 TCP4-LISTEN 和 socks5port 端口即可。

一个连接 cip.cc  的 socat 服务


对于下面的操作,一个或者数个域名是必要的。

域名申请不是本文重点,就稍微提一提,对域名要求不大的可以试试 dynv6.com (免费,三级域名,不限制 CNAME ),个人认为注册和操作都比较简单,也支持 ipv6 及 ipv4 的 DDNS,目前家里的树莓派就使用这家的 ipv6 DDNS。

dynv6 首页

域名申请流程:

它的 ddns 也十分简单,使用 wget 或者 curl 对一个 api 发起请求即可刷新地址,定时刷新可以使用 crontab (Linux)或者 任务计划(Windows)实现。

下面是一个 ipv6 的 api,用于 ipv6 DDNS:

下面的步骤就以有一个域名作为前提了,下面的配置就以 example.com 作为例子,请根据自身实际替换!


Nginx 安装与配置

sudo apt install -y nginx    安装 Nginx

cd /etc/nginx    进入 Nginx 配置目录

sudo mkdir vhosts    建立虚拟主机配置目录

sudo vim nginx.conf    编辑 Nginx 主配置

在 http{ } 中添加 include /etc/nginx/vhosts/*.conf; (结尾有个英文分号 ; 不要丢)

cd vhosts    # 进入配置目录

sudo vim example.com.conf    建议使用域名作为配置文件名

关键配置如下:

proxy_set_header Host    要接前面 socat 配置的远程服务域名

proxy_pass    接 socat 监听的本地地址

其他反代配置根据自己实际需求添加。

这里以 www.cip.cc 作为测试说明

sudo systemctl start nginx    启动 Nginx

sudo systemctl enable nginx    设置 Nginx 开机启动

sudo nginx -s reload    重新加载 Nginx 配置

接着我们访问这个地址看看 Nginx 是不是能够通过中转访问 www.cip.cc 了

可以看到香港的机子经过台湾中转成功访问了反代目标(www.cip.cc)

同样的,反代目标 www.cip.cc 是方便测试,测试成功后就可以换成我们需要的服务了。

下面是我所用的 vhost 配置(第一步),用于特定服务,仅供参考:


使用 certbot 启用 HTTPS(可选)

前往 https://certbot.eff.org/instructions 填入 Nginx 及系统版本会自动显示相应文档,根据文档操作即可。

输入域名对应的需要即可自动为站点添加 SSL。


检查验收

启动需要用到上面 Nginx 的应用,查看是否能正常工作。

以本文所用例子来看,都可以正常播放,配置成功


本文参考

  • 《nginx proxy_pass over https_proxy》https://stackoverflow.com/questions/46803431/nginx-proxy-pass-over-https-proxy

  • 《socat 支持 socks5》https://runsisi.com/2019-09-23/socat-with-socks5