// // DNSClient.swift // Tun // // Created by 安礼成 on 2025/12/10. // import Foundation import NIOCore import NIOPosix // 处理和sn-server服务器之间的通讯 final class SDLDNSClient: ChannelInboundHandler { typealias InboundIn = AddressedEnvelope private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1) private var channel: Channel? private let logger: SDLLogger private let dnsServerAddress: SocketAddress public let packetFlow: AsyncStream private let packetContinuation: AsyncStream.Continuation // 启动函数 init(dnsServerAddress: SocketAddress, logger: SDLLogger) async throws { self.dnsServerAddress = dnsServerAddress self.logger = logger (self.packetFlow, self.packetContinuation) = AsyncStream.makeStream(of: Data.self, bufferingPolicy: .unbounded) } func start() throws { let bootstrap = DatagramBootstrap(group: group) .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .channelInitializer { channel in channel.pipeline.addHandler(self) } let channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait() self.logger.log("[DNSClient] started", level: .debug) self.channel = channel } func waitClose() async throws { try await self.channel?.closeFuture.get() } // --MARK: ChannelInboundHandler delegate func channelRead(context: ChannelHandlerContext, data: NIOAny) { let envelope = unwrapInboundIn(data) var buffer = envelope.data let remoteAddress = envelope.remoteAddress self.logger.log("[DNSClient] read data: \(buffer), from: \(remoteAddress)", level: .debug) let len = buffer.readableBytes if let bytes = buffer.readBytes(length: len) { self.packetContinuation.yield(Data(bytes)) } } func channelInactive(context: ChannelHandlerContext) { self.packetContinuation.finish() } func forward(ipPacket: IPPacket) { guard let channel = self.channel else { return } let buffer = channel.allocator.buffer(bytes: ipPacket.data) let envelope = AddressedEnvelope(remoteAddress: self.dnsServerAddress, data: buffer) channel.pipeline.eventLoop.execute { channel.writeAndFlush(envelope, promise: nil) } } deinit { try? self.group.syncShutdownGracefully() self.packetContinuation.finish() } } extension SDLDNSClient { struct Helper { static let dnsServer: String = "100.100.100.100" // dns请求包的目标地址 static let dnsDestIpAddr: UInt32 = 1684300900 // 判断是否是dns请求的数据包 static func isDnsRequestPacket(ipPacket: IPPacket) -> Bool { return ipPacket.header.destination == dnsDestIpAddr } } }