V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
BetaGo
V2EX  ›  分享创造

分享开发 iOS 和 Mac 全新 VPN 的艰难历程,顺带求帮忙测试

  BetaGo · 2016-03-18 15:27:15 +08:00 · 24759 次点击
这是一个创建于 3202 天前的主题,其中的信息可能已经有所发展或是发生改变。

故事的起因

2015 年苹果在开发者大会上,首次提到 iOS 9 和 OSX 10.11 将公开底层网络接口给第三方 developer ,这组新的接口叫做 Network Extension API 。简单地讲,苹果将在 iOS 和 OSX 里植入虚拟网卡,允许第三方 app 控制虚拟网卡并修改系统路由表。

Imgur

在此之前的 8 年里,苹果从未公开过这组 API 。在没有 jailbreak 的 iOS 上,只有三家公司曾做到过控制系统路由表: Cisco, Juniper ,以及 iOS 6.0 之后的 OpenVPN 社区。他们能做,因为他们和 Apple 签了某种协议,从而获得苹果定制的 entitlement 。

现在,苹果决定开放这个权限给全世界。

于是技术狂悄悄动手了。 ss 在 7 月中开始 coding 全新的 proxy 代码,可惜 8 月底 git repo 被清空了。那时基于新接口的 ss 还没完工。

Imgur

为苹果免费 debug 的艰难历程

我和 ss 几乎同时开始做这块。不过,我的打法是开发全新 VPN 协议,这和 ss 走 sock5 代理是两条路。

要调用 Network Extension ,先要问苹果拿一个特殊的 entitlement 。否则只能得到无止尽的 NSError 。拿这个许可大约花费两周时间。

Imgur

我们很早就在Android 上开发了新的 VPN 协议并投入使用。

原以为拿到许可之后,简单地把 C 代码搬到 XCode 里,再加个 OC 或 Swift 的 UI 层就搞定了。后来的经历证明苹果的坑很多,官方文档和 stackoverflow 对这块技术也接近空白,一切全靠试错。

第一个坑, NWTCPConnection 不 work

开篇提到的苹果开发者大会 Session 717 ,当时 Tommy Pauly 演示了一个 swift 写的 vpn demo ,用的是 NWTCPConnection 。三个月后苹果放出来的 sample code 也用了 NWTCPConnection 。

Imgur

But, 实测下来, NWTCPConnection 根本不 work , connect 一直 timeout ,不知道 Tommy Pauly 当时怎么做的。

Workaround 还是有的,就是用 C 开 TCP socket ,然后用 BSD 的 kqueue 自己写异步 IO 。

第二个坑, NWUDPSession 每个包最多只能传送 1472 字节

这很容易理解,大部分 WiFi 环境下 iOS 网卡 MTU 配置成 1500 ,减掉 IP header 共 20 字节,再减掉 UDP header 共 8 个字节,剩下数据部分 1472 个字节。

但是 iOS 的行为非常古怪。

之前我们在 Windows, OSX , Linux 和 Android 上获得的经验是这样的,系统 IP 层会自动分解超大的 UDP 数据,这个过程叫 fragment ,送到另一端时 IP 层又自动合成出原始 UDP 包,这个过程叫 defragment 。整个过程对应用层 app 是透明的。所以在其他几个操作系统上用 UDP 传送超过 MTU 的数据不会有问题。

iOS 呢?实测下来, iOS 不会自动 fragment/defragment ,也不会把超过 MTU 的包整个扔掉,而是传送 1472 字节给应用层。

于是从 network extension 拿到的只是部分数据,当然无法跑通 VPN 。这问题花了几周时间才搞清楚。

强烈要求苹果改改 iOS TCP/IP 内核代码,起码也要和 OSX 一样吧。

第三个坑, iOS Provision Profile 带来的问题

终于, iOS 上搞定了,自己用的很开心。

交给苹果 review ,等到 D 疼,终于 approve 了。从 app store 下载安装,居然不能用!

dev 版本是可以用的, production 版本不能用,问题在哪里?

先连夜赶工, VPN 核心模块切换到老代码,然后加个 switch ,默认关闭。

Imgur

