技术博客

越是喧闹,越是孤独。越是寂寞,越是丰富
The more noisy, the more lonely. The more lonely, the more rich

越是喧闹,越是孤独。越是寂寞,越是丰富
The more noisy, the more lonely. The more lonely, the more rich

技术博客


自主制作一个代理工具来访问ChatGPT

2023-04-23 Mendel
工具ChatGPT

 代理工具,不多说,懂的都懂。



4月以来,随着ChatGPT不断封锁账号、IP、节点等,导致不少人无法正常访问ChatGPT。如果你是因为账号本身的问题被禁用,那么可能需要向OpenAI提交申诉。如果因为是IP或节点的问题(这个很常见,页面提示 Access denied及错误码1020),那么可以尝试更换节点或其他的魔法工具。


我一直用LD,感觉还不错,购买了专业版后,基本上网络比较稳定,我注册ChatGPT账号时就是用的它,一直使用ChatGPT到4月初都没有问题。但是最近某一天突然就出现了Access denied的提示了,于是我猜测我可能被封了。我先尝试了更换了一个其他V-P-N工具叫ExpressV-P-N,虽然几乎连接不到任何一个节点,但趁着偶尔连接成功了一次赶紧试了下,发现我是可以成功登录ChatGPT的,所以就放心了一半,我的账号没有问题,应该是节点的问题。由于我的LD基本上一直连的是某个固定的节点(如日本/韩国),我推荐的几个使用LD的朋友,他们连上后也都是同一个IP节点,并且它只能自动连接到某些固定的节点,无法手动更换。所以会导致大量的LD用户在这个节点IP注册ChatGPT账号,进而被OpenAI纳入黑名单。


针对这个问题,网上有很多解决方案,有的说是清除cookie,清除缓存,浏览器无痕模式,这些我试了都没用。还有就是更换其他魔法工具,而它们也基本上都是收费的,而那些工具也很可能都是几个固定的IP,依然有被封锁的可能。于是我想了一下,能不能自己做一个代理来解决这个问题。




01

购买云主机



起初我想的是,购买一个海外云主机,它应该能访问ChatGPT,然后用它做个代理,实现本机的上网。于是试着购买了一两个最短期最低配的阿里云美国节点和欧洲节点,通过 wget chat.openai.com 验证一下请求是否正常,结果得到的都是403状态码,以为这个表示的是被封禁了,于是就放弃了。(后来发现实际上,在任何节点上wget访问ChatGPT都可能是403,只是因为首次访问还没有session状态。所以阿里云海外主机到底能不能正常访问目前无法确定。但就算是能访问,选择阿里云做代理还是觉得不放心)


心想,因为ChatGPT并不对中国开放,所以阿里云无法访问也理所当然。同时谷歌云、亚马逊云可能跟OpenAI是竞争关系,也有被封锁的可能。最后偶然从知乎上看到有人说,因为微软跟OpenAI是合作关系,那通过微软云Azure访问ChatGPT应该是没问题的,于是就准备尝试下。


访问Azure网站,用微软账号登录,同时获得了100美元的免费试用额度。接着开始添加虚拟机,参考下图来填写相关内容,如区域、镜像、登录用户名密码等。这里我选择了美国区域,Redhat系统,1CPU 1G内存的配置。



创建成功后,这台虚拟机会分配一个公网IP地址,需要通过SSH连接上去安装代理工具。




02


安装代理工具


使用任何一款SSH客户端,通过公网IP,以及创建虚拟机时设置的用户名和密码登录到主机,开始安装一个叫TinyProxy的轻量级网络代理工具。


首先试了用 yum install -y tinyproxy 来安装,发现它不在软件包内,于是就尝试用源码安装。


打开TinyProxy的Github主页:

