diff --git a/Tun/Super/SDLSuperClient.swift b/Tun/Super/SDLSuperClient.swift index 8268832..e209dd7 100644 --- a/Tun/Super/SDLSuperClient.swift +++ b/Tun/Super/SDLSuperClient.swift @@ -6,10 +6,7 @@ // import Foundation -import NIOCore import Network -import CryptoKit -import Security // 定义错误类型,便于上层处理 enum SDLSuperError: Error { @@ -34,7 +31,7 @@ actor SDLSuperClient { private var state: State = .idle - private let frameParser: SDLQUICFrameParser + private let frameParser: SDLSuperFrameParser // 数据流 public var messageStream: AsyncThrowingStream @@ -52,7 +49,7 @@ actor SDLSuperClient { self.serverEndpoint = serverEndpoint self.port = port - self.frameParser = SDLQUICFrameParser(maxBufferSize: maxBufferSize) + self.frameParser = SDLSuperFrameParser(maxBufferSize: maxBufferSize) (self.messageStream, self.messageCont) = AsyncThrowingStream.makeStream(of: SDLQUICInboundMessage.self) } @@ -74,7 +71,7 @@ actor SDLSuperClient { options.securityProtocolOptions, { _, trust, complete in // 执行公钥校验 - complete(TLSVerifier.verify(trust: trust, host: serverEndpoint.host)) + complete(SDLSuperTLSVerifier.verify(trust: trust, host: serverEndpoint.host)) }, queue ) @@ -146,7 +143,7 @@ actor SDLSuperClient { let frames = try self.frameParser.parseFrames(data: data) for frame in frames { try Task.checkCancellation() - if let message = SDLQUICCodec.decode(frame: frame) { + if let message = SDLSuperCodec.decode(frame: frame) { self.messageCont.yield(message) } else { self.finishMessageContinuationIfNeed(throwing: .decodeError("invalid message")) @@ -232,183 +229,3 @@ actor SDLSuperClient { } } - -// --MARK: 数据累加器 -extension SDLSuperClient { - - class SDLQUICFrameParser { - private let allocator = ByteBufferAllocator() - // 最大缓冲区区为2M - private let maxPacketSize: Int = 64 * 1024 - private let maxBufferSize: Int - private var buffer: ByteBuffer - - init(maxBufferSize: Int) { - self.buffer = allocator.buffer(capacity: maxBufferSize) - self.maxBufferSize = maxBufferSize - } - - // 尝试解析数据 - public func parseFrames(data: Data) throws -> [ByteBuffer] { - self.buffer.writeBytes(data) - - guard buffer.readableBytes >= 2 else { - return [] - } - - var frames: [ByteBuffer] = [] - while true { - guard let len = buffer.getInteger(at: buffer.readerIndex, endianness: .big, as: UInt16.self) else { - break - } - - if len > self.maxPacketSize { - throw SDLSuperError.packetTooLarge - } - - guard buffer.readableBytes >= len + 2 else { - break - } - - buffer.moveReaderIndex(forwardBy: 2) - if let buf = buffer.readSlice(length: Int(len)) { - frames.append(buf) - } - } - - let threshold = maxBufferSize / 10 * 6 - if buffer.readerIndex > threshold { - buffer.discardReadBytes() - } - - return frames - } - - } - -} - -// --MARK: 编解码器 -extension SDLSuperClient { - - enum SDLQUICCodec { - public static func decode(frame: ByteBuffer) -> SDLQUICInboundMessage? { - var buffer = frame - guard let type = buffer.readInteger(as: UInt8.self), - let packetType = SDLPacketType(rawValue: type) else { - return nil - } - - switch packetType { - case .welcome: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let welcome = try? SDLWelcome(serializedBytes: bytes) else { - return nil - } - return .welcome(welcome) - - case .registerSuperAck: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let registerSuperAck = try? SDLRegisterSuperAck(serializedBytes: bytes) else { - return nil - } - return .registerSuperAck(registerSuperAck) - case .registerSuperNak: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let registerSuperNak = try? SDLRegisterSuperNak(serializedBytes: bytes) else { - return nil - } - return .registerSuperNak(registerSuperNak) - case .peerInfo: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let peerInfo = try? SDLPeerInfo(serializedBytes: bytes) else { - return nil - } - return .peerInfo(peerInfo) - case .policyResponse: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let policyResponse = try? SDLPolicyResponse(serializedBytes: bytes) else { - return nil - } - return .policyReponse(policyResponse) - case .arpResponse: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let arpResponse = try? SDLArpResponse(serializedBytes: bytes) else { - return nil - } - return .arpResponse(arpResponse) - case .event: - guard let bytes = buffer.readBytes(length: buffer.readableBytes), - let event = try? SDLEvent(serializedBytes: bytes) else { - SDLLogger.log("SDLSuperClient decode Event Error", for: .debug) - return nil - } - return .event(event) - case .pong: - return .pong - default: - SDLLogger.log("SDLSuperClient decode miss type: \(type)", for: .debug) - - return nil - } - } - } -} - -// --MARK: tls验证 -extension SDLSuperClient { - - enum TLSVerifier { - // 你的 Base64 公钥指纹 - static let pinnedPublicKeyHashes = [ - "Q41r6hbMWEVyxo6heNAH4Wx/TH5NNOWlNif9bewcJ3E=" - ] - - static func verify(trust: sec_trust_t, host: String) -> Bool { - let secTrust = sec_trust_copy_ref(trust).takeRetainedValue() - - // --- Step 1: 系统验证 --- - var error: CFError? - guard SecTrustEvaluateWithError(secTrust, &error) else { - SDLLogger.log("❌ 系统证书验证失败: \(error?.localizedDescription ?? "未知错误")", for: .debug) - return false - } - - // --- Step 2: 主机名验证 --- - let policy = SecPolicyCreateSSL(true, host as CFString) - SecTrustSetPolicies(secTrust, policy) - - guard SecTrustEvaluateWithError(secTrust, &error) else { - SDLLogger.log("❌ 主机名校验失败: \(error?.localizedDescription ?? "未知错误")", for: .debug) - return false - } - - // --- Step 3: 获取叶子证书 --- - guard let chain = SecTrustCopyCertificateChain(secTrust) as? [SecCertificate], - let leafCertificate = chain.first else { - SDLLogger.log("❌ 无法获取证书链或叶子证书", for: .debug) - return false - } - - // --- Step 4: 提取公钥 --- - guard let publicKey = SecCertificateCopyKey(leafCertificate), - let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) as Data? else { - SDLLogger.log("❌ 无法提取公钥", for: .debug) - return false - } - - // --- Step 5: SHA256 校验 --- - let hash = SHA256.hash(data: publicKeyData) - let hashBase64 = Data(hash).base64EncodedString() - - if pinnedPublicKeyHashes.contains(hashBase64) { - SDLLogger.log("✅ 公钥校验通过", for: .debug) - return true - } else { - SDLLogger.log("⚠️ 公钥不匹配! 收到: \(hashBase64)", for: .debug) - return false - } - } - - } -} diff --git a/Tun/Super/SDLSuperCodec.swift b/Tun/Super/SDLSuperCodec.swift new file mode 100644 index 0000000..d8b2c75 --- /dev/null +++ b/Tun/Super/SDLSuperCodec.swift @@ -0,0 +1,71 @@ +// +// SDLSuperCodec.swift +// punchnet +// +// Created by 安礼成 on 2026/5/22. +// +import Foundation +import NIOCore + +enum SDLSuperCodec { + public static func decode(frame: ByteBuffer) -> SDLQUICInboundMessage? { + var buffer = frame + guard let type = buffer.readInteger(as: UInt8.self), + let packetType = SDLPacketType(rawValue: type) else { + return nil + } + + switch packetType { + case .welcome: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let welcome = try? SDLWelcome(serializedBytes: bytes) else { + return nil + } + return .welcome(welcome) + + case .registerSuperAck: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let registerSuperAck = try? SDLRegisterSuperAck(serializedBytes: bytes) else { + return nil + } + return .registerSuperAck(registerSuperAck) + case .registerSuperNak: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let registerSuperNak = try? SDLRegisterSuperNak(serializedBytes: bytes) else { + return nil + } + return .registerSuperNak(registerSuperNak) + case .peerInfo: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let peerInfo = try? SDLPeerInfo(serializedBytes: bytes) else { + return nil + } + return .peerInfo(peerInfo) + case .policyResponse: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let policyResponse = try? SDLPolicyResponse(serializedBytes: bytes) else { + return nil + } + return .policyReponse(policyResponse) + case .arpResponse: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let arpResponse = try? SDLArpResponse(serializedBytes: bytes) else { + return nil + } + return .arpResponse(arpResponse) + case .event: + guard let bytes = buffer.readBytes(length: buffer.readableBytes), + let event = try? SDLEvent(serializedBytes: bytes) else { + SDLLogger.log("SDLSuperClient decode Event Error", for: .debug) + return nil + } + return .event(event) + case .pong: + return .pong + default: + SDLLogger.log("SDLSuperClient decode miss type: \(type)", for: .debug) + + return nil + } + } +} diff --git a/Tun/Super/SDLSuperFrameParser.swift b/Tun/Super/SDLSuperFrameParser.swift new file mode 100644 index 0000000..56d9102 --- /dev/null +++ b/Tun/Super/SDLSuperFrameParser.swift @@ -0,0 +1,58 @@ +// +// SDLSuperFrameParser.swift +// punchnet +// +// Created by 安礼成 on 2026/5/22. +// +import Foundation +import NIOCore + +final class SDLSuperFrameParser { + private let allocator = ByteBufferAllocator() + // 最大缓冲区区为2M + private let maxPacketSize: Int = 64 * 1024 + private let maxBufferSize: Int + private var buffer: ByteBuffer + + init(maxBufferSize: Int) { + self.buffer = allocator.buffer(capacity: maxBufferSize) + self.maxBufferSize = maxBufferSize + } + + // 尝试解析数据 + public func parseFrames(data: Data) throws -> [ByteBuffer] { + self.buffer.writeBytes(data) + + guard buffer.readableBytes >= 2 else { + return [] + } + + var frames: [ByteBuffer] = [] + while true { + guard let len = buffer.getInteger(at: buffer.readerIndex, endianness: .big, as: UInt16.self) else { + break + } + + if len > self.maxPacketSize { + throw SDLSuperError.packetTooLarge + } + + guard buffer.readableBytes >= len + 2 else { + break + } + + buffer.moveReaderIndex(forwardBy: 2) + if let buf = buffer.readSlice(length: Int(len)) { + frames.append(buf) + } + } + + let threshold = maxBufferSize / 10 * 6 + if buffer.readerIndex > threshold { + buffer.discardReadBytes() + } + + return frames + } + +} diff --git a/Tun/Super/SDLSuperTLSVerifier.swift b/Tun/Super/SDLSuperTLSVerifier.swift new file mode 100644 index 0000000..2c94efc --- /dev/null +++ b/Tun/Super/SDLSuperTLSVerifier.swift @@ -0,0 +1,63 @@ +// +// SDLSuperTLSVerifier.swift +// punchnet +// +// Created by 安礼成 on 2026/5/22. +// +import Foundation +import CryptoKit +import Security + +enum SDLSuperTLSVerifier { + // 你的 Base64 公钥指纹 + static let pinnedPublicKeyHashes = [ + "Q41r6hbMWEVyxo6heNAH4Wx/TH5NNOWlNif9bewcJ3E=" + ] + + static func verify(trust: sec_trust_t, host: String) -> Bool { + let secTrust = sec_trust_copy_ref(trust).takeRetainedValue() + + // --- Step 1: 系统验证 --- + var error: CFError? + guard SecTrustEvaluateWithError(secTrust, &error) else { + SDLLogger.log("❌ 系统证书验证失败: \(error?.localizedDescription ?? "未知错误")", for: .debug) + return false + } + + // --- Step 2: 主机名验证 --- + let policy = SecPolicyCreateSSL(true, host as CFString) + SecTrustSetPolicies(secTrust, policy) + + guard SecTrustEvaluateWithError(secTrust, &error) else { + SDLLogger.log("❌ 主机名校验失败: \(error?.localizedDescription ?? "未知错误")", for: .debug) + return false + } + + // --- Step 3: 获取叶子证书 --- + guard let chain = SecTrustCopyCertificateChain(secTrust) as? [SecCertificate], + let leafCertificate = chain.first else { + SDLLogger.log("❌ 无法获取证书链或叶子证书", for: .debug) + return false + } + + // --- Step 4: 提取公钥 --- + guard let publicKey = SecCertificateCopyKey(leafCertificate), + let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) as Data? else { + SDLLogger.log("❌ 无法提取公钥", for: .debug) + return false + } + + // --- Step 5: SHA256 校验 --- + let hash = SHA256.hash(data: publicKeyData) + let hashBase64 = Data(hash).base64EncodedString() + + if pinnedPublicKeyHashes.contains(hashBase64) { + SDLLogger.log("✅ 公钥校验通过", for: .debug) + return true + } else { + SDLLogger.log("⚠️ 公钥不匹配! 收到: \(hashBase64)", for: .debug) + return false + } + } + + }