接下去,找始作俑者,也就是开发 Network Extension 的那位大神。

Imgur

非常不幸的是,苹果在安全保密方面极端严格。通过这个渠道去询问技术问题,绝对无可奉告。

上论坛试试吧。

Imgur

最终我们得到大神回复,删掉本机所有 profile ,然后新建一组 profile ,重新 build ,试试!

我们照做了,搞定!

不过坦率承认,这招我们时常用,在此贴之前,不管怎么弄 profile 都没用。苹果微调了啥呢?

更艰难的 Mac 之旅

有了 iOS 的 code base , port 到 Mac 岂不是秒杀?

Yes and No.

在 UI 层,大部分工作就是把 UI 改成 NS ,比如把 UIView 改成 NSView 。这要多谢 Cocoa 和 Cocoa Touch 结构基本相同。

但底层的 app extension 里还是有细节上的差异。要注意, Xcode 不会显示 app extension 里的 NSLog ,得这样看。

Imgur

又瞎忙了 N 天,看起来差不多了。在自己 Mac 上跑的甚好。

事后证明,还需要被折磨 6 周,才能最终把它推到 Mac app store 。

这次,还是 provision profile 的问题。见图。

Imgur

原来,调用 Network Extension 要求先取得苹果的许可,然后可以新建一个 provision profile 使用 network extension 扩展 entitlement ,其中包括三种权限,分别是:

  • HotspotHelper ,允许 app 控制 wifi 连接,这是 wifi 万能钥匙这种 app 必须的功能
  • AppProxy ,让第三方 app 在应用层过滤其他 app 的网络通信,适合做内容过滤和监控
  • PacketTunnelProvider ,这是 VPN 相关的,在 IP 层拿到虚拟网卡和路由表控制权

但是, OSX 不支持 HotspotHelper ,所以, Xcode 打包项目后做 validation 时报错了。

解决方案呢?

先依靠自己的力量,找遍所有相关资料,一个一个试,无解。

然后,去 Apple 开发者论坛发帖,无解。

最后几经周折,在确信这问题 99%出在苹果的前提下,硬着头皮找到苹果 Core OS 团队的人。

Imgur

嗯,进了他们的 ticket system ,也算为 OSX 和 Network Extension 做点贡献了。

然后,等。

顺便说下, OSX 里有个 pluginkit 命令,开发 app extension 时要用到。

列出所有 plugin

pluginkit -m -A

强制安装 plugin

pluginkit -a <filename>

强制删除指定的 plugin

pluginkit -r <filename>

在开发阶段, Xcode 有时不能正确安装或刷新 app extension ,此时就要手工操作了。

完工

后来, Apple fix 了这个问题。幸好,不需要升级 XCode 。

我们有幸成为全球第一个,也是唯一一个遇到这个问题的人。

这是 Mac 版成品的样子。

Imgur

这是 iOS 版。

Imgur

整个开发过程零零碎碎历经几个月。我们总体感觉是,苹果开放的 Network Extension 接口没有达到最成熟的阶段,可能的原因是苹果开发流程很封闭而且环节很多,涉及 Apple Developer Program 里各种权限,涉及 XCode ,还有就是 code ,任何一环出错都会造成产品无法上线。

而且我们认为,苹果自己的 Core Network 部门并没有像第三方 developer 一样从头到尾把流程跑一遍,才会出现各种细节问题。

Anyway , we did it 。

现在,我们需要更多人来测试这个产品。当时 iOS 那个 profile 引发的 bug 至今没有得到苹果的官方解释。同时,在 Mac 上,我们也发现 pluginkit 不是每次都能自动加载 app extension 。

任何新发现的问题我们都会及时和苹果 Core Network 团队沟通,相信大部分都是他们的错。

如果你有 iOS 9.0 和 OSX 10.11 以上的设备,正好需要完全免费的 VPN ,请试用这两个 app 。

iOS: https://itunes.apple.com/us/app/hideme-free-vpn-proxy-unlimited/id879905781?ls=1&mt=8

Mac: https://itunes.apple.com/us/app/hideme-free-vpn-proxy-unlimited/id1084098222?ls=1&mt=12

