Tuesday, March 19, 2013

(新旧版)对gaeproxy的“https代理”功能之分析和说明

本文系转载。是对gaeproxy安全性的分析,原文分为新版和旧版二篇文章,为了堵住阅读方便,一起汇总至本文。


(新版)对gaeproxy的“https代理”功能之分析和说明


旧版地址如下,普通用户无需阅读


http://blog.williamgates.net/2013/02/gaeproxy-analysis-deprecated/


经过我旧版文章分析后,gaeproxy的作者Max Lv很诚恳和大度地在项目主页和官方twitter帐号上解释了“https代理”功能,并将本地址作为说明放在项目主页上,故我将较为耸人听闻的旧版移至另一地址,在本地址重做了一份简单的说明。

对我的文章给作者带来的一些误解表示歉意。

再次声明,我相信作者从未也永远不会谋求窃取/篡改用户数据,作者提供的该功能是基于善意,我个人只是指出整个流程中的一个安全风险,并希望所有用户都有所了解之后自己选择是否要使用


  gaeproxy是GoAgent 在android上的客户端,作者是Max Lv,goagent在google code页面上将其作为android上使用goagent的解决方案来介绍。


  说明1:gaeproxy的“https代理”功能


  该功能实际上是将https的请求和回应通过作者提供的代理服务器 来进行代理,原理如下:

  没有打开“https代理”功能时,所有的流量都通过goagent服务器端,而goagent服务器端是部署在google appengine(GAE)上的,在客户和服务器之间,只有google的服务器存在,这个过程中只要你信任google的服务器,就是相对安全的。如图:

gaeproxy-goagent


  打开“https代理”功能时,https流量(往往是敏感数据,不过会被加密,并非明文)会通过作者提供的服务器代理,而不经过goagent的服务器端,这时候如果有人攻破了作者提供的服务器,在其上进行中间人欺骗,或者解密用户与目的服务器交换的数据(并非完全不可能),会给用户造成无法估量的损失。如图:

gaeproxy-https


  说明2:风险所在


  如上文所述,典型的goagent架构全程只通过google所维护的服务器来代理,虽然由于gae不支持https connect,所以在google的服务器上https请求会被解码并重编码(我理解如此,未必正确),所以不管是PC还是android上访问https网站,都需要导入证书。

  而gaeproxy作者提供的https代理不经过google的服务器,而是经过作者自己提供并维护的服务器,考虑到人力物力上的差距,作者维护的服务器在安全性上不如google的服务器来得可信,这就是我们所担心的。


  说明3:风险到底有多大


  实际上这种风险与你购买收费VPN SSH 代理的风险是一样的,甚至小于使用免费VPN、SSH的风险(包括著名的地下铁),存在恶意的VPN和SSH提供商能够给你带来更大的损害。我只是提出了整个流程中的一种可能性,而且不满于作者(当时)未明示这一事实而已。实际上我猜测是由于android设备上直接使用典型goagent模式时,https的性能比较差(我实测如此),所以作者才添加了“https代理”这一功能,并非出于恶意,相反自己花费了经费。

  实际上goagent的作者也承认,PC上典型的goagent架构也是不安全的,我们只是信任google的维护能力而已,并不是说goagent就是安全的。

  实际上翻墙 的方法无非两种,一种是通过各类代理,其中加入了一道甚至几道服务器后,信息被窃取/篡改的可能性显然会增加;另一种是通过对网络协议的修改,如西厢计划等小众方案,由于需要使用别人编写的软件,一样存在风险。没有一种翻墙方式是不增加信息被窃取/篡改的风险的,只能说一定程度上降低了被GFW 窃取/篡改的风险而已。


  总结:既然gaeproxy的作者明示了“https代理”功能的原理,我对这个软件及其服务并无进一步的意见,我推荐大家继续使用这个软件。就我个人而言,我不会继续使用“https代理”这个功能,但如果你选择继续使用,风险并没有多么可怕。


===================



(旧版)对gaeproxy的一些研究,兼谈Geek的社会责任


新版地址如下,不需要深入了解的用户请阅读新版


