2015年12月13日星期日

最近看过的书,简评几则


  • 《战争史》(基根):没有想象中的宏大,是更为学术性的书。主要针对战争本身进行研究,阅读起来略微有一些无趣。作者跟克劳塞维茨算是杠上了。
  • 《毛毛星球》(约翰.斯卡尔齐):一本小品式的“科幻”。介绍上说是硬科幻,但里面的法律内容比科学和幻想加起来还要多。就像很多读者说的那样,作者的确“很会讲故事”,是很“温情”的故事,我喜欢。只可惜有“毛毛”死去,看到最后虽然正义感得到了满足,但还是轻松不起来。
  • 《锁定目标》(汤姆.克兰西):一开篇就是火爆的动作场面,后面也是高潮不断。人基本上还是那班人,但比《虎牙》刺激多了。一本不错的克兰西作品。
  • 《悖论:破解科学史上最复杂的9大谜团》(吉姆.艾尔.哈利利):还算不错的入门级科普,看过之后应该能对物理学上的一些重难点有所了解,而且又不至于被吓倒。留给儿子以后看吧。
  • 《羊毛战记》(休.豪伊):不错的反乌托邦科幻,和Fallout系列的感觉很接近。我觉得用Fallout1/2的引擎很容易就能根据这书的剧情改编出一个游戏来。144层的Vault,想想也很大。不过从后期透露的信息看来,虽然深度很大,但每层的面积并不是很大。作者用了一种舞台剧一样的写法,情节冲突也是一波一波地。这种写法我不是太喜欢,不过还是很期待下一部的续集《尘埃记》。
  • 《虎牙》(汤姆.克兰西):比起《锁定目标》来,这本的节奏就太过平稳了。个人认为唯一称得上动作戏的,就只有Mall里面那场枪战而已。不过这本书主要是为了交待“校园”的来历,大概是过渡性的作品吧。
  • 《虚无的十字架》(东野圭吾):本以为是本格派的作品,结果读完却几乎以为是松本清张写的。我对他了解还不是太深。据说是14年的作品,难道东野圭吾在转型成社会派?作为日式推理小说并不是太好看,看起来被亚马逊放进特价书目里面并不是毫无理由。线索太散乱,布局感又太明显,立意很高,但显然对这个话题又无力下定论。何况是个很沉重的故事,看起来实在是太不轻松了。

2015年12月2日星期三

完了完了,今年又要完了

数了数,从去年的年末座谈会到现在,今年(2015年)一共只写了八篇Blog。平均一个月还不到一篇,我真的是太过于懒惰了。

其实,因为不见得全是懒惰。一方面,今年公司上马新项目,我是主程,工作时间特别忙,已经很难再抽出空来写Blog了。另外一方面,今年家里出的状况也特别的多,私人时间也很难抽得出来。曾经寄希望于搬家之后每天上下班时间能够在公共交通上完成这个任务,但现在看起来也不太适合。总之吧,客观原因还是挺多的。

争取这个月多写写吧。眼下貌似没有那么忙了。不然月底竜堂家四兄弟又要来找我的麻烦了。

2015年8月27日星期四

也谈Shadowsocks的“关闭”风波

之前已经在Google+上零星地发表过一些看法。本文总的来说可以看作是对这些零星看法的一个汇总和系统化。已经看过的朋友可以无视。
另外,标题之所以对“关闭”二字加引号,是因为这种开源项目从严格意义上来说没有什么关闭不关闭的。项目已经被许多人fork过,Release也都还在,就算最新源代码被删了又怎么样呢?也就只是做给国安局的人看看吧。

言归正传……

这次Shadowsocks作者被盖世太保警告,然后GitHub上的项目代码被删,在IT界造成了不小的震动。除了愤怒与哀叹,还有以下几个问题/观点也被抛出:
  • 认为没什么人对Shadowsocks作贡献。
  • 把GPL开源转闭源违反协议。
说起来,这两个问题,其实是开源项目的问题,与GFW无关。原作者在删代码之前,也曾言辞激烈地作过批评。现在的这两个看法,基本上也延续了原作者的思路。不过,我倒是有一些不同的看法。