70 条回复    2022-03-18 19:17:41 +08:00
metrue
    1
metrue  
   2016-03-18 19:01:51 +08:00 via Android
坚持下来了,结果是好的。
dangyuluo
    2
dangyuluo  
   2016-03-18 20:01:34 +08:00
艰难困苦,玉汝于成
KillAd
    3
KillAd  
   2016-03-18 21:57:22 +08:00
认认真真写了这么长不容易
我也认认真真读完了
楼主辛苦
bindiry
    4
bindiry  
   2016-03-18 23:13:33 +08:00
楼主能给个联系方式吗?想跟你谈谈合作,谢谢。 bindiry at gmail
Malygos
    5
Malygos  
   2016-03-19 03:09:49 +08:00 via iPhone
楼主的摸索过程,值得参考学习~ 感谢🙏
goodbest
    6
goodbest  
   2016-03-19 08:07:55 +08:00
>We are the first team in the world building VPN solutions on top of Apple ’ s new network extension, with this new technology you will be able to get the best VPN performance and security not seen before.

楼主你说自己是第一个这样不妥当吧。
我查了一下你们是从 1.7 版本也就是 20151219 开始说支持 iOS9 Network Extension 的。
而大名鼎鼎的 Surge 发布是 20151025 。
BetaGo
    7
BetaGo  
OP
   2016-03-19 10:13:04 +08:00
@goodbest surge 不是 vpn ,工作在 proxy 层, apple review 时可以省掉很多麻烦,同样 shadowsocks 也不是 vpn ,具体啥区别可以自己 google vpn vs socks5
joysuns
    8
joysuns  
   2016-03-19 10:54:29 +08:00
这 vpn 是免费的,可以用自己的 SS 或者 VPN 账号吗
ajan
    9
ajan  
   2016-03-19 11:02:04 +08:00
mac 上用不了
ajan
    10
ajan  
   2016-03-19 11:02:28 +08:00
貌似又好了
streamgo
    11
streamgo  
   2016-03-19 11:10:01 +08:00
向所有程序员们致敬!
bawn
    12
bawn  
   2016-03-19 12:46:55 +08:00
赞!!!!!!!!!
junyixin
    13
junyixin  
   2016-03-19 14:28:44 +08:00
mac 上刚开始的时候打开一直转,然后第二次打开能连,但是比较慢,过一会儿才会稳定
vincentxue
    14
vincentxue  
   2016-03-19 14:40:40 +08:00
这么难做出来的竟然免费,良心。
vincentxue
    15
vincentxue  
   2016-03-19 14:43:08 +08:00
那这么说是不支持 ss 的了?
DT27
    16
DT27  
   2016-03-19 15:21:09 +08:00
Mac 第一次运行列表没加载,也连不上。
第二次运行正常了。
但是试了好几个服务器,速度太慢了= =、
nodeny
    17
nodeny  
   2016-03-19 18:06:21 +08:00
我和楼上的情况基本上差不多,
Mac 第一次运行节点列表加载不成功;
退出后第二次运行就正常了;
试了 JP 和 HK 节点,速度比较慢,但还算稳定;

总之,谢谢楼主了,你的努力非常棒!
denniszhaolk
    18
denniszhaolk  
   2016-03-19 18:07:07 +08:00 via iPhone
请问有计划开源协议吗?
ericFork
    19
ericFork  
   2016-03-19 18:36:25 +08:00
@denniszhaolk 我觉得答案是显而易见的……
denniszhaolk
    20
denniszhaolk  
   2016-03-19 19:27:52 +08:00
@ericFork 好吧。。。不过他这个 VPN 居然也把 UDP 和 icmp drop 了?
jseanj
    21
jseanj  
   2016-03-19 19:33:57 +08:00
请教一个问题:如果用 NEPacketTunnelProvider 的话,返回的数据是 IP 层的数据包,想拿到应用层的数据的话是否需要自己解包?这块一直没有想明白 surge 是怎么做的。如果使用 NEAppProxyProvider 倒是可以直接拿到传输层的数据,不过貌似苹果只能让用于受控设备。
weihongchang
    22
