Potatso原理解析

      1 Comment on Potatso原理解析

更新:现在可用的Potatso源在这里:https://github.com/haxpor/Potatso

其实对于iOS而言,之前有shadowsocks-iOS这个项目,我有段时间也看了这个项目,当时没有仔细看源码,只是想把它跑起来看看,折腾了一阵虽然能够跑起来了,但是并不起作用。后来在美区下载了这个app试用了一下,还是只能在应用存活期间提供代理服务,缺陷是很明显的。clowwindy在apple宣布开放networkExtension后在这个页面讨论了一下network extension的使用方法,最后大批的留言让人感动。

前几天,icodesign开源了Potatso,我看了几天源码,了解了一下大概流程:

一、需要向apple申请networkExtension的使用权限,拿到权限entitlement文件之后,需要安装一个Xcode网络扩展模版插件,地址在: /System/Library/Frameworks/NetworkExtension.framework/Resources/NEProviderTargetTemplate.pkg。

二、 安装完之后可以在Xcode新建Application Extension模版。此段参考iOS 9 VPN API – The Definitive Guide to Network Extension API NEPacketTunnelProvider and NWUDPSession。网上有对应的中文版,这里就贴英文原文吧,mac sierra上这个安装包找不到了,官方推荐的做法在这里https://forums.developer.apple.com/thread/65265

三、之前提到过shadowsocks-iOS被系统杀死后就不能提供代理服务了, 上一条提到的Application Extension就突破了这一局限,即使app被杀死,Application Extension依然会在后台运行。持续为设备过来的数据提供代理。下面就说一下代码层面上到底是怎么实现的

四、Potatso首先会将用户的shadowsocks服务器信息存起来,用户选中某项shadowsocks配置后点击连接,Potatso会首先调用Manager.swift的”regenerateConfigFiles”方法,保存了4个配置:

  • 保存用户定义的DNS;
  • 生成一个antinat服务器需要的XML配置文件并保存起来,antinat是一个socks服务器,用来将需要代理的socks流量导向设备上和shadowsocks服务器连接的端口;
  • 生成连接shadowsocks时需要的信息,这些信息被包装为一个NSDictionary保存起来;
  • 生成了一个http的过滤规则供稍后privoxy使用,provixy是一个http代理,工作在稍后建立起来的VPN连接上,因此provixy截获的流量是IP数据包,处于L3,通过过滤规则进行过滤,对于需要代理转发的通过Tun2socks将IP数据包转为socks流量转发向antinat socks服务器,由antinat转发到设备上的shadowsocks端口,至于为什么不直接发向设备上的shadowsocks端口,我特地请教了一下Potatso的作者,作者表示,由于项目遗留原因,所以现在暂时是这样处理,以后会更新,直接转发给设备上的shadowsocks端口,让我们拭目以待。当开启全局代理的时候provixy可以不需要经过规则过滤,直接把数据包发给设备的shadowsocks端口。关于privoxy著名博客编程随想上有一篇文章介绍的很好。另外这篇文章Socks代理转VPN解释了一下Tun2socks和android-ss,我觉得也写的很好。

五、保存了以上信息后通过manager.swift中的loadAndCreateProviderManager方法创建一个默认的VPN连接,实际上这个VPN连接没有VPN的具体信息,只是在调用完这个方法后,系统会调用Application Extension中PacketTunnelProvider的“- (void)startTunnelWithOptions:(NSDictionary *)options completionHandler:(void (^)(NSError *))completionHandler”方法,这个时候处置权就交到了Application Extension中,这里才是重头戏。

六、 Application Extension获得控制权之后。

  • 先开启设备与shadowsocks服务器的连接,连接完毕之后,获得设备上shadowsocks端口并保存起来
  • 启动privoxy,监听本地一个任意端口,监听完成之后将端口保存起来
  • 启动antinat,将本地任一端口与本地shadowsocks端口连接起来,连接完毕后将端口保存起来
  • 用之前保存的privoxy端口开始一个VPN连接,这个时候才是真正把VPN连上了。实际上这个连上的VPN的服务器地址也是在本机上,目的只是为了截取设备流量,进行后续操作

七、所以VPN端口也就是privoxy监听的端口,privoxy不断的处理设备过来的数据。完成代理动作。

最后,我将Potatso的代码注释了一下放在这里.有兴趣的可以看看,由于privoxy和antinat涉及到了网络底层我并不熟悉,可能有误解,也希望大家能不吝赐教。

1 comment on “Potatso原理解析

Leave a Reply

Your email address will not be published. Required fields are marked *