http://blog.williamgates.net/2013/02/gaeproxy-analysis/


该文中描述的原理仍然有效,而gaeproxy的作者已经在项目主页、官方twitter帐号上明确说明了存在这种情况,故“作者未对公众说明”已经不存在了。

作者Max Lv在这件事上表现出来的诚恳和大度令人钦佩,且已经在项目主页上放上了我原文的链接,所以特将原文移动至此,原地址仅放上我对原理的解释,不再有较为激进的内容。

对我的文章给作者带来的一些误解表示歉意。


核心提示:gaeproxy的“https代理”功能是由作者自建服务器提供,并非通过GAE转发,打开这个选项就意味着所有的https请求都会通过第三方代理服务器;由于种种原因,很多人实际上不能正常连接goagent服务器端,但手机端看起来还可以使用,是因为这个“https代理”功能让用户通过私人VPS进行了代理访问,而这些服务器到底是谁拥有、谁运营、安全性如何,我们完全一无所知。这一切,都没有在google code或google play页面告知用户。


  gaeproxy是goagent在android上的客户端,作者是Max Lv,goagent在google code页面上将其作为android上使用goagent的解决方案来介绍。使用这个软件给我带来了很多便利,但是不记得从什么时候开始,不打开其中的“https代理”选项就无法访问任何网站,打开该选项后也会有一些问题——比如G+客户端不显示图片(根据后文,实际上这时候我已经无法连接GAE了)。那个时候我懒得进行深入的研究,也就没有在意。

  从近期的某次升级开始,gaeproxy不再支持android 2.2系统,其项目主页上建议2.2用户使用0.19.1版。但是使用0.19.1版再也打不开“https代理”选项了,只要勾选这个选项就会一直提示gae代理启用失败;取消这个选项后,虽然显示gae代理启用成功,但任何网站(无论http还是https)都无法访问,于是我就开始了我的研究之旅:


  1、寻找官方签名版


  通过阅读Issue 231,我了解到“所有第三方编译版本都无法使用 Enable HTTPS Proxy 选项”,“打开此选项后,所有 HTTPS 流量将由远程服务器转发”,为了避免中间人攻击,gaeproxy会在启用这个功能的时候验证apk的签名。

  于是我就想下载一个官方签名版,我误以为google code上的是自动编译的版本,签名不正确,所以提交Issue 476,希望作者提供一个签名正确的版本,作者回应说:“官方版见 Downloads 页面,另外 HTTPS 模式已不支持 2.2 系统了,请依照 Wiki 自行导入根证书”,这时候我对后半句还不明白(看下文你就明白了),前半句倒是听懂了,google code上就是官方版,那为什么我不能打开“https代理”呢?

  搜索后发现,其实有不少所谓“汉化去广告版”都自称可以打开“https代理”功能,又看到这篇文章(需翻越观看),了解到gaeproxy验证签名其实就是访问一个页面(https://auth-gaeproxy.rhcloud.com/auth.php)并提供基于时间戳和apk签名的sig,我发现这个地址已经不能访问了,而最新版代码(github上gaeproxy/src/org/gaeproxy/GAEProxyService.java)里访问的是http://myhosts.sinaapp.com/auth-4.php。看来作者在版本更新过程中放弃了容易被墙的rhcloud,换成了sinaapp。那能不能自己编译一个版本,将代码里写死的rhcloud地址换成sinaapp的,再通过前面说的技巧骗过验证呢?

  我尝试向作者要一个修改验证地址的0.19.1版本(Issue 477),作者回应说“抱歉,0.19.1 已不支持 HTTPS 代理。解决方案:1. 升级你的 ROM 到 2.3。2. 使用伪造证书的 HTTPS 模式。”这时我对“https代理”这个功能的含义发生了怀疑——难道不是“对https流量也进行代理”的意思?经过翻阅,我终于看到了Issue 433,了解到了两个惊人的事实:

  (1)作者说“gaeproxy 的 https 代理有两种模式,第一种是由本地伪造证书由GAE转发的模式,第二种是由第三方服务器透明转发的模式。未开启「HTTPS代理」选项时默认使用第一种方式。第二种方式属于私有方式,由App中的置顶广告所得提供服务器资源。第二部分的服务器代码部署在SAE上,是出于可靠性考虑,SAE 对于开源应用有资源支持,不涉及收费问题。关闭「HTTPS代理」选项后,即是由GAE转发。”

  也就是说,“https代理”功能不是指“通过goagent代理https流量”,刚好相反,这个意思是“不通过goagent代理https流量”,而是通过第三方服务,这令人惊出一身冷汗——我们之所以信任goagent就是因为信任GAE,信任google,作者也说“所有 HTTPS 流量将由远程服务器转发,通过恶意修改这部分的代码可以轻松的获得所有经由 HTTPS 传输的敏感信息”,那我们的https访问原来一直是通过第三方代理的?作者从未明确告知过我们。

  (2)根据作者所说,那么这个功能如果不打开,应该也能正常访问http网站;通过导入证书,更应该能访问https网站。但实际上不只是我,很多人不打开这个功能什么网站都连接不上,也有很多人打开这个功能后图片显示不出来(http访问不正常),也就说明很多人使用gaeproxy这个软件,根本只是在用作者提供的第三方代理!


  2、寻找能正常连接GAE的版本


  了解了这些事实后,我再也不敢用“https代理”这个功能了,我导入了证书,只想用正常的goagent(我承认导入证书也有风险),但是无论什么版本的gaeproxy都无法使用,软件提示gae服务已启用,系统log及SuperSU的log中也看出iptables被正确写入,redsocks正确启动,goagent的1984端口也正常打开,但就是无法连上GAE(应该是goagent客户端出了问题),也就根本没法访问任何网站(见Issue 478)。我也更换了不同的goagent服务器端,连古老的goagent1.8.11/gaeproxy0.16.7和goagent1.7.8/gaeproxy0.15.6这两个搭配都试过,没有一个能够使用。

  经过翻看代码的history,发现0.20.2的更新内容是“fix issues on Android 2.2”,奇怪,作者不是说0.19.1之后不再支持2.2么?而且0.20.1的更新还写着“update to python 2.7.2 for new goagent”,作者称python 不能用于android 2.2(未见别处有这种说法),0.20.2居然还能在android 2.2上运行?事实证明就是可以,python版本就是2.7,安装后完全正常,可以访问http/https网站。

  这一版到底修改了什么产生了如此神奇的效果,看了代码也没明白。首先猜测是该软件一定要通过某种验证才能启用基本的功能,但该版本的验证地址虽然是sinaapp,但验证页面不对,所以也无法打开“https代理”功能,不过这个猜测至少能解释老版本goagent服务器端配老版本gaeproxy,当年能用现在却不行这一问题;另一种猜测是另有写死的地址(该作者在每一版代码中都有诸多写死的地址,甚至IP),但我简单浏览了几个版本的history,没发现关键所在;还有一种猜测是goagent客户端不使用python2.7就是不行,因为github上最早版本的goagent 1.7.8已经是python27环境了,但如果是这样,gaeproxy岂不一直只是一个第三方https代理?应该不可能。所以,这个问题有待进一步研究,可能需要作者去分析了。


  3、“https代理”功能研究


  我虽然不敢再用这个功能,但还是进行了一下研究,发现gaeproxy的原理实际上是通过iptables将设备上所有的请求都经redsocks转发,而redsocks在http流量上使用goagent生成的代理(1984端口),在https流量上,如果你不勾选“https代理”就仍然走1984,如果勾选的话会变成gaeproxy从sinaapp那个页面取到的一个服务器,53端口的代理,是美国的某VPS。通过显示客户地址的网页(比如https://ip-lookup.net)也可以看出,打开“https代理”选项,我们的地址变成了一台VPS的地址(我测试到的是一个123systems的VPS,臭名昭著啊)。

  据此可以了解到,作者通过这个验证页面不仅想防止中间人攻击,而且想防止他提供的免费代理被人滥用或者被封。实际上很好找——它就在redsocks.conf里面,只要你有一台2.3以上版本的设备,安装0.21.1版(0.21.2版在我的Nexus 10上无法使用,见Issue 479),连一次“https代理”就行了……经测试,也能用于无法打开该功能的旧版gaeproxy,但是我强烈建议不要这么做,更不推荐将其用于gaeproxy以外的地方。


  从整个研究过程可以看出,作者其实很早就发现android设备上goagent的证书无法很好地被使用(即使导入了还有问题),而且在android上goagent对https的转发性能也很不理想,所以他在0.10.2版本就引入了第三方服务,当时是用FreeSocksProxy.org;后来又改为了这种自建在VPS上的代理。其实我很惊讶53端口的代理能带来这么强劲的速度和承载能力——coolapk上约467750次下载,google play上100,000 – 500,000次下载,不知道作者到底用了多少服务器来做这个“https代理”。

  我很佩服作者的这种公益精神和技术能力,但是从未在任何软件介绍和项目页面说明这一点,就显得非常不恰当。从学生时代,不少Geek朋友就有这种理念——我们写我们的,用户都是傻x,只管用就好了。实际上我赞同用户有权也应当是傻瓜,他们应该不用向我这样研究一个软件的代码才能使用它,面对普通用户的软件应该是轻松易用的;但是这种轻松附随了一个要求——用户有选择权。用户虽然可以傻瓜地使用软件,但有权在涉及自己切身利益——特别是隐私问题的时候有知情权和选择权。

  独立的软件作者写东西往往没有金钱回报,研究问题也纯属兴趣和公益心,但是只要你自认是Geek,那么你就一样有社会责任,这种责任不仅要求你做对社会有益的事情,而且要求你将这种“你自认为对社会有益的事情”公开出来,由社会监督;这种责任不仅要求你提供给用户好的东西,还要求你允许用户自行评判“你自认为好的东西”。这也是自由的要义——精神和意志上的自由才是真正的自由,受蒙蔽而使用免费的“自由软件”,蒙蔽用户而发布“自由软件”,均非真正的自由。

  也许有人不同意,免费为你提供服务,你放下筷子还骂娘?殊不知信息权力已经成为一种真正可以影响社会的权力,比如google,它免费为世界提供Gmail服务,虽然我们没有支付任何费用,但它有义务保障用户的数据和隐私安全,而且有义务接受全世界各种眼光(包括黑客)的监督;比如国内的很多商业和半商业网站,明文存储的密码给无数人带来了损失,正是因为信息权力不受监督所致——一方面是政府要求明文存储密码的权力,一方面是网站安全流程设计上的权力,均不受公众监督。任何不受监督的权力必然导致腐败,即使这种腐败是一种极为特别的形式——掌握权力者本身甚至可能并未参与,但绝不意味着他可以置身世外。在开源领域,作者的代码虽然已经公开,但仍有责任向公众介绍软件的机制,特别是涉及隐私、涉及代码外黑箱的部分。

  在gaeproxy这个软件的问题上,作者从未积极地向公众介绍其“https代理”功能的原理,而且一直严重这一误导性的名称,并且在开源的代码外架设有验证服务器、代理服务器,这是多个黑箱,其中有一个留有陷阱就会让数万用户产生不可估量的损失。即使作者本身不参与窃取隐私的行动,这种不透明的流程仍然可能被人破解及利用。实际上了解到这个软件使用的第三方代理地址易如反掌,而一旦攻破这些VPS,获取代理的log后就能得到不少有价值的隐私信息,如果进一步将这些代理服务器用于中间人攻击,后果不堪设想。

  即使我们无比相信开源软件的作者,我们也无法相信不受监督的权力。请将自由还给自由软件的用户。





※ 除声明转载,美博园文章均为"原创",软件版权归原作者,转载请以上面超链接注明来源

如喜欢本站请关注: Email订阅美博园 | RSS订阅美博园 | 翻墙Google+ | 美博园翻墙Facebook | 翻墙Twitter






via 美博园 http://feedproxy.google.com/~r/allinfa/~3/QMRx9OEjxT4/gaeproxy-https-proxy-analysis.html

No comments:

Post a Comment