weihongchang  
   2016-03-19 19:39:21 +08:00
试过 了, 速度很慢,翻 也没成功,
g67261831
    23
g67261831  
   2016-03-19 19:56:21 +08:00
Surge 让我这个非 ios 开发人员都对 NE API 感兴趣了。
jseanj
    24
jseanj  
   2016-03-19 20:06:10 +08:00
Session 717 中演示的 demo 应该是 udp 传输,而且现在 NWTCPConnection 是可以 work 的...
hydyy
    25
hydyy  
   2016-03-20 00:09:09 +08:00
mark@@@@
alexsunxl
    26
alexsunxl  
   2016-03-20 00:45:22 +08:00
好厉害,这解决问题的能力真是让人惊叹
Monad
    27
Monad  
   2016-03-20 08:12:31 +08:00
界面上还有些问题, iOS 连接 /断开 vpn 有时候按了没有反应 vpn 并没有对应的断开 /重新连接
另外切换 vpn server 的时候没有自动重新建立 vpn 连接 没有引导的话可能会让人产生错觉以为切换了服务器地址
另外以后的收费模式是怎么样的?单纯依赖广告吗?后续是否会有支持 SS 的想法?
cute
    28
cute  
   2016-03-20 09:18:08 +08:00
@jseanj tun2socks
123s
    29
123s  
   2016-03-20 10:30:57 +08:00
大家都说免费不好,搞到我也不敢用。是养肥了再宰吗?还是一开始说好比较妥当。
Unlimited Free VPN Proxy 是真的 Unlimited Free ?
kjlist
    30
kjlist  
   2016-03-20 14:15:58 +08:00
楼主辛苦
qa52666
    31
qa52666  
   2016-03-20 16:12:49 +08:00
牛逼
sangmong
    32
sangmong  
   2016-03-20 16:39:20 +08:00
pagxir
    33
pagxir  
   2016-03-20 23:26:06 +08:00 via iPad
一直用 andriod 手机开热点给 iPad 翻墙,简单可靠。
snhfly
    34
snhfly  
   2016-03-21 09:40:09 +08:00
https://www.flyvpn.com 我用的是這個商用的 一直不錯
googya
    35
googya  
   2016-03-21 10:00:21 +08:00
Mac 上连不上
googya
    36
googya  
   2016-03-21 10:02:36 +08:00
接 35 楼, 退出, 再进 就可以连上了
nocoo
    37
nocoo  
   2016-03-21 11:07:49 +08:00
俩字,牛逼
sean10
    38
sean10  
   2016-03-21 12:22:18 +08:00 via iPhone
赞,在未越狱设备也能系统代理,这个应该是第一家了吧
badcode
    39
badcode  
   2016-03-21 12:50:23 +08:00
收藏和感谢,楼主辛苦了
touzi
    40
touzi  
   2016-03-22 09:27:44 +08:00
牛逼, 技术沉淀.
breestealth
    41
breestealth  
   2016-03-22 10:10:26 +08:00
比较期待放出可以自己搭建 VPN 的方法。毕竟 VPN 这种东西,还是比较敏感的。
LeoDev
    42
LeoDev  
   2016-03-22 11:31:24 +08:00
致敬探索精神!
hotpki
    43
hotpki  
   2016-03-22 15:45:27 +08:00
MAC 上第一次连接无反应,退出程序,再次连接成功。功能很好,界面约显简陋。
forgetandnew
    44
forgetandnew  
   2016-03-22 16:54:03 +08:00
期待开源
sean10
    45
sean10  
   2016-03-23 11:00:35 +08:00 via iPhone
@sean10 我错了,这个这只是调用 ios 自身的设置,没有 surge 的全局 socket 代理功能
cwhong4399
    46
cwhong4399  
   2016-03-24 09:25:01 +08:00
膜拜中……顺便收藏了
kaynewbie
    47
kaynewbie  
   2016-03-24 10:08:18 +08:00
赞一个!
imSam
    48
imSam  
   2016-03-24 11:46:45 +08:00
楼主需要设计师伙伴么?算我一个
heygu
    49
heygu  
   2016-03-27 13:38:55 +08:00
