NETunnelProvider 在 iOS 14 上停止接收数据包?

Oma*_*arj 6 networking udp swift networkextension ios14

我有一个Local VPN使用“ NETunnelProvider/ NetworkExtentsion”的应用程序,在我的解决方案中,我在设备本身上创建了一个拆分隧道来跟踪 DNS 请求,使用NEKit我能够查看数据包内部并根据目标地址过滤正在进行的请求(let's call ita UDP listener for DNS requests).

这个解决方案在 iOS 13.7 及更低版本上运行良好,最近苹果发布iOS 14,我的解决方案停止工作,VPN连接仍然建立,但用户无法访问任何网站,我调试了代码并发现networkExtision没有收到任何packets来自用户活动的信息.

我正在使用CocoaAsyncSocket图书馆。

func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
    
    let host = GCDAsyncUdpSocket.host(fromAddress: address)
    
    guard let message = DNSMessage(payload: data) else {
        return
    }
    
    guard let session = pendingSession.removeValue(forKey: message.transactionID) else {
        return
    }
    
    session.realResponseMessage = message
    session.realIP = message.resolvedIPv4Address
    
    let domain = session.requestMessage.queries[0].name
    
    let udpParser = UDPProtocolParser()
    udpParser.sourcePort = Port(port: dnsServerPort)
    udpParser.destinationPort = (session.requestIPPacket!.protocolParser as! UDPProtocolParser).sourcePort
    udpParser.payload = session.realResponseMessage!.payload
    
    let ipPacket = IPPacket()
    ipPacket.sourceAddress = IPAddress(fromString: dnsServerAddress)
    ipPacket.destinationAddress = session.requestIPPacket!.sourceAddress
    ipPacket.protocolParser = udpParser
    ipPacket.transportProtocol = .udp
    ipPacket.buildPacket()
    
    packetFlow.writePackets([ipPacket.packetData], withProtocols: [NSNumber(value: AF_INET as Int32)])
}


let dummyTunnelAddress = "127.0.0.1"

let dnsServerAddress = "8.8.4.4"
let dnsServerPort: UInt16 = 53

// Tunnel confg.
let tunnelAddress = "192.168.0.1"
let tunnelSubnetMask = "255.255.255.0"
Run Code Online (Sandbox Code Playgroud)

关于触发“本地网络权限”这不是这里的问题(我认为我的解决方案不需要这个权限),根据苹果文档,一些应用程序需要请求本地网络权限,我将权限添加到info.plist但本地不会触发网络权限。

========================== 更新 #1 ====================== ========

我发现我能够捕获数据包并做我自己的事情然后将数据包写回 packetFlow packetFlow.writePackets,但在 iOS 14 浏览器上不加载网站并继续加载直到显示超时。

在此处输入图片说明

小智 0

我有一个想法,或许也可以为你提供一个解决方案。从 iOS 版本 14 开始,C 函数 connect() 开始在必须运行 VPN 的网络扩展中失败,并显示来自内核的以下日志消息:

Sandbox: VPN Extensio(8335) deny(1) network-outbound*:<port #>
Run Code Online (Sandbox Code Playgroud)

但是,它确实可以在应用程序中使用,如果您在扩展程序中需要它,那么它几乎没有用处。GCDAsyncUdpSocket 是一个薄层,它在幕后调用 socket() 和 connect()。

NWConnection 确实可以在网络扩展中工作,如果可以移植您的代码并且您不需要实际的套接字描述符,那么它应该适合您。但如果您必须支持 ios 12 以下的设备,则必须有条件地进行编译。