fix dns client
This commit is contained in:
parent
0df890a699
commit
7ca620eca7
102
Tun/Punchnet/DNSClient.swift
Normal file
102
Tun/Punchnet/DNSClient.swift
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
//
|
||||||
|
// DNSClient.swift
|
||||||
|
// Tun
|
||||||
|
//
|
||||||
|
// Created by 安礼成 on 2025/12/10.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import NIOCore
|
||||||
|
import NIOPosix
|
||||||
|
|
||||||
|
// 处理和sn-server服务器之间的通讯
|
||||||
|
@available(macOS 14, *)
|
||||||
|
actor DNSClient {
|
||||||
|
private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||||
|
private let asyncChannel: NIOAsyncChannel<AddressedEnvelope<ByteBuffer>, AddressedEnvelope<ByteBuffer>>
|
||||||
|
private let (writeStream, writeContinuation) = AsyncStream.makeStream(of: Data.self, bufferingPolicy: .unbounded)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
let bootstrap = DatagramBootstrap(group: group)
|
||||||
|
.channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
|
||||||
|
|
||||||
|
self.asyncChannel = try await bootstrap.bind(host: "0.0.0.0", port: 0)
|
||||||
|
.flatMapThrowing { channel in
|
||||||
|
return try NIOAsyncChannel(wrappingChannelSynchronously: channel, configuration: .init(
|
||||||
|
inboundType: AddressedEnvelope<ByteBuffer>.self,
|
||||||
|
outboundType: AddressedEnvelope<ByteBuffer>.self
|
||||||
|
))
|
||||||
|
}
|
||||||
|
.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() async throws {
|
||||||
|
try await withTaskCancellationHandler {
|
||||||
|
try await self.asyncChannel.executeThenClose {inbound, outbound in
|
||||||
|
try await withThrowingTaskGroup(of: Void.self) { group in
|
||||||
|
group.addTask {
|
||||||
|
defer {
|
||||||
|
self.logger.log("[DNSClient] inbound closed", level: .warning)
|
||||||
|
}
|
||||||
|
|
||||||
|
for try await envelope in inbound {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
defer {
|
||||||
|
self.logger.log("[DNSClient] outbound closed", level: .warning)
|
||||||
|
}
|
||||||
|
|
||||||
|
for await message in self.writeStream {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
|
||||||
|
let buffer = self.asyncChannel.channel.allocator.buffer(bytes: message)
|
||||||
|
let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: self.dnsServerAddress, data: buffer)
|
||||||
|
try await outbound.write(envelope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _ = try await group.next() {
|
||||||
|
group.cancelAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} onCancel: {
|
||||||
|
self.writeContinuation.finish()
|
||||||
|
self.packetContinuation.finish()
|
||||||
|
self.logger.log("[DNSClient] withTaskCancellationHandler cancel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func forward(ipPacket: IPPacket) {
|
||||||
|
self.writeContinuation.yield(ipPacket.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
try? self.group.syncShutdownGracefully()
|
||||||
|
self.writeContinuation.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,23 +1,23 @@
|
|||||||
////
|
|
||||||
//// DNSUtil.swift
|
|
||||||
//// punchnet
|
|
||||||
////
|
|
||||||
//// Created by 安礼成 on 2025/12/9.
|
|
||||||
////
|
|
||||||
//
|
//
|
||||||
//import Foundation
|
// DNSUtil.swift
|
||||||
//import Network
|
// punchnet
|
||||||
//
|
//
|
||||||
//struct DNSUtil {
|
// Created by 安礼成 on 2025/12/9.
|
||||||
// static let dnsServers: [String] = ["100.100.100.100"]
|
|
||||||
// // dns请求包的目标地址
|
|
||||||
// static let dnsDestIpAddr: UInt32 = 1684300900
|
|
||||||
//
|
|
||||||
// // 判断是否是dns请求的数据包
|
|
||||||
// static func isDnsRequestPacket(ipPacket: IPPacket) -> Bool {
|
|
||||||
// return ipPacket.header.destination == dnsDestIpAddr
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Network
|
||||||
|
|
||||||
|
struct DNSUtil {
|
||||||
|
static let dnsServers: [String] = ["100.100.100.100"]
|
||||||
|
// dns请求包的目标地址
|
||||||
|
static let dnsDestIpAddr: UInt32 = 1684300900
|
||||||
|
|
||||||
|
// 判断是否是dns请求的数据包
|
||||||
|
static func isDnsRequestPacket(ipPacket: IPPacket) -> Bool {
|
||||||
|
return ipPacket.header.destination == dnsDestIpAddr
|
||||||
|
}
|
||||||
|
|
||||||
// // DNS Header 结构
|
// // DNS Header 结构
|
||||||
// struct DNSHeader {
|
// struct DNSHeader {
|
||||||
// var id: UInt16
|
// var id: UInt16
|
||||||
@ -35,8 +35,6 @@
|
|||||||
// var qclass: UInt16
|
// var qclass: UInt16
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//
|
|
||||||
//
|
|
||||||
// // 解析域名(DNS Label 格式)
|
// // 解析域名(DNS Label 格式)
|
||||||
// func parseName(from data: Data, offset: inout Int) -> String {
|
// func parseName(from data: Data, offset: inout Int) -> String {
|
||||||
// var labels: [String] = []
|
// var labels: [String] = []
|
||||||
@ -109,13 +107,13 @@
|
|||||||
// print("Question: \(q.name), type: \(q.type), class: \(q.qclass)")
|
// print("Question: \(q.name), type: \(q.type), class: \(q.qclass)")
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
//// Helper 扩展:读取整数类型
|
// Helper 扩展:读取整数类型
|
||||||
//private extension Data {
|
private extension Data {
|
||||||
// func uint16(at offset: Int) -> UInt16 {
|
func uint16(at offset: Int) -> UInt16 {
|
||||||
// let subdata = self[offset..<offset+2]
|
let subdata = self[offset..<offset+2]
|
||||||
// return subdata.withUnsafeBytes { $0.load(as: UInt16.self).bigEndian }
|
return subdata.withUnsafeBytes { $0.load(as: UInt16.self).bigEndian }
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|||||||
@ -51,6 +51,9 @@ public class SDLContext: @unchecked Sendable {
|
|||||||
var udpHole: SDLUDPHole?
|
var udpHole: SDLUDPHole?
|
||||||
var superClient: SDLSuperClient?
|
var superClient: SDLSuperClient?
|
||||||
|
|
||||||
|
// dns的client对象
|
||||||
|
var dnsClient: DNSClient?
|
||||||
|
|
||||||
// 数据包读取任务
|
// 数据包读取任务
|
||||||
private var readTask: Task<(), Never>?
|
private var readTask: Task<(), Never>?
|
||||||
|
|
||||||
@ -107,6 +110,18 @@ public class SDLContext: @unchecked Sendable {
|
|||||||
public func start() async throws {
|
public func start() async throws {
|
||||||
self.rootTask = Task {
|
self.rootTask = Task {
|
||||||
try await withThrowingTaskGroup(of: Void.self) { group in
|
try await withThrowingTaskGroup(of: Void.self) { group in
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
while !Task.isCancelled {
|
||||||
|
do {
|
||||||
|
try await self.startDnsClient()
|
||||||
|
} catch let err {
|
||||||
|
self.logger.log("[SDLContext] UDPHole get err: \(err)", level: .warning)
|
||||||
|
try await Task.sleep(for: .seconds(2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
group.addTask {
|
group.addTask {
|
||||||
while !Task.isCancelled {
|
while !Task.isCancelled {
|
||||||
do {
|
do {
|
||||||
@ -235,6 +250,35 @@ public class SDLContext: @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func startDnsClient() async throws {
|
||||||
|
let dnsSocketAddress = try SocketAddress.makeAddressResolvingHost("127.0.0.1", port: 15353)
|
||||||
|
self.dnsClient = try await DNSClient(dnsServerAddress: dnsSocketAddress, logger: self.logger)
|
||||||
|
|
||||||
|
try await withThrowingTaskGroup(of: Void.self) { group in
|
||||||
|
defer {
|
||||||
|
self.logger.log("[SDLContext] dns client task cancel", level: .warning)
|
||||||
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
try await self.dnsClient?.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
if let packetFlow = self.dnsClient?.packetFlow {
|
||||||
|
for await packet in packetFlow {
|
||||||
|
let nePacket = NEPacket(data: packet, protocolFamily: 2)
|
||||||
|
self.provider.packetFlow.writePacketObjects([nePacket])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _ = try await group.next() {
|
||||||
|
group.cancelAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func handleSuperEvent(event: SDLSuperClient.SuperEvent) async throws {
|
private func handleSuperEvent(event: SDLSuperClient.SuperEvent) async throws {
|
||||||
switch event {
|
switch event {
|
||||||
case .ready:
|
case .ready:
|
||||||
@ -485,39 +529,47 @@ public class SDLContext: @unchecked Sendable {
|
|||||||
repeat {
|
repeat {
|
||||||
let (packets, numbers) = await self.provider.packetFlow.readPackets()
|
let (packets, numbers) = await self.provider.packetFlow.readPackets()
|
||||||
for (data, number) in zip(packets, numbers) where number == 2 {
|
for (data, number) in zip(packets, numbers) where number == 2 {
|
||||||
if let packet = IPPacket(data) {
|
await self.dealPacket(data: data)
|
||||||
let destIp = packet.header.destination_ip
|
|
||||||
NSLog("destIp: \(destIp), int: \(packet.header.destination)")
|
|
||||||
|
|
||||||
|
|
||||||
Task.detached {
|
|
||||||
let dstIp = packet.header.destination
|
|
||||||
// 本地通讯, 目标地址是本地服务器的ip地址
|
|
||||||
if dstIp == self.devAddr.netAddr {
|
|
||||||
let nePacket = NEPacket(data: packet.data, protocolFamily: 2)
|
|
||||||
self.provider.packetFlow.writePacketObjects([nePacket])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找arp缓存中是否有目标mac地址
|
|
||||||
if let dstMac = await self.arpServer.query(ip: dstIp) {
|
|
||||||
await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// 构造arp请求
|
|
||||||
let broadcastMac = Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
|
||||||
let arpReqeust = ARPPacket.arpRequest(senderIP: self.devAddr.netAddr, senderMAC: self.devAddr.mac, targetIP: dstIp)
|
|
||||||
await self.routeLayerPacket(dstMac: broadcastMac, type: .arp, data: arpReqeust.marshal())
|
|
||||||
|
|
||||||
self.logger.log("[SDLContext] dstIp: \(dstIp) arp query not found", level: .debug)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} while true
|
} while true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理读取的每个数据包
|
||||||
|
private func dealPacket(data: Data) async {
|
||||||
|
guard let packet = IPPacket(data) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if DNSUtil.isDnsRequestPacket(ipPacket: packet) {
|
||||||
|
let destIp = packet.header.destination_ip
|
||||||
|
NSLog("destIp: \(destIp), int: \(packet.header.destination)")
|
||||||
|
await self.dnsClient?.forward(ipPacket: packet)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Task.detached {
|
||||||
|
let dstIp = packet.header.destination
|
||||||
|
// 本地通讯, 目标地址是本地服务器的ip地址
|
||||||
|
if dstIp == self.devAddr.netAddr {
|
||||||
|
let nePacket = NEPacket(data: packet.data, protocolFamily: 2)
|
||||||
|
self.provider.packetFlow.writePacketObjects([nePacket])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找arp缓存中是否有目标mac地址
|
||||||
|
if let dstMac = await self.arpServer.query(ip: dstIp) {
|
||||||
|
await self.routeLayerPacket(dstMac: dstMac, type: .ipv4, data: packet.data)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 构造arp请求
|
||||||
|
let broadcastMac = Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||||
|
let arpReqeust = ARPPacket.arpRequest(senderIP: self.devAddr.netAddr, senderMAC: self.devAddr.mac, targetIP: dstIp)
|
||||||
|
await self.routeLayerPacket(dstMac: broadcastMac, type: .arp, data: arpReqeust.marshal())
|
||||||
|
|
||||||
|
self.logger.log("[SDLContext] dstIp: \(dstIp) arp query not found", level: .debug)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async {
|
private func routeLayerPacket(dstMac: Data, type: LayerPacket.PacketType, data: Data) async {
|
||||||
@ -594,6 +646,7 @@ public class SDLContext: @unchecked Sendable {
|
|||||||
self.rootTask?.cancel()
|
self.rootTask?.cancel()
|
||||||
self.udpHole = nil
|
self.udpHole = nil
|
||||||
self.superClient = nil
|
self.superClient = nil
|
||||||
|
self.dnsClient = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取mac地址
|
// 获取mac地址
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user