赞,能自定义服务器就好了
yyyle
    50
yyyle  
   2016-03-29 16:37:55 +08:00
佩服楼主的死磕精神 就是 APP 图标有点对不起观众~
jacinto
    51
jacinto  
   2016-03-30 10:05:14 +08:00
谢谢楼主,能用。
lawder
    52
lawder  
   2016-04-03 13:39:42 +08:00
赞下 LZ 坚持不懈的探索精神。问下有开源的计划吗?
rootsir
    53
rootsir  
   2016-04-23 13:56:34 +08:00
Surge 出来好久了 为什么楼主走了这么多艰辛历程
ji4ozhu
    54
ji4ozhu  
   2016-05-03 21:44:01 +08:00
楼主有木有联系方式。想联系一下楼主~
hellboys
    55
hellboys  
   2016-05-10 17:46:12 +08:00
ne 开发挺还是有不少的坑的,不过一点一点趟吧, 我们的已经也上线了 https://itunes.apple.com/cn/app/id1032660607
WildCat
    56
WildCat  
   2016-08-02 07:57:20 +08:00 via iPhone
楼主那个表你当时是怎么填写的?我发邮件一个多月了没回复
hanangellove
    57
hanangellove  
   2016-10-08 21:57:02 +08:00
现在这个已经不好用了。
noinlj
    58
noinlj  
   2016-10-09 22:50:39 +08:00
qinxianjun163
    59
qinxianjun163  
   2016-12-11 11:27:12 +08:00
各位大神,为啥在扩展里面的 NSLog 在控制台上面不显示呢?如何在扩展里面做调试呢?
igeeker
    60
igeeker  
   2016-12-17 16:06:39 +08:00
支持这种钻研精神!
immueggpain
    61
immueggpain  
   2017-01-19 17:14:56 +08:00
https://vpn.gwent.win/
immueggpain
    62
immueggpain  
   2017-01-19 17:16:41 +08:00
抱歉发错了。。。。 o(╯□╰)o
ljs999
    63
ljs999  
   2017-06-28 16:54:35 +08:00
需要个能输入自己服务器地址,账号密码的 vpn 客户端,老大可以改下你的软件么
konakona
    64
konakona  
   2017-07-13 19:59:13 +08:00
mac os 一打开就 crash 了。
10.12.5
ZiYe000
    65
ZiYe000  
   2017-12-02 16:03:41 +08:00
楼主您好,我现在也正在做 vpn 的东西,需要用到 NWTCPConnection,我的 vpn 建立也是进了第一个坑。NWUDPSession 是可以正常运行能从虚拟网卡拿到数据也能建立起 vpn 的,但是用 NWTCPConnection 就建立不起来 vpn。不知道为什么。我现在只是想建立 vpn 然后从虚拟网卡里拿到数据看看而已。但是这步用 NWTCPConnection 都实现不了。请求楼主 帮助。不甚感激。
itlr
    66
itlr  
   2018-05-31 07:39:46 +08:00
Jamecvr
    67
Jamecvr  
   2018-11-29 18:54:08 +08:00
你好,
为了你 MAC 上的 VPN 问题我想推荐以下的网站。
https://www.vpnranks.com/best-vpn-for-mac/ ( English)
https://www.vpnranks.com/zh-hans/mac-vpn/ (中文)
hyrz
    68
hyrz  
   2019-03-21 12:29:43 +08:00 via Android
sjinying
    69
sjinying  
   2020-04-16 20:47:42 +08:00
我在中國如果要 MAC 上 VPN 的話,需要用中國 VPN 那我在台灣的話需要用 VPN 台灣 嗎?
我一個朋友給我介紹的以下的網站:
https://www.taiwanvpnz.com/
這個網站安全嗎?
HAOKE
    70
HAOKE  
   2022-03-18 19:17:41 +08:00
5000 找人二开,能不能联系一下做一个小火箭 v2 协议? tg:helloworld000007
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1178 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 29ms · UTC 18:12 · PVG 02:12 · LAX 10:12 · JFK 13:12
Developed with CodeLauncher
♥ Do have faith in what you're doing.