首先,要说说对开源项目的贡献这种事情。
在程序员(开发人员)看来,对开源项目作贡献,通常意义上意味着需要修改/提交代码。至少,也得明确地指出Bug的所在,可能还得需要有对应的解决方案或手段。这样,才能算是对项目作出了贡献。
但是,在我看来,那些只是默默地使用着Shadowsocks,用来配合自己的VPS完成翻墙的人,他们都对这个项目有贡献。如果测试出了错误,当然应该指出。但是还有更多没有测试出错误,没有遇到错误的使用者,他们同样可以被视为是测试人员之一。一个庞大的用户基数,是保障一个软件变得越来越成熟的基础。如果没有什么人用,即使自己或一个小团队测试并修正了很多Bug,也不能确定它是不是真的足够稳定耐用。如果有很多人使用,但是没有什么人报告Bug,那只是说明了作者水平不错,并不能说明别人不贡献。
那么,如果一个开源项目做得不好,差劲,问题多多。别人用了之后拔腿就跑,还是不肯修改或报告错误,这是不是就能说明“天朝那么多牛B哄哄的程序员不肯作贡献”了呢?
答案还是“否”。开源项目,是有自己的生态系统的。如果一个项目大家都跑,那它就应该消亡。用脚投票,也是一种贡献,不能因此责怪别人“不作贡献”。只有完全不用,这就真的是“不作贡献,但你难道把这种事情怪到卖菜小贩头上?
在我看来,之所以Shadowsocks原作者会觉得没什么人帮他改代码,恰恰在于他把这个项目做得太好用了。大家用起来都很舒服,自然不会有什么人想要去改。会想去改的人,就更可能是那些“爱折腾”却又不具备相关能力的人,所以作者才会觉得有压力。
换句话说,对于真正有能力改动代码的人,以及要求不高的人而言。Shadowsocks一开始就已经足够好了。这就过滤掉了一大群人。“劣币驱逐良币”这个比喻用在这里可能不是很恰当,不过我相信大家懂我的意思。对于一个用户数够大的软件而言,沉默的人占大多数,这是一个好事。原作者可能还没意识到这个情况。

GPL转闭源这个的确违反了许可协议,这没有什么话好说。我是在想另外一件事情:GPL到底保护了什么?
GPL要求后继项目也必须公开源代码,并且也必须采用GPL。这保证了项目代码会永远开源下去。但问题是,如果你采用GPL许可证,你是想保护你的思想还是你的代码?
由于要求比较苛刻,可能会有更多的人不愿意从GPL项目中fork,特别是那些想商业化的公司、团队或个人。这样一来,你的代码还是原来的代码,没有人来夺走,但你的代码其实是你思想的结晶,否则它们只是一堆敲击键盘而成的无意义的文字而已。如果没有人愿意fork,那你的思想也就无法被继承并发扬。
如果我想让自己的思想发扬光大的话,我会选择让自己的代码进入Public Domain。并且,只提供思路及核心代码,包括一个最简实现。至于项目最后包装成啥样,有兴趣的就自己动手。改动代码也好,只是加个壳也好,做成商业应用去卖钱也好,免费分发也罢,都可以。
本来推墙这种事情,就是需要五花八门,三教九流一齐上。你管它是志愿军还是雇佣兵。反倒是如果仅此一种工具,就很容易被GFW对付。提供一种可行的思路,比做出一个完美的实用产品,可能更合适一点。
这样的好处就是,原作者的压力小了,甚至可以不需要去维护。不需要去考虑产品化,不需要在UI上费脑筋,不需要为了不同用户的一些无关大局的小需求改来改去。这些事情,如果需要,就自然有人会去做。作为原作者,可以把精力放在更有意义的事情上——如果你有那个能力的话。

2015年8月19日星期三

蹊跷的LNK1104错误

最近在给公司开发下一代产品,所以比较忙,也没有太多的事情写Blog。不过昨天在技术上遇到一件不大不小的事情,也许值得拿出来说一下。

这个下一代产品是从头全新开发的,为此我提供了一些基础库的代码,给到项目组的其它Project使用。其中有一个是用的动态链接库的形式。为了方便其它Project使用,我把如下的预编译宏写在了头文件中:
#pragma comment(lib, "XEngine")
这样,所有需要包含这个头文件的代码,就不需要自己去搞清楚到底要链接哪个lib文件了。

但是,同事在拿到代码做全新编译的时候,出现了LNK1104错误。Cannot Open File XEngine.lib。同事当然一头雾水,Baidu上搜了一下之后,一头埋进去检查硬盘坏道去了。

