From f72a9acf243b61a3ecc0703cff49873e879dc16f Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Tue, 14 Apr 2026 20:07:17 +0800 Subject: [PATCH] fix router --- Tun/Punchnet/Actors/SDLContextActor.swift | 242 ++++++++----------- Tun/Punchnet/Actors/SDLTunPacketRouter.swift | 114 +++++++++ 2 files changed, 221 insertions(+), 135 deletions(-) create mode 100644 Tun/Punchnet/Actors/SDLTunPacketRouter.swift diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index 9cc7d60..2914efd 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -748,141 +748,6 @@ actor SDLContextActor { } } - // 处理读取的每个数据包, Tun收到的包的一级路由 - private func dealTunPacket(packet: IPPacket) async { - let networkAddr = self.config.networkAddress - let dstIp = packet.header.destination - - // 本地通讯, 目标地址是本地服务器的ip地址 - if dstIp == networkAddr.ip { - let nePacket = NEPacket(data: packet.data, protocolFamily: 2) - self.provider.packetFlow.writePacketObjects([nePacket]) - } - // 处理dns的解析 - else if DNSHelper.isDnsRequestPacket(ipPacket: packet) { - if case .udp(let udpPacket) = packet.transportPacket { - // 数据是通过offset解析的, dns查询必然是udp包 - let payloadOffset = udpPacket.payloadOffset - let dnsParser = DNSParser(data: packet.data, offset: payloadOffset) - if let dnsMessage = dnsParser.parse(), let name = dnsMessage.questions.first?.name { - // 如果是内部域名,则转发整个ip包的内容到云端服务器 - if name.contains(self.config.networkAddress.networkDomain) { - SDLLogger.log("[SDLContext] get cloud dns request: \(name)") - if let dnsClient = self.dnsClient { - await dnsClient.forward(ipPacketData: packet.data) - } - } - // 如果开启了出口节点,则转发给出口节点 - else if let exitNode = config.exitNode { - let exitNodeIp = exitNode.exitNodeIp - SDLLogger.log("[SDLContext] dstIp: \(packet.header.destination.asIpAddress()), use exit_node: \(exitNodeIp.asIpAddress())") - // 查找arp缓存中是否有目标mac地址 - if let dstMac = await self.arpServer.query(ip: exitNodeIp) { - await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data) - } - else { - try? await self.arpServer.arpRequest(targetIp: exitNodeIp, use: self.quicClient) - } - } - // 通过本地的dns解析,发送的是udp的payload部分 - else { - SDLLogger.log("[SDLContext] get local dns request: \(name)") - let dnsPayload = Data(packet.data[payloadOffset.. RouteDecision { + let dstIp = packet.header.destination + + // 本地通讯, 目标地址是本地服务器的ip地址 + if dstIp == self.networkAddress.ip { + return .loopback(ipPacketData: packet.data) + } + + // 处理dns的解析 + if let dnsDecision = self.routeDNS(packet: packet, now: now) { + return dnsDecision + } + + // 判断目标地址是否和当前的网络地址是否在同一个网段 + // 只有在同一个网段的ip数据才直接发送 + if SDLUtil.inSameNetwork(ip: dstIp, compareIp: self.networkAddress.ip, maskLen: self.networkAddress.maskLen) { + return .forwardToNextHop(ip: dstIp, type: .ipv4, data: packet.data, kind: .sameNetwork) + } + + // 不在同一个网段的数据,看是否配置了网络出口, 如果配置了,转发数据个网络出口,否则丢弃 + if let exitNode = self.exitNode { + return .forwardToNextHop(ip: exitNode.exitNodeIp, type: .ipv4, data: packet.data, kind: .exitNode) + } + + return .drop(reason: .noRoute) + } + + private func routeDNS(packet: IPPacket, now: Date) -> RouteDecision? { + guard DNSHelper.isDnsRequestPacket(ipPacket: packet) else { + return nil + } + + guard case .udp(let udpPacket) = packet.transportPacket else { + return .drop(reason: .invalidDNSRequest) + } + + // 数据是通过offset解析的, dns查询必然是udp包 + let payloadOffset = udpPacket.payloadOffset + let dnsParser = DNSParser(data: packet.data, offset: payloadOffset) + guard let dnsMessage = dnsParser.parse(), let name = dnsMessage.questions.first?.name else { + return .drop(reason: .invalidDNSRequest) + } + + // 如果是内部域名,则转发整个ip包的内容到云端服务器 + if name.contains(self.networkAddress.networkDomain) { + return .cloudDNS(name: name, ipPacketData: packet.data) + } + + // 如果开启了出口节点,则转发给出口节点 + if let exitNode = self.exitNode { + return .forwardToNextHop(ip: exitNode.exitNodeIp, type: .ipv4, data: packet.data, kind: .dnsExitNode) + } + + // 通过本地的dns解析,发送的是udp的payload部分 + let dnsPayload = Data(packet.data[payloadOffset..