一个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的方式来达到隐藏自己的目的。

Ubuntu下安装Docker构建镜像教程

奶牛就做简单的记录了。在Ubuntu下使用

apt  install docker.io

这样子就完成安装了。然后我们需要登录https://hub.docker.com/settings/security设置Access Tokens

docker login -u nenew

输入生成的Tokens就可以登录了。之后我们通过Dockerfile构建镜像。

docker build -t nenew/python_run:v1.0 .
docker push nenew/python_run:v1.0
docker pull nenew/python_run:v1.0

这样子构建,推送,取回就都可以完成了。

windows下安装weditor的gbk错误处理方法

奶牛在使用pip直接安装的时候发生错误,提示一个gbk的编码错误。这个时候就不要继续pip安装了,那些网上说降低版本安装也是没有必要的。直接git源代码安装即可。错误的信息是:

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xad in position 825: illegal multibyte sequence

git clone https://gitcode.net/mirrors/alibaba/web-editor
cd web-editor
python setup.py install
pip更换国内源

在windows下生成一个pip.ini放在user/nenew文件夹下,pip.ini的内容是

[global]
index-url = https://mirrors.aliyun.com/pypi/simple
[install]
use-mirrors =true
mirrors =https://mirrors.aliyun.com/pypi/simple/
trusted-host =mirrors.aliyun.com
关于minio的docker配置以及403错误解决方法

关于docker版本的minio安装,其实很容易,就按照官网的配置好就可以了,奶牛是群晖的nas,所以在nas的docker里面直接把minio给pull回来就好了,然后就是一些配置选项。

这里需要注意的是要指定KMS,要不S3会发生无法传输问题。

MINIO_KMS_MASTER_KEY
MINIO_ACCESS_KEY
MINIO_SECRET_KEY

主要就是配置这三个key,直接指定就好了,其中的access key和secret key对应的就是minio的登录用户名和密码,大概就这么理解就成了。

然后记得把路由器的端口绑定做好,绑定到9000端口。

然后就是同步使用aws s3的时候,可能会遇到403的bug,奶牛在使用ansible来做同步的时候也是看到了403错误,这里把403在aws cli里面显示的是

An error occurred (RequestTimeTooSkewed) when calling the ListBuckets operation: The difference between the request time and the server's time is too large.

就是说服务器间的时间差距太大了,一看自己的server,果然是时间不太准了,设置下

date -s "20201211 19:58:00"  #yyyymmdd hh:mm:ss

然后再执行就很容易了。

最后记录下aws cli的s3配置

aws configure
AWS Access Key ID [None]: Q3AM3UQ867SPQQA43P2F
AWS Secret Access Key [None]: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
Default region name [None]: us-east-1
Default output format [None]: ENTER

aws configure set default.s3.signature_version s3v4

aws --endpoint-url https://play.min.io:9000 s3 ls

aws --endpoint-url https://play.min.io:9000 s3 ls s3://mybucket

aws --endpoint-url https://play.min.io:9000 s3 mb s3://mybucket

aws --endpoint-url https://play.min.io:9000 s3 cp simplejson-3.3.0.tar.gz s3://mybucket

aws --endpoint-url https://play.min.io:9000 s3 rm s3://mybucket/argparse-1.2.1.tar.gz

aws --endpoint-url https://play.min.io:9000 s3 rb s3://mybucket

minio实现了s3的很多功能,但是权鉴什么的没仔细研究,分布式的同步方案要4个存储空间,也相对要求太高,不过简单易用,如果作为对象存储服务器,奶牛觉得还是有差距的,只是个小的替代品。

群晖NAS黑转白DS920+实战

奶牛家的黑裙NAS寿终就寝了,估计是电源挂了,也懒得修了,直接上了今年的新款DS920+,下面说说群晖黑转白的过程。

1.拆盘+换盘

把旧盘拆下来直接插到新机器上就ok了,数据都在。

2.开机联机升级系统

用群晖助手找到新的IP,然后联机上nas的5000端口,一路下一步。

3.重置安装

发现从ds5.x直接升级到ds6.x会有系统bug,直接用不了,索性有比较好的重置功能,不怕丢数据,也不怕raid信息丢失。现在已经在为raid0担心了,又入了一块儿银河企业盘做备份。

群晖后面有个reset口,用针插会听到嘀嘀的声音,听到声音后松开针,再在1秒钟内重新按住,会听到陆续的三声嘀嘀,机器进入重置模式,然后用下载的固件直接重置安装即可,默认的设置估计都不在了,帐号也不在了,bt下载的话transmission得重新安装,自己网上找教程就好了,还有就是transmission的数据记得转移,如果安装位置有所改变的话。