我这边一开始没有问题,当把发布目录中的XEngine.lib删除了之后也出现了同样的问题。源代码对编译结果产生了依赖,这当然是不对的。问题当然出在那句预编译宏上,只不过代码的编写时间过去有点久了,我一时没想起来。
正好这个DLL具有导出函数,因此VC自动生成了相关的代码,只需要把前面的预编译宏放在这里面就可以了:
#ifdef XENGINE_EXPORTS
#define XENGINE_API __declspec(dllexport)
#else
#define XENGINE_API __declspec(dllimport)
#pragma comment(lib, "XEngine")
#endif
这样就解决这个问题了。如果没有这些自动生成的代码可以利用,也可以参考着自己写一个。

2015年6月18日星期四

GAE Proxy可以使用GVS了

根据近来的消息,GoAgent的某些新版本已经支持使用GVS的IP了。
这自然是好事情。GFW把可用的Google IP已经封得差不多了,但GVS却基本没怎么动。如果GVS能用,就又多了一支生力军。(虽然还是会很快很容易地被干掉)

我去验证了一下,的确是可以了。当然,旧版GoAgent的代码需要做一些修改。主要是需要在客户端wrap_socket的时候把ciphers设成ECDHE-RSA-AES128-SHA。改动不止一处,但也不会很多,两三处、三四处吧。
另外一个好消息是,不只是GVS,还有别的一些原本不能用来做GAE Proxy的Google IP,也可以被这样用起来了。

尽管这些IP我估计都撑不到明年6月4日,但能用总比没有强。只可惜Google北京IP段不能用同样的方法来做GAE Proxy,否则那速度就爽了。
本文同样希望低调,就也不作推广了。看得到是缘分。看不到?看不到也就看不到了。

2015年6月9日星期二

荒野求生:把GGC转发搭建在非标准端口上

话先说在前面:这篇Blog,我没有,也不会去做任何的推广。能看到是缘分,尽量保持低调才能活得久一些。这不叫“自我审查”,这叫做对敌斗争策略
另外,本文只提供思路,不提供具体的操作方法(命令、脚本等)。想要知道的,可以自行搜索。也因此,本文可能不太适合技术小白。
好了,言归正传:

着GFW近日来将之前具备的GoogleSSL证书嗅探功能投入使用,hosts的生存周期日渐缩短。根据我自己监控下来的记录,新投入使用的hosts,大约最多只能存活不到两天。在自己的VPS上一旦开启了GGC转发,则48小时之内该IP必定会被黑洞路由掉。

从理论上,SSL证书嗅探可以在旁路上以异步方式排队进行,因此对GFW的性能方面压力并不大。以日为“结算”周期,集中地更新路由表,也可以避免频繁调整骨干路由设置导致的网络不稳。从各方面来说,hosts接下来都是在劫难逃了。

那么,真的没有办法了吗?hosts真的要“死”了吗?

※ ※ ※ ※ ※ ※ ※ ※ 低调的分割线 ※ ※ ※ ※ ※ ※ ※ ※

GFW这次的SSL证书嗅探,是针对443端口的。443端口,是HTTPS协议的标准端口。如果用hosts来翻墙,一定要与HTTPS配合,否则直接明文内容的话是通不过关键词审查的。所以,GFW这次盯住443端口,也是很有道理的。

那么,很自然地就想到,是不是避开了443端口,在别的端口上开启HTTPS服务,GFW就不进行嗅探了呢?这当然取决于GFW使用者,全端口嗅探当然也是可以做到的。不过目前还很幸运,答案是肯定的:GFW只检查443端口,其余的TCP端口被放过了。

接下来的问题就是:Google的服务器,控制权不在我们,如何让它把HTTPS服务开在非443端口上呢?去白宫请愿吗?

显然也不是。既然本文的标题叫做“荒野求生”,主要讲的就是“自己想办法”。Google的服务器我们控制不了,但GGC转发器我们可以自己架(在VPS上)。把端口转发开在非标准端口上,是我们完全可以做到的事情。

然而,另一个问题又来了。好了,我们现在有把HTTPS服务开在非标准端口上的Google服务器,但是,如何让我们的浏览器知道去这个非标准端口上访问HTTPS服务呢?