(https://github.com/tinyproxy/tinyproxy ,复制一下Code-> Download Zip 按钮的链接地址,在虚拟机上下载:

$ wget https://github.com/tinyproxy/tinyproxy/archive/refs/heads/master.zip

解压:

$ unzip master.zip

按照文档提示执行 ./autogen.sh 时报错

./autogen.sh: line 11: aclocal: command not found

查了资料,需要安装缺失的包:

$ sudo dnf makecache$ sudo dnf install automake

然后继续执行  ./autogen.sh 仍然报错:

configure: error: no acceptable C compiler found in $PATH

查了资料,继续安装缺失的包:

$ sudo yum groupinstall "Development tools"
然后就可以顺利执行了,依次执行下面的命令:
$ ./autogen.sh$ make$ sudo make install
这样TinyProxy就安装完成了,可直接通过tinyproxy命令启动。启动之前,需要先创建一个配置文件 tinyproxy.conf,内容如下:
User mendelGroup mendel
Port 8888Listen 0.0.0.0LogFile "/home/mendel/logs/tinyproxy.log"Timeout 600
配置代理端口为8888,并不限客户端IP来源,配置日志文件路径及超时时间等。然后即可启动tinyproxy代理。
$ tinyproxy -c tinyproxy.conf
然后跟踪一下日志文件,看下启动状态:
$ tail -f logs/tinyproxy.log
大致内容如下:
NOTICE    Apr 22 02:37:33.029 [32592]: Initializing tinyproxy ...NOTICE    Apr 22 02:37:33.032 [32592]: Reloading config fileINFO      Apr 22 02:37:33.035 [32592]: Added address [0.0.0.0] to listen addresses.NOTICE    Apr 22 02:37:33.037 [32592]: Reloading config file finishedINFO      Apr 22 02:37:33.040 [32592]: listen_sock called with addr = '0.0.0.0'INFO      Apr 22 02:37:33.043 [32592]: trying to listen on host[0.0.0.0], family[2], socktype[1], proto[6]INFO      Apr 22 02:37:33.045 [32592]: listening on fd [3]INFO      Apr 22 02:37:33.049 [32592]: Not running as root, so not changing UID/GID.INFO      Apr 22 02:37:33.052 [32592]: Setting the various signals.INFO      Apr 22 02:37:33.058 [32592]: Starting main loop. Accepting connections.
说明代理工具启动成功。赶紧测试一下吧!但需要先在虚拟机的网络配置中添加入站端口规则,把8888端口开放访问:


添加成功后,就迫不及待的用公网IP和8888端口配置到本机电脑的网络代理配置中,结果空欢喜一场。虽然偶尔能连接上,但是很不稳定,而且ChatGPT的网页也一直打不开,并没有解决我的问题。于是开始陷入了沉思...



03


用SSH配置代理


我想到了,我的ChatGPT Lite (https://chat.mengchen.cc)是在阿里云Server上部署的,而阿里云是没办法直接访问OpenAI的,我之前临时采用的方式是通过Xshell工具连接上Server后,配置一个端口转移规则(即SSH隧道,SSH Tunnel),将某个端口从Server上映射到本机LD的代理服务器端口,然后在Server上去访问OpenAI接口时,设置一下使用的代理(proxy)即可(如Python的requests发起请求时设置一下proxies属性)。

(LD设置页面,展示代理服务器信息)


于是,我参考这样的方式,先用Xshell登录上Azure虚拟机,然后配置一个SSH隧道,如下图所示:

(XShell,为会话配置端口转移规则)


这里的方向选择“本地(拨出)”,建立本机端口8890到虚拟机端口8888的映射。配置好后,将 127.0.0.1:8890 配置到系统的网络代理设置中,最后果不其然成功了!ChatGPT也可以顺利访问了,就是网速慢点,毕竟节点在国外,也可以接受。


按理说,到了这一步已经基本解决了我的问题,可以实现魔法了。但每次使用前都要打开Xshell登录,然后打开系统网络设置,开启代理,输入IP和端口,不用的时候还要关掉,总觉得麻烦。应该有相应的命令来自动化执行这些操作。于是想到了批处理(bat文件),开始继续探索...




04


自动化脚本


关于SSH端口转移,是我最开始在工作中学到的,当时为了用本地MySQL客户端去直接连接线上数据库排查问题而配置的,那时感觉这个功能很强大,能把线上和本地连接起来,同时以为端口转移是XShell工具特有的功能。但随着经验的不断积累,以及最近开发ChatGPT Lite,逐步意识到这个应该是SSH本身的功能,于是查了一下果真如此,这个叫做SSH Tunnel技术。所有XShell工具上的可视化操作,都有对应的ssh命令支持。


所以,我找到了配置端口转移的命令,并在本机执行如下命令,成功配置了ssh隧道,跟XShell配置的结果一样。

$ ssh -f -NL 8890:localhost:8888 mendel-proxy
其中:
  • -f : 让隧道创建后在后台运行,而不在命令行前端执行
  • -N : 只建立隧道,而不连接到远程主机
  • -L : 方向,这里指ssh隧道在本机执行,建立从本机到远程的映射。如果是 -R 则表示从远程到本机的映射。
  • 8890 : 本机建立的端口
  • localhost:8888 : 在远程机上的IP和端口
  • mendel-proxy : 远程主机名,即 username@ip 的形式

以上命令每次执行时都需要输入server的登录密码,感觉比较麻烦。于是做了一下如何用ssh实现免密登录。先生成本机SSH秘钥:
$ ssh-keygen
敲几下回车后即可创建完成,可以在用户主目录 ~/.ssh 目录下找到 id_rsa 和id_rsa.pub两个文件,分别表示私钥和公钥。接着需要将公钥复制到server上。如果是Mac,可以直接用ssh-copy-id实现复制,但在windows上这个命令不可用,需要用等价的方式操作:
$ type id_rsa.pub | ssh mendel-proxy "cat >> ~/.ssh/authorized_keys
其中 type 相当于 Linux/Mac 的cat命令,可以查看文件内容。通过管道操作符“|”将文件内容传到经ssh登录的主机上,并追加到authorized_keys文件的末尾。这样server就允许了这个客户端的免密登录授权。

端口映射可以用命令实现了,同样修改网络代理也可以。在windows上通过修改注册表来实现:
$ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 1 /f $ reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /t REG_SZ /d "127.0.0.1:8890" /f

最后,需要再智能化地判断一下,当前ssh隧道是否正在运行,来表明代理是否开启中。如果开启中,可按下某个键来关闭隧道和代理如果关闭状态,可以按下某个键开启隧道和代理
$ tasklist | findstr /i "ssh.exe" >nul 2>nul && goto running || goto notrunning
其中前半段命令是在进程列表中寻找是否有ssh.exe进程(建立隧道后就会有这个进程), running 和 notrunning 是在bat文件中的两个label,实现当ssh.exe进程存在和不存在时控制程序流程的跳转。

当进程存在时,我想通过输入Q来实现关闭隧道和代理,那么可通过下述代码实现:
:running      echo *** Proxy is running. Press Q key to shutdown.    choice /c q    if %errorlevel% equ 1 (            taskkill /f /im ssh.exe      echo *** Proxy is shutdown.
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 0 /f reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /t REG_SZ /d "" /f echo *** Network proxy deleted.
pause>nul ) exit
同理,如果进程不存在,通过输入S来开启隧道和代理,代码如下:
:notrunning    echo *** Proxy is not running. Press S key to start.    choice /c s    if %errorlevel% equ 1 (      echo *** Connecting SSH tunnel...      start "" ssh -f -NL 8890:localhost:8888 %PROXY_HOST%      echo *** Connect SSH tunnel success!
echo *** Modifying network proxy... reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 1 /f       reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /t REG_SZ /d "127.0.0.1:8890" /f echo *** Modify network proxy success!
echo *** Proxy is started.
pause>nul ) exit
最后再加一个 install 过程,用于初始化。当判断本机没有 id_rsa 文件时执行前面几个步骤。最后整个程序的整体判断逻辑为:
if exist "%USERPROFILE%/.ssh/id_rsa" (  tasklist | findstr /i "ssh.exe" >nul 2>nul && goto running || goto notrunningelse (  goto install)
最后保存文件为 .bat 后缀,就可以直接双击执行了。(有需要完整代码的可以私信我)


05


借助ChatGPT的力量


可用于Windows上的bat文件做好了,但是我想在Mac上也运行怎么办。由于命令有差异,直接原封不动放到mac上是无法运行的。需要针对Mac重新开发一版。鉴于ChatGPT,尤其是GPT-4的强大,我想到了,可以让ChatGPT基于我的windows bat文件生成适用于Mac系统的功能相同的脚本。果不其然,它成功地给出了代码,经测试,只要将第一行 #!/bin/bash 换成 #!/bin/sh,其他的原封不动。可直接在Mac上顺利运行,功能完全一致!不得不说,有了ChatGPT,不怕做不到,就怕想不到。用了它,绝对事半功倍。


但.sh文件在mac上需要打开Terminal并增加执行权限(+x)后才能运行,不像bat可直接双击运行。后来查了下,把sh文件改成 .command结尾即可实现。但是首次双击 command文件时,会有安全警告,需要在系统的安全设置中选择“仍要打开”后才可正常使用。


至此,代理工具就开发完成了。整个过程虽然踩了不少坑,但收获还是很大的。恢复了ChatGPT的访问后,我第一时间又续费了一个月的Plus会员用于GPT-4的使用,希望它能继续为我发挥价值。


友情提示:本文涉及的一些技术点在研究探索时借助了ChatGPT,但本文的所有文字均由本人编写,并没有借助ChatGPT生成。


(全文完)





相关文章