2

近期计划启用整个团队的chatgpt4.0。现实情况决定了我们需要chatgpt4.0却不是频繁需要,所以当下的需求实现上变成了:

  1. 团队中的每位成员都可以在不爬梯子的情况下使用chatgpt
  2. 4.0的费用是20刀/月,我们希望将整个团队的费用控制在这个当量下
  3. 4.0有请求频率限制,我们希望能够充分的利用好这一限制,让每位成员都有使用的资格,但却不过渡使用从而触发限额。

而上述过程的第1步,则需要当前搭建本地chatgpt的服务器可以愉快的连接openapi的接口地址,而本文的主旨在于解决这个本地chatgpt的网络问题。

反向代理

网上有很多帖子在讲,如何购买国外的云服务器,然后配置nginx做为反向代理的问题。这种方案简单可行,还可以通知防火墙来提供反代的安全问题。

VPN

我们使用 VPN 技术来解决这一问题,来把本地的服务器完全模拟在外网环境中。由于服务器本身就像是在外网环境中一样,所以用这种方式其实可以规避很多小的问题。而访问chatgpt的api接口当然也不在话下了。

在此,我们使用更简单(尚可以发布)的wireguard来完成 VPN 的搭建过程。

服务端

远端服务端需要自己解决或是有一些 VPN 的运营商。在此我们以ubuntu为例:

首先是通过su来切成root用户,然后安装wireguard:

# apt install wireguard

安装完成后,但有两个命令可用,分别为:wgwg-quick

此时先使用wg生成一个密钥对:

# wg genkey | tee privatekey | wg pubkey > publickey

此时将生成私钥privatekey及公钥 publickey

然后来到/etc/wireguard使用nano wg0.conf来创建一个wireguard配置文件,内容如下:

[Interface]
PrivateKey = 这里换成privatekey的内容
Address = 10.10.8.1/24
ListenPort = 5128
DNS = 1.1.1.1,8.8.8.8
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

简单解释一下:

  • PrivateKey 私钥内容
  • Address 当前wireguard服务端地址及分配的对端IP范围
  • ListenPort 监听端口号
  • DNS DNS地址
  • PostUp wg接口启用时,向iptables中添加一些转发的命令,这样对端发起的请求,便可以通过本服务端进行转发了
  • PostDown wg接口停用时,将前面添加的记录删除掉

为了使用服务端可以对客户端的连接进行转发,还需要启用转发功能:

# nano /etc/sysctl.conf

在文件中找到#net.ipv4.ip_forward=1并把前面的注释去掉,如果并没有这行,则直接在文件中添加一行:net.ipv4.ip_forward=1。保存文件后,执行:

# sysctl -p

使其改更生效。

最后启动wg:

# wg-quick up wg0

客户端

在客户端使用的操作系统仍然为稳定的FreeBSD,安装wireguard如下:

首先使用su命令切换到root用户,然后运行命令:

# pkg install wireguard

接着创建一个文件夹:

# mkdir -p /usr/local/etc/wireguard
# cd /usr/local/etc/wireguard

然后同样创建一对密钥对:

# wg genkey | tee privatekey | wg pubkey > publickey

在这个文件夹中执行ee wg0.conf创建一个配置文件,内容如下:

[Interface]
Address = 10.10.8.100/24
PrivateKey = 这里换成privatekey的内容

由于做为客户端出现,所以配置比较简单。仅仅配置了本端的ip地址及私钥。

PEER

wireguard其实是弱化了客户端与服务端的概念的,即每个安装了wireguard的主机,即可以是客户端也可以是服务端,也就是说它们是对等端的关系。这种对等的关系往往体现在两个主机可以直接通讯的前提下,但由于我们当前的客户端处于 NAT 下,所以才有了服务端与对等端的概念。而在配置中,则需要在客户端处增加配置Endpoint

通讯双方还可以设置PreSharedKey预设共享密钥来增强安全性,这样以来在第一次通讯时,双方传输的即为加密数据。

在客户端与服务端使用wg genpsk来生成这一共享密钥

首先进行服务端的peer配置,编辑服务端配置文件/etc/wireguard/wg0.conf,添加以下配置:

[peer]
PublicKey = 这里使用客户端publickey的内容
AllowedIPs = 10.10.8.100/32
PreSharedKey = 这里使用刚刚生成的共享密钥的内容

上述配置中 10.10.8.100 为客户端在前面配置的IP地址。

客户端的配置相对复杂一些,同样编辑客户配置文件,增加配置如下:

[Peer]
PublicKey = 客户端publickey的内容
Endpoint = 服务端公网IP:5128
AllowedIPs = 这里的地址后面给
PreSharedKey = 这里使用刚刚生成的共享密钥的内容(与服务端的相同)
PersistentKeepalive = 25

上面的AllowedIPs有点讲究,这里的内容需要先打开 https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/ 然后通过输入:走 VPN 通道的地址以及不走 VPN 通道的地址来生成,比如:

image.png

请将上图中的192.168.0.0/16替换为自己的实际情况,如果你需要将所以的流量都通过 VPN 进行转发,那么也可以这样:

image.png

其中把1.2.3.4换成服务端的公网 IP 地址。

原则上即使不在AllowedIPs中排除公网IP地址,其实也应该是没有问题的。但是如果需要进行定制化的生成AllowedIPs,则必须将服务端的地址加入到 Disabllowed IPs,然后进行运算。

最后点击运算:

image.png

则会得到我们需要的 AllowedIPs,将得到的值复制到配置文件中即可。

启动

在服务端与客户端分别执行 wg-quick up wg0,即可完成启动。此时在客户端使用curl cip.cc,如果显示为服务端的公网 IP,那么恭喜你已经成功了。

在freebsd系统下,还可以向 /etc/rc.conf 添加:

wireguard_enable="YES"
wireguard_interfaces="wg0"

来完成开机自启动。

在ubuntu系统下,则可以通过:

sudo systemctl enable wg-quick@wg0.service
sudo systemctl daemon-reload

设置wireguard的开机自启动。

chatgpt测试

执行:

curl 'https://api.openai.com/v1/chat/completions?path=v1' -H 'authority: api.openai.com' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' -H 'accept-language: en-GB,en;q=0.9,zh-CN;q=0.8,zh;q=0.7' -H 'cache-control: max-age=0' -H 'sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"' -H 'sec-ch-ua-mobile: ?0' -H 'sec-ch-ua-platform: "macOS"' -H 'sec-fetch-dest: document' -H 'sec-fetch-mode: navigate' -H 'sec-fetch-site: none' -H 'sec-fetch-user: ?1' -H 'upgrade-insecure-requests: 1' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' --compressed

成功返回:

{
    "error": {
        "message": "You didn't provide an API key. You need to provide your API key in an Authorization header using Bearer auth (i.e. Authorization: Bearer YOUR_KEY), or as the password field (with blank username) if you're accessing the API from your browser and are prompted for a username and password. You can obtain an API key from https://platform.openai.com/account/api-keys.",
        "type": "invalid_request_error",
        "param": null,
        "code": null
    }
}

说明当前网络已经成功的对接到chatgpt.

总结

本文阐述一种使用 VPN 技术达到了本地主机拥有外网环境的实现方案。相较于反向代理方案,该方案在实现难度上更大,但相对也更安全。

同时,该方案还适用于:设置在测试或打包时需要外网的机器人的网络环境。


潘杰
3.1k 声望239 粉丝