写在前面
首先,这是一个简单的APP,拦截手机的流量,代理。其中ipv4和ipv6以及dns都要转发到自己的节点。期间就遇到了ipv4的可以代理,但是ipv6的就不可以,这就很蛋疼了。搞了一周,记录下来,给需要的人
如果标题的前半句不明白,可以看这个
如果ipv6也不明白,了解下v6格式的地址就好
关于DNS污染的问题,这里也不涉及,需要的话可以自己研究,挺简单的
代码都是只记录了核心的配置代码
先看下ipv4正常代理的代码
self.vpnSetting = [[NEPacketTunnelNetworkSettings alloc]initWithTunnelRemoteAddress:HOST_NAME];
NSString *virtual_ip = settingSet[0];
NSString *dns_ip = settingSet[1];
NSString *mtuStr = settingSet[2];
int mtu = mtuStr.intValue;
self.vpnSetting.MTU = mtu > 0 ? @(mtu) : @(VPN_MTU);
NEDNSSettings *dnsSetting = [[NEDNSSettings alloc]initWithServers:@[dns_ip?dns_ip:@"8.8.8.8"]];
self.vpnSetting.DNSSettings = dnsSetting;
if (virtual_ip.length > 0) {
self.vpnSetting.IPv4Settings = [[NEIPv4Settings alloc]initWithAddresses:@[virtual_ip] subnetMasks:@[@"255.255.255.255"]];
self.vpnSetting.IPv4Settings.includedRoutes = @[[NEIPv4Route defaultRoute]];
}
settingSet 是一个存放了相关信息的数组,这不是重点,重点是最后创建的self.vpnSetting对象要通过- (void)setTunnelNetworkSettings:(nullable NETunnelNetworkSettings *)tunnelNetworkSettings completionHandler:(nullable void (^)( NSError * __nullable error))completionHandler
函数设置给extension来进行流量的拦截
至此,已经正常拦截了流量和正常代理
然后就是ipv6的拦截了。按照苹果文档中ipv4的写法,应该是这样的
self.vpnSetting.IPv6Settings = [[NEIPv6Settings alloc]initWithAddresses:@[virtual_ip_v6] networkPrefixLengths:@[@128]];
NEIPv6Route *route = [[NEIPv6Route alloc]initWithDestinationAddress:@"::" networkPrefixLength:@128];
self.vpnSetting.IPv6Settings.includedRoutes = @[route];
或者这样的
self.vpnSetting.IPv6Settings = [[NEIPv6Settings alloc]initWithAddresses:@[virtual_ip_v6] networkPrefixLengths:@[@128]];
self.vpnSetting.IPv4Settings.includedRoutes = @[[NEIPv6Route defaultRoute]];
但是!!!!!
这个时候,v4的数据包可以获取到,但是v6的就不行,就是那个packetflow 的readhandler 函数读不到,说明没有拦截到;仅仅配置ipv6的拦截的时候,状态栏的VPN图标都不会出来,这也说明了ipv6拦截失败。
还可以通过Mac 自带工具“控制台”查看extension进程打印的日志,如下图,
截屏2020-05-06上午10.26.20.png
上图的日志只能说明你的代码配置了啥,但是并不能表示这就正常拦截了
于是乎,我就各种搜资料和尝试
最后发现如下设置即可
self.vpnSetting.IPv6Settings = [[NEIPv6Settings alloc]initWithAddresses:@[virtual_ip_v6] networkPrefixLengths:@[@128]];
NEIPv6Route *route = [[NEIPv6Route alloc]initWithDestinationAddress:@"::" networkPrefixLength:@1];
NEIPv6Route *route1 = [[NEIPv6Route alloc]initWithDestinationAddress:@"8000::" networkPrefixLength:@1];
self.vpnSetting.IPv6Settings.includedRoutes = @[route,route1];
既然defaultRoute不好使,那我们就让路由全覆盖,也能达到一样的目的,我的目的是拦截所有路由的流量,倘若你的需求就是拦截某些路由,那就没有我这个问题了,直接设置你的路由就好
如果有
nw_path_necp_update_evaluator_block_invoke [4AD2873A-2B7D-4F5B-8AD8-994186AD4EF8 <NULL> generic, indefinite]
path: satisfied (Path is satisfied), interface: pdp_ip0, scoped, ipv4, ipv6, dns, expensive能看到这样的这样的信息,表示对应tun建立好了,可以读取数据了
总结
感觉这是苹果的一个bug啊,为啥像ipv4那样就不好使呢,最后拐个歪达到目的了,但是真的是坑啊。如果是我哪个地方错误,麻烦您一定要指出来,共同进步,谢谢
You obviously want to create a full tunnel. You do this by configuring your tunnel with an NEPacketTunnelNetworkSettings object whose
iPv4Settings
property references an NEIPv4Settings object whoseincludedRoutes
property is set toNEIPv4Route.default()
(and similarly for IPv6). Once your tunnel starts the system sets it as the default route, and so it sees all outgoing traffic.
网友评论