transmission的配置在/volume1/@appstore/transmission/var里面,新安装在哪里就从哪里复制一份备份进去,记得chown把用户名和组搞定。

MT的话建议把DHT关闭。剩下的就继续自己探索了。

群晖在控制面板开启ssh后可以用用户名登录,之后sudo su提升权限到root,这样子就不会出现权限尴尬的问题了,但是操作的东西记得把权限也改了。

密码保护:2020年年中小记

这是一篇受密码保护的文章,您需要提供访问密码:

年味儿已逝

去年开始,烟花礼炮已经全面禁放,最后的年味儿也随着今年春晚名单出炉慢慢淡出我的世界。

三十岁,果然是个坎儿。

记得小时候,即使不玩儿用火点的烟花礼炮,也会买一些泥巴做的土炮仗摔着听响儿,大概现在在城市里买都买不到了。

我的孩子可能从出生就不知道过年到底是什么,又该怎么过。

百无聊赖,还不如上班来得充实自在,当然,我年年都得上班,没有节也没有假日,只希望财富自由的那天快点儿到来。

最近给自己添置了两件家用电器,一个电动马桶盖,一个电动牙刷,总体使用下来,感觉还是很好的,特别是经过洗牙之后,抽烟的牙怎么也刷不干净,用电动牙刷效果真的好很多。还有电动马桶盖,终于知道为什么印度等地区为什么痔疮发病率那么低了。

最近在学习各种行业,关注各种公司,新能源汽车在今后相当长的时间内会慢慢升温,然后逐步替代现在的燃油车,这个趋势真的非常好,今天记录下来,几年之后翻看不知道感想几何。

罗曼蒂克消亡史——2019年总结

2020年伊始,奶牛对2019年做做总结。

马上就步入30岁了,越发觉得时间匆匆了,我恨不能时间停滞,让我再努力努力。

在过去的十年里,我觉得我的思想还是很浪漫的,倒不是说多无忧无虑,但也终归都把不快忘记,虽不满足于衣食无忧,却也得过且过地活着。

2019年宝宝降生,生活上也有很多改变,多了份做父亲的责任,也开始对未来有了更多思考。

过去的自己对钱看得并没有那么重,虽然并不是大手大脚的人,但是心理上觉得这东西真的就是那句话,“钱是王八蛋,没了咱再赚”。

可是2019年也是自己真正成长的一年,很多事看开了,很多东西却开始看重了。

说说教育,我们在学校里面学习的永远是怎么工作(至少大部分专业是学习如何从事一项工作的基本技能),但却从来没人教你怎么赚钱。

就像一圈人在打牌,打了好几圈了你还不知道赔钱的傻子是谁,那么你就是那个傻子。

我觉得2019年是我真正开始价值投资的一年,很多事情认清了之后就知道自己的方向了,虽然前路可能很艰辛,但是我依然充满激情。

对于IT圈的关注会逐渐从技术方面转移,慢慢向上层,向前沿,向未来进军。

巴菲特是不搞自己一眼看不明白的投资的,但是,我觉得既然很多东西自己还能明白一些,那么就去投投看看,我不相信互联网只有泡沫,比特币就是一个很好的例子,当然,其实我想说区块链。

关注大环境更多了,政策干预多数时候都是向好的,背道而驰必然行不通。

2019年,基金定投已有3年,成效初现,我仍然只能用自己的生命去验证自己的对错,希望自己可以活得久一些。

昨天看到一个名叫 “洛阳小散户”的投资者的文章,感觉自己的起步确实晚了一些,但是还不算太晚,人生真的就是阶段性的,你不到那个年纪,又没人给你指导,你肯定会走很多弯路,所以一定一定要多读书,读关于财富的书,然后心理学,数学,哲学,历史,管理学,经济学,感觉要涉猎的方面太多了,只是自己真的晚了很多,在过去的十年里,我看的最多的书都是关于IT技术的,不能说是浪费了很多时间,但是就未来来看,可能走偏了一些。

还好,还好,至少现在认清楚了很多。

我们的思维,大多时候就随着教育,被固化了,昨天看到一句话特别好:“困难不在于接受新思想,而在于摆脱旧思想”。

只希望在未来几年可以实现财富自由,可以有更多的时间可以去探索更多奇妙的领域,可以有更多的时间陪伴自己的孩子成长。​​​​

使用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变量是绑定域名,不能用绑定域名来判定,因为绑定域名会变,但是访问域名可能会造成改变。