略有HTTP知识的,都知道在URL里面可以通过主机名后面加冒号来标注端口。我们当然可以这样写来访问这个非标准端口上的HTTPS服务:
https://www.google.com:12345
这样或许是能看到首页。但是,在使用Google服务的过程中,接下来会跳转到的那些URL地址,可能就不能如我们所愿了。另外,不管怎么说,这样用起来也太不自然了。有没有更好用的招数呢?

好吧,稍微想想,其实我们只要在本地再找一台机器,把这个端口转发再改回来,就可以了。像这样(懒得画图了):
浏览器 -> (:443)本地代理 -> (:12345)VPS -> Google服务器
本地再找一台机器,这会不会太麻烦了啊?
其实也不会。有翻墙路由器的朋友,看到这里大概就知道很简单了。没有翻墙路由器的呢?也很简单,在本地搭一个就好。Windows的话,用netsh在本地开一个端口转发,然后hosts指向loopback地址。这样就又可以用hosts了,GAE Proxy也可以用了,真好哎!

2015年6月4日星期四

按更新时间同步单个文件的简易方案

我曾经抱怨过,有个很简单的单个文件同步需求,却居然难以找到有软件能够解决。也许是需求太过于简单,反而没人去考虑。连Allway Sync这么好的东西,也做不到。于是一直都是人肉解决。

最近有点厌倦了每次Copy来Copy去的事情。而且中间也不是没有出过错。一出错就会丢一次的数据。索性简单地写了个bat批处理脚本来解决这种事情:
@echo off
xcopy D:\仓库\文件.txt .\ /D /Y >nul
xcopy .\文件.txt D:\仓库\ /D /Y >nul
运行这个bat脚本后,更新时间比较早的那个副本,会被另外一个覆盖掉。接下来只要每次编辑前或编辑后都记得运行一下这个脚本,就可以使两边文件版本一致,不需要再考虑复制方向对不对的问题了。

可能需要好多个VPS呢

目前打算在VPS上部署下列服务:
  • Shadowsocks:主要给PC和Android用。
  • GGC转发:给PC上的hosts和GoAgent用,比起Shadowsocks来还是快一点。
  • IPSec VPN:给iOS用。
从被GFW发现并封掉的风险来看,由高到低:
  • GGC转发:这个是最容易被检测到的。目前只能开在非标准端口上。开443的话不出一天必死。
  • IPSec VPN:特定端口和协议,也很容易检测。但因为商务上也有比较广泛的应用,被封的可能性比GGC转发还是要低很多。
  • Shadowsocks:如果协议没有漏洞的话,应该只能通过流量分析来检测到。
这样的话,我可能需要准备好几个VPS:
  1. 通用梯:能换IP(或方便加IP)的便宜VPS。三种服务都开。要是被封了就换IP,实在不行就弃。平时主要用这个,最好准备两台,用不同的VPS提供商。
  2. 移动设备专用梯:开Shadowsocks和IPSec VPN。需要在移动数据和WIFI上都能访问的VPS。延迟越低越好。因为手机上切换梯子不方便,所以这个梯子只需要一台就好。
  3. 救生梯:只开Shadowsocks,安装IPSec VPN但平时不启动。可以使用不方便换IP的VPS。平时尽量少用,只用于防止最坏情况出现时无梯可用。延迟只要不是太低都可以。只需要一台。
  4. 共享梯:三种服务都开。只在非本人电脑上临时使用。VPS越便宜越好。只需要一台。
这些梯子上,彼此间所有端口都不能重复,各种密码也都不能共用。

2015年6月3日星期三

匪军六三新动向Ⅱ

最近家里一团糟,工作也忙成狗,按理说今年写Blog的事情几乎要按下来了。但是随着一年一度的中国特色姨妈节的临近,大局域网里各种新情况层出不穷,不写点东西实在对不住自己,也怕清算菊花癌的时候忘记,所以还是来写点吧。

之前就在Google+上提到过,今年匪军吸取了去年的教训,花了大约一年的时间潜心收集各种Google的可用IP,在上个月的时候,就把这些可用IP封了个精光。并且匪军还开启了Google证书嗅探功能,所有HTTPS连接握手时的信息,都每天汇总到菊花残办。新发现的hosts,或者自行假设的GGC转发,存活期越来越短,基本不可能支撑到姨妈节。所幸也就只是这样而已,一阵腥风血雨之后,随着hosts/GAE Proxy的全面倒下,貌似平静了一段时间。

不过明天就是姨妈节了,在这个特殊的日子,我要很高兴地向大家汇报:菊花癌及其启明星姘头又推出了贴心的新套餐——云维稳。

这个云维稳,其实也不是新东西了,我以前在Google+上也层提到过。我发现自己找的Facebook的hosts,在家里能用,但是在单位用不了。抓包看下来,有台设备(TTL==128)在热情地替我Reset。进入非工作时段时,似乎就没这情况了。后来还发现googlevideo.com也享受这待遇,差点害我错判了形势。

这个设备的工作原理很简单:SSL证书过滤。注意是“过滤”,不是大局域网里的那种“嗅探”。你SSL需要握手吧?握手需要Server发Cert给你验证服务端身份吧?咔嚓

那么这个设备是什么呢?是这样的。只要你单位有通过ISP上网,某个“有关部门”就会找到你们单位的IT,要求你们单位购买并安装一个“上网行为管理系统”。这个系统里面呢,当然是会有一堆后门,专门给那个“有关部门”来用的。它们不光能看日志,还能随心所欲地让你来姨妈。

不过呢,今天的情况跟以前相比,又略有一些不同,简单地通报一下:

  1. Google主产品系列今天还没被封。
  2. Blogger眼下享受SSL证书过滤待遇。
  3. Youtube眼下享受SSL域名过滤待遇。

最后这一条我解释一下。“SSL证书过滤”这办法其实不是太高明。因为在某个时间段内证书只在第一次SSL连接时发一次,后面一般是可以跳过这一步的。所以只要用别的方式(VPN或Shadowsocks)拿一下证书,然后就可以hosts正常用了。而“SSL域名过滤”呢,是从你的Client Hello里面去拿Server Name(我只能说SSL太特么老实了)。这下没得跑了。预先拿到证书也没用,一看到关键字就给你咔嚓

话说回来,SSL用来翻墙的确很不合适。浑身上下都是漏洞,特别是在握手阶段,太多特征可以用来检测了。SSL本质上要求服务端身份得到严格确认,这样传输通道才是可信的。但翻墙在这一点上其实是完全相反的需求——服务端身份越模糊越好,最好谁都认不出来。看似矛盾,实际上分成两层来分别解决这两个需求,就没有问题了。不过这是后话,按下不提。

在最后,预祝各位姨妈节快乐,要记得给组织扎小人儿哦!

2015年3月11日星期三

在Windows上用x64的Python运行GoAgent

首先声明:本文适用于至少懂编程,并且爱折腾的人。不一定要很熟悉Python,但至少应该入过门了。

GoAgent自带Python27运行环境,不过因为本机上也安装了Python 2.7 x64,所以希望能直接使用我安装的64位版本。总结下来,要点有:
  • 无论你是否准备使用x64版Python。GoAgent与Python 2.7.9不兼容,应该安装Python 2.7.8版本。
  • 要运行GoAgent还需要gevent和pyOpenSSL。可以手动安装,也可以通过pip来安装。推荐后者因为省事。
  • Python 2.7.8(无论是否x64)及更早的版本,没有自带pip。所以要去下载get-pip.py,然后用python运行这个脚本安装pip。
    ps:用get-pip.py下载到的pip.exe的版本,比Python 2.7.9里面带的要新一些。所以就算有自带我也会换掉它。

另一个重点来了:
有些版本的GoAgent里面对于crypt32.dll的加载代码在x64的Python中有问题,需要修改。改成像这样就可以了:
crypt32 = ctypes.WinDLL(u'crypt32.dll')
crypt32_handle = crypt32._handle
释放的时候要这样:
ctypes.windll.kernel32.FreeLibrary.argtypes = [HMODULE]
ctypes.windll.kernel32.FreeLibrary(crypt32_handle)
在前面还要:
from ctypes.wintypes import *
否则x64下会报错,因为HMODULE和long的长度在x64下不一样了。

我用的2.1.17的GoAgent中,对于crypt32.dll的加载代码还位于proxy.py中。最新的GoAgent已经移到proxylib.py里面了。什么时候移的我没有去考察过。代码改法可能略有不同,不过思路应该是一样的。

折腾好以后。把本机上的Python.exe复制一份改名成Python27.exe。接下来就可以把GoAgent自带的Python27.*给删掉啦。