忙里偷闲的八月
八月依然有些很狗血的策划案要做,以至于花了两周时间,周五做出来后,连策划自己都觉得配置超多超复杂。。。
这个月比较过瘾的,是下决心做了 dns 的实验。当时为了防止 DNS 污染,曾经用 Python 写过一个 DNS 代理,通过 TCP 管道传输解析包,避免墙的干扰,地址在 google code。项目原本是通过丢弃最先返回的 udp 包来实现的,后来改为了 TCP 查询。不过,当时硬着头皮读的 RFC1035,只读懂了 TCP 的部分,只要将接收到的包体加上长度作为包头,就可以直接丢到 TCP 管道的另一端,解包也是根据包头解出 DNS 返回包,送回到查询者即可。
于是,这个月就再重读了一次 RFC,实现了一个基本的域名 =>dns 查询工具,地址在 github。真正实现的时候,RFC 文档还是很实用的,尤其是里面查询结构的定义,相当清晰。就是在 python 里不大好处理位,需要自己做与运算。实现时有个问题不是很明白,为什么域名要分成 label 这样的短字符串来实现,搞的一个域名有可能用了 3 个字节,只是用来分别标记 3 个 label 各自的长度呢?后面有提到域名 label 的复用机制,但是这个和一个完整字符串是不矛盾的啊。Anyway,这种 jump 指针的实现的确很巧妙,甚为折服。调试的时候,还初步学会了使用 scapy 工具,碉堡了。可以输入 RFC 里面的各种参数来构造一个包,还能打印出包体的字符串表示,通过对比很快知道了自己实现的缺陷所在。最爽的是还能从 IP 包构建到 UDP 包,通过 IP 包 /UDP 包 这种表示来表达 payload 的意思,有空用来写个 TCPkill 玩玩,哈哈。
另一件,是参与到晓靖的 levent 项目 里。levent 在 Lua 里基本复刻出 python 的 gevent,顺带创建了自己的类机制,还有一些非常实用的库比如 struct(跟 python 的 struct 相仿)。随手写了两个示例,一个是负责端口转发的 portforward,另一个是 http 代理 。写端口转发的时候,竟然有种写 golang 的感觉,一个 lua 的 coroutine,就好比一个 golang 的 goroutine。针对一个 socket 起了两个协程,一个负责读,一个负责写,在虚拟机里跑能有 2000 多的 qps,还算不错。对比 gevent,gevent 一开始能够上 3000 多,不过越跑越慢,最后完全跑不动了。用的是示例里的 echo server,测试用的 redis benchmark。http 代理的实现,参考了 PythonProxy 的实现。对于 1.0 的 http 协议,只支持了 GET,POST 等有限几种方法。除了 CONNECT 方法外,基本都是改写一下头部,丢过去服务器就可以了。CONNECT 方法更简单,连接后直接作为管道转发数据,连 header 都不用改写了。。。
希望接下来的 9 月顺顺利利啊