106 lines
3.4 KiB
Swift
106 lines
3.4 KiB
Swift
//
|
|
// DNSClient.swift
|
|
// Tun
|
|
//
|
|
// Created by 安礼成 on 2025/12/10.
|
|
//
|
|
|
|
import Foundation
|
|
import NIOCore
|
|
import NIOPosix
|
|
|
|
// 处理和sn-server服务器之间的通讯
|
|
@available(macOS 14, *)
|
|
actor SDLDNSClientActor {
|
|
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
|
|
|
private var channel: Channel?
|
|
private let logger: SDLLogger
|
|
private let dnsServerAddress: SocketAddress
|
|
|
|
public let packetFlow: AsyncStream<Data>
|
|
private let packetContinuation: AsyncStream<Data>.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(SDLDNSInboundHandler(packetContinuation: self.packetContinuation, logger: self.logger))
|
|
}
|
|
|
|
self.channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait()
|
|
self.logger.log("[DNSClient] started", level: .debug)
|
|
}
|
|
|
|
func forward(ipPacket: IPPacket) {
|
|
guard let channel = self.channel else {
|
|
return
|
|
}
|
|
|
|
let buffer = channel.allocator.buffer(bytes: ipPacket.data)
|
|
let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: self.dnsServerAddress, data: buffer)
|
|
channel.pipeline.eventLoop.execute {
|
|
channel.writeAndFlush(envelope, promise: nil)
|
|
}
|
|
}
|
|
|
|
deinit {
|
|
try? self.group.syncShutdownGracefully()
|
|
self.packetContinuation.finish()
|
|
}
|
|
|
|
}
|
|
|
|
extension SDLDNSClientActor {
|
|
|
|
private final class SDLDNSInboundHandler: ChannelInboundHandler {
|
|
typealias InboundIn = AddressedEnvelope<ByteBuffer>
|
|
|
|
private var packetContinuation: AsyncStream<Data>.Continuation
|
|
private var logger: SDLLogger
|
|
|
|
// --MARK: ChannelInboundHandler delegate
|
|
|
|
init(packetContinuation: AsyncStream<Data>.Continuation, logger: SDLLogger) {
|
|
self.packetContinuation = packetContinuation
|
|
self.logger = logger
|
|
}
|
|
|
|
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()
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
}
|