fix holeControlPlane
This commit is contained in:
parent
eca022cae0
commit
1907c4347b
@ -30,6 +30,7 @@ actor SDLContextActor {
|
||||
private let dnsLocalService: DNSLocalService
|
||||
private let superService: SDLSuperService
|
||||
private let superControlPlane: SDLSuperControlPlane
|
||||
private let holeControlPlane: SDLHoleControlPlane
|
||||
private let udpHoleService: SDLUDPHoleService
|
||||
private let udpHoleV6Service: SDLUDPHoleV6Service
|
||||
private let packetOutboundActor: PacketOutboundActor
|
||||
@ -76,6 +77,7 @@ actor SDLContextActor {
|
||||
let dnsCloudService = DNSCloudService(serverIP: config.serverEndpoint.ip)
|
||||
let dnsLocalService = DNSLocalService(publicDnsServers: Self.publicDnsServers)
|
||||
let superControlPlane = SDLSuperControlPlane(config: config, rsaCipher: rsaCipher)
|
||||
let holeControlPlane = SDLHoleControlPlane(networkAddress: config.networkAddress)
|
||||
let tunNetworkManager = SDLTunNetworkManager(provider: provider)
|
||||
let ipv6AssistPair = AsyncStream.makeStream(of: Optional<SDLV6Info>.self, bufferingPolicy: .bufferingNewest(1))
|
||||
let packetOutboundActor = PacketOutboundActor(
|
||||
@ -122,6 +124,7 @@ actor SDLContextActor {
|
||||
self.dnsLocalService = dnsLocalService
|
||||
self.superService = superService
|
||||
self.superControlPlane = superControlPlane
|
||||
self.holeControlPlane = holeControlPlane
|
||||
self.udpHoleService = udpHoleService
|
||||
self.udpHoleV6Service = udpHoleV6Service
|
||||
self.packetOutboundActor = packetOutboundActor
|
||||
@ -410,16 +413,15 @@ actor SDLContextActor {
|
||||
|
||||
}
|
||||
|
||||
// MARK: probe网络类型
|
||||
extension SDLContextActor {
|
||||
|
||||
// MARK: probe网络类型
|
||||
|
||||
private func setNatType(natType: SDLNATProberActor.NatType) {
|
||||
self.natType = natType
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Notifier通知机制
|
||||
extension SDLContextActor {
|
||||
|
||||
private func prepareTunnelNotifier() {
|
||||
// 启动noticeClient
|
||||
@ -432,15 +434,8 @@ extension SDLContextActor {
|
||||
private func publishTunnelEvent(code: Int? = nil, message: String) {
|
||||
SDLTunnelAppNotifier.shared.publish(code: code, message: message)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: 数据发送
|
||||
extension SDLContextActor {
|
||||
|
||||
// 发送给peer的数据
|
||||
private func sendPeerPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) async {
|
||||
await self.sendPacket(type: type, data: data, remoteAddress: remoteAddress)
|
||||
}
|
||||
|
||||
private func sendPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) async {
|
||||
switch remoteAddress {
|
||||
@ -452,10 +447,8 @@ extension SDLContextActor {
|
||||
SDLLogger.log("[SDLContext] unsupported socket family: \(remoteAddress)", for: .debug)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: 处理和Super之间的通讯
|
||||
extension SDLContextActor {
|
||||
|
||||
private func handleSuperDecision(_ decision: SuperDecision) async {
|
||||
switch decision {
|
||||
@ -530,10 +523,8 @@ extension SDLContextActor {
|
||||
self.config.acl = acl
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: DNS service events
|
||||
extension SDLContextActor {
|
||||
|
||||
private func handleDNSEvent(_ event: DNSEvent) async {
|
||||
switch event {
|
||||
case .packet(let packet):
|
||||
@ -541,91 +532,29 @@ extension SDLContextActor {
|
||||
self.provider.packetFlow.writePacketObjects([nePacket])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: 处理从Hole收到的数据
|
||||
extension SDLContextActor {
|
||||
|
||||
private func handleUDPHoleControlEvent(_ event: SDLUDPHoleService.Event) async {
|
||||
switch event {
|
||||
case .ready(let localAddress):
|
||||
SDLLogger.log("[SDLContext] udpHole ready: \(localAddress)")
|
||||
case .natType(let natType):
|
||||
let decisions = self.holeControlPlane.handle(event)
|
||||
for decision in decisions {
|
||||
await self.handleHoleDecision(decision)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleHoleDecision(_ decision: HoleDecision) async {
|
||||
switch decision {
|
||||
case .updateNatType(let natType):
|
||||
self.setNatType(natType: natType)
|
||||
SDLLogger.log("[SDLContext] nat_type is: \(natType)")
|
||||
case .packet(let remoteAddress, let message):
|
||||
await self.handleUDPHolePacket(remoteAddress: remoteAddress, message: message)
|
||||
case .closed(let error):
|
||||
SDLLogger.log("[SDLContext] udpHole closed: \(error)", for: .debug)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleUDPHolePacket(remoteAddress: SocketAddress, message: SDLHoleControlMessage) async {
|
||||
switch message {
|
||||
case .stunReply(_), .stunProbeReply(_):
|
||||
SDLLogger.log("[SDLContext] get a stun reply", for: .debug)
|
||||
case .register(let register):
|
||||
try? await self.handleRegister(remoteAddress: remoteAddress, register: register)
|
||||
case .registerAck(let registerAck):
|
||||
await self.handleRegisterAck(remoteAddress: remoteAddress, registerAck: registerAck)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRegister(remoteAddress: SocketAddress, register: SDLRegister) async throws {
|
||||
let networkAddr = config.networkAddress
|
||||
SDLLogger.log("[SDLContext] register packet: \(register), network_address: \(networkAddr)")
|
||||
|
||||
// 判断目标地址是否是tun的网卡地址, 并且是在同一个网络下
|
||||
if register.dstMac == networkAddr.mac && register.networkID == networkAddr.networkId {
|
||||
// 回复ack包
|
||||
var registerAck = SDLRegisterAck()
|
||||
registerAck.networkID = networkAddr.networkId
|
||||
registerAck.srcMac = networkAddr.mac
|
||||
registerAck.dstMac = register.srcMac
|
||||
|
||||
await self.sendPeerPacket(type: .registerAck, data: try registerAck.serializedData(), remoteAddress: remoteAddress)
|
||||
// 这里需要建立到来源的会话, 在复杂网络下,通过super-node查询到的nat地址不一定靠谱,需要通过udp包的来源地址作为nat地址
|
||||
if let addressType = Self.addressType(from: remoteAddress),
|
||||
let session = Session(dstMac: register.srcMac, natAddress: remoteAddress, addressType: addressType) {
|
||||
case .sendPacket(let type, let data, let remoteAddress):
|
||||
await self.sendPacket(type: type, data: data, remoteAddress: remoteAddress)
|
||||
case .addSession(let session):
|
||||
await self.sessionManager.addSession(session: session)
|
||||
} else {
|
||||
SDLLogger.log("[SDLContext] didReadRegister get unsupported remoteAddress: \(remoteAddress)", for: .debug)
|
||||
}
|
||||
} else {
|
||||
SDLLogger.log("[SDLContext] didReadRegister get a invalid packet, because dst_ip not matched: \(register.dstMac)")
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRegisterAck(remoteAddress: SocketAddress, registerAck: SDLRegisterAck) async {
|
||||
// 判断目标地址是否是tun的网卡地址, 并且是在同一个网络下
|
||||
let networkAddr = config.networkAddress
|
||||
if registerAck.dstMac == networkAddr.mac && registerAck.networkID == networkAddr.networkId {
|
||||
if let addressType = Self.addressType(from: remoteAddress),
|
||||
let session = Session(dstMac: registerAck.srcMac, natAddress: remoteAddress, addressType: addressType) {
|
||||
await self.sessionManager.addSession(session: session)
|
||||
} else {
|
||||
SDLLogger.log("[SDLContext] didReadRegisterAck get unsupported remoteAddress: \(remoteAddress)", for: .debug)
|
||||
}
|
||||
} else {
|
||||
SDLLogger.log("[SDLContext] didReadRegisterAck get a invalid packet, because dst_mac not matched: \(registerAck.dstMac)")
|
||||
}
|
||||
}
|
||||
|
||||
private static func addressType(from remoteAddress: SocketAddress) -> Session.AddressType? {
|
||||
switch remoteAddress {
|
||||
case .v4:
|
||||
return .v4
|
||||
case .v6:
|
||||
return .v6
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: 和Stun相关的心跳机制
|
||||
extension SDLContextActor {
|
||||
|
||||
private func runStunRequestOnce() async throws {
|
||||
let probeReply = try? await self.ipv6AssistClient?.probe(requestTimeout: .seconds(3))
|
||||
|
||||
@ -637,10 +566,8 @@ extension SDLContextActor {
|
||||
|
||||
await self.superControlPlane.sendStunRequest(natType: self.natType, v6Info: probeReply?.v6Info)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: NEPacketTunnelProvider相关的逻辑
|
||||
extension SDLContextActor {
|
||||
|
||||
// 取消出口节点的时候,ip地址为: 0.0.0.0
|
||||
public func updateExitNode(exitNodeIp: String) async throws {
|
||||
|
||||
113
Tun/Context/SDLHoleControlPlane.swift
Normal file
113
Tun/Context/SDLHoleControlPlane.swift
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// SDLHoleControlPlane.swift
|
||||
// Tun
|
||||
//
|
||||
// Created by Codex on 2026/5/28.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import NIOCore
|
||||
|
||||
enum HoleDecision {
|
||||
case updateNatType(SDLNATProberActor.NatType)
|
||||
case sendPacket(type: SDLPacketType, data: Data, remoteAddress: SocketAddress)
|
||||
case addSession(Session)
|
||||
}
|
||||
|
||||
struct SDLHoleControlPlane {
|
||||
private let networkAddress: SDLConfiguration.NetworkAddress
|
||||
|
||||
init(networkAddress: SDLConfiguration.NetworkAddress) {
|
||||
self.networkAddress = networkAddress
|
||||
}
|
||||
|
||||
func handle(_ event: SDLUDPHoleService.Event) -> [HoleDecision] {
|
||||
switch event {
|
||||
case .ready(let localAddress):
|
||||
SDLLogger.log("[SDLContext] udpHole ready: \(localAddress)")
|
||||
return []
|
||||
case .natType(let natType):
|
||||
SDLLogger.log("[SDLContext] nat_type is: \(natType)")
|
||||
return [
|
||||
.updateNatType(natType)
|
||||
]
|
||||
case .packet(let remoteAddress, let message):
|
||||
return self.handlePacket(remoteAddress: remoteAddress, message: message)
|
||||
case .closed(let error):
|
||||
SDLLogger.log("[SDLContext] udpHole closed: \(error)", for: .debug)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
private func handlePacket(remoteAddress: SocketAddress, message: SDLHoleControlMessage) -> [HoleDecision] {
|
||||
switch message {
|
||||
case .stunReply, .stunProbeReply:
|
||||
SDLLogger.log("[SDLContext] get a stun reply", for: .debug)
|
||||
return []
|
||||
case .register(let register):
|
||||
return self.handleRegister(remoteAddress: remoteAddress, register: register)
|
||||
case .registerAck(let registerAck):
|
||||
return self.handleRegisterAck(remoteAddress: remoteAddress, registerAck: registerAck)
|
||||
}
|
||||
}
|
||||
|
||||
private func handleRegister(remoteAddress: SocketAddress, register: SDLRegister) -> [HoleDecision] {
|
||||
SDLLogger.log("[SDLContext] register packet: \(register), network_address: \(self.networkAddress)")
|
||||
var decisions: [HoleDecision] = []
|
||||
|
||||
guard register.dstMac == self.networkAddress.mac && register.networkID == self.networkAddress.networkId else {
|
||||
SDLLogger.log("[SDLContext] didReadRegister get a invalid packet, because dst_ip not matched: \(register.dstMac)")
|
||||
return decisions
|
||||
}
|
||||
|
||||
var registerAck = SDLRegisterAck()
|
||||
registerAck.networkID = self.networkAddress.networkId
|
||||
registerAck.srcMac = self.networkAddress.mac
|
||||
registerAck.dstMac = register.srcMac
|
||||
|
||||
if let data = try? registerAck.serializedData() {
|
||||
decisions.append(.sendPacket(type: .registerAck, data: data, remoteAddress: remoteAddress))
|
||||
}
|
||||
|
||||
if let session = self.makeSession(dstMac: register.srcMac, remoteAddress: remoteAddress) {
|
||||
decisions.append(.addSession(session))
|
||||
} else {
|
||||
SDLLogger.log("[SDLContext] didReadRegister get unsupported remoteAddress: \(remoteAddress)", for: .debug)
|
||||
}
|
||||
|
||||
return decisions
|
||||
}
|
||||
|
||||
private func handleRegisterAck(remoteAddress: SocketAddress, registerAck: SDLRegisterAck) -> [HoleDecision] {
|
||||
guard registerAck.dstMac == self.networkAddress.mac && registerAck.networkID == self.networkAddress.networkId else {
|
||||
SDLLogger.log("[SDLContext] didReadRegisterAck get a invalid packet, because dst_mac not matched: \(registerAck.dstMac)", for: .debug)
|
||||
return []
|
||||
}
|
||||
|
||||
guard let session = self.makeSession(dstMac: registerAck.srcMac, remoteAddress: remoteAddress) else {
|
||||
SDLLogger.log("[SDLContext] didReadRegisterAck get unsupported remoteAddress: \(remoteAddress)", for: .debug)
|
||||
return []
|
||||
}
|
||||
|
||||
return [.addSession(session)]
|
||||
}
|
||||
|
||||
private func makeSession(dstMac: Data, remoteAddress: SocketAddress) -> Session? {
|
||||
guard let addressType = Self.addressType(from: remoteAddress) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Session(dstMac: dstMac, natAddress: remoteAddress, addressType: addressType)
|
||||
}
|
||||
|
||||
private static func addressType(from remoteAddress: SocketAddress) -> Session.AddressType? {
|
||||
switch remoteAddress {
|
||||
case .v4:
|
||||
return .v4
|
||||
case .v6:
|
||||
return .v6
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user