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

问题描述

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

解决方案在iOS 13.7及更低版本上运行良好,最近是Apple版本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"

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

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

我发现我可以捕获数据包并做自己的事情,然后将数据包写回packetFlow packetFlow.writePackets,但是在iOS 14上,浏览器不加载网站并保持加载,直到显示超时为止。 / p>

解决方法

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

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

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

NWConnection 确实在网络扩展中工作,如果可以移植您的代码并且您不需要实际的套接字描述符,它应该对您有用。但是如果你必须支持设备