my blog my blog

Tag: Lua
一个openai的ChatGPT反向代理实现

在奶牛看来,用api的同时保护自己不被暴露的安全性是最重要的。ChatGPT最近老火了,虽然奶牛还没用上4.0,一直在排队,但是也写点儿东西来弥补一下这个曾经没什么作品的遗憾吧。一直以来都没有发不过什么作品,这次写了个docker来实现这个反代。以OpenResty,通过lua来做安全验证防护,通过Nginx的proxy来反代。

使用方法:

docker pull nenew/openai-api
docker run -itd --name api-server -p 127.0.0.1:811:80 nenew/openai-api

你的openai反代地址: http://127.0.0.1:811
通过绑定到本地端口,可以阻止服务器被公众访问。
如果想让你的api反代服务器被公开,你也可以通过-e选项来绑定一个可以访问的IP或者设置一个密码来保证只有自己可以使用。

docker run -itd --name api-server -p 811:80 -e BIND_IP="123.123.123.123" nenew/openai-api
docker run -itd --name api-server -p 811:80 -e SECRET="Your secret" nenew/openai-api

注意:如果你设置了SECRET环境变量,你还需要设置你的app的请求头,增加X-Secret来完成验证:

X-Secret:Your secret

 测试:

访问 http://127.0.0.1/status 你可以看到你的请求头、请求体、设置的IP、设置的密码以及响应头的具体信息.
你也可以设置你的app的api到这个页面来进行测试或者使用Nginx的proxy_pass来设置转发。

proxy_pass http://1277.0.0.1/status

为什么你的反代不安全

其实写这个docker的原因很简单,看到很多不安全因素存在在你们的自建api里面。
首先你们没有去掉或者掩盖[“X-Real-IP”]和[“X-Forwarded-For”]。
反向代理的作用是保护目标服务器,但是我们其实想通过反代保护我们自己来保障我们的app可以正常的访问,所以完全没有必要把我们的X-Real-IP和X-Forwarded-For给目标服务器。我们建立反代其实目的是建立一个正向代理。这两个参数明显会暴露我们自己的真实IP,造成api的key多人使用的问题。
其次,很多人自建的api谁都可以用,比如像那些利用serverless实现的反代,你的访问IP地址每次都可能变化,那样子你的api key很可能就被判定为滥用【remote_addr一直是变化的】。我这个docker可以通过设置绑定IP和SECRET来阻止外界访问。
我认为最安全的方案应该是:
把这个docker放在你的独立服务器或者VPS上,你可以设置你的web app也在同一台服务器上,当然你也可以设置你的app来通过加密或者绑定IP的方式来达到隐藏自己的目的。

使用Nginx Lua阻止对服务器IP的80/443端口直接访问

Lua作为Nginx服务器的脚本扩充非常好用,而且性能也很好。如果要使用Nginx Lua阻止对服务器IP的80/443端口直接访问,我们可以对nginx.conf进行如下设置

location / {
access_by_lua_block{
	if ( ngx.var.host ~= "www.nenew.net" ) then 
		ngx.exit(444)
	end
                    }
             }

其中的ngx.var.host代表目标域名,有几个变量可能会发生混淆:

ngx.var.server_name对应server_name:www.nenew.net
ngx.var.host对应host:test1.nenew.net
ngx.var.hostname对应hostname:nenew

这里我们就看啊,如果我们把IP绑定给其它域名,或者对方直接用hosts来进行dns解析,改变的是ngx.var.host,这个是访问者的目标域名,是变化的,所以这里block是针对的ngx.var.host,只要判定不相同即无法访问,我们直接给一个444状态,切断连接不响应。hostname是主机名,这里没有什么用,ngx.var.server_name变量是绑定域名,不能用绑定域名来判定,因为绑定域名会变,但是访问域名可能会造成改变。