fix Inbound
This commit is contained in:
parent
7c46838101
commit
2cf0bcec73
@ -9,6 +9,35 @@ import Foundation
|
|||||||
import NetworkExtension
|
import NetworkExtension
|
||||||
|
|
||||||
actor PacketInboundActor {
|
actor PacketInboundActor {
|
||||||
|
private struct PolicyPacketContext {
|
||||||
|
let srcIdentityID: UInt32
|
||||||
|
let proto: UInt8
|
||||||
|
let srcIP: UInt32
|
||||||
|
let dstIP: UInt32
|
||||||
|
let srcPort: UInt16?
|
||||||
|
let dstPort: UInt16?
|
||||||
|
|
||||||
|
var logDescription: String {
|
||||||
|
let srcPort = self.srcPort.map(String.init) ?? "-"
|
||||||
|
let dstPort = self.dstPort.map(String.init) ?? "-"
|
||||||
|
return "srcIdentityID: \(self.srcIdentityID), proto: \(self.proto), srcIP: \(SDLUtil.int32ToIp(self.srcIP)), dstIP: \(SDLUtil.int32ToIp(self.dstIP)), srcPort: \(srcPort), dstPort: \(dstPort)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ProcessingAction {
|
||||||
|
case sendARPReply(dstMac: Data, data: Data)
|
||||||
|
case appendARP(ip: UInt32, mac: Data)
|
||||||
|
case writeToTun(packetData: Data, identityID: UInt32)
|
||||||
|
case requestPolicy(PolicyPacketContext)
|
||||||
|
case dropByPolicy(PolicyPacketContext)
|
||||||
|
case none
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ProcessingPlan {
|
||||||
|
let inboundBytes: Int
|
||||||
|
let action: ProcessingAction
|
||||||
|
}
|
||||||
|
|
||||||
private let provider: NEPacketTunnelProvider
|
private let provider: NEPacketTunnelProvider
|
||||||
private let policyService: PolicyService
|
private let policyService: PolicyService
|
||||||
private let packetOutboundActor: PacketOutboundActor
|
private let packetOutboundActor: PacketOutboundActor
|
||||||
@ -46,13 +75,8 @@ actor PacketInboundActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleData(_ data: SDLData) async {
|
func handleData(_ data: SDLData) async {
|
||||||
let processor = PacketInboundProcessor(
|
let policyRuntime = self.policyService.policyRuntime()
|
||||||
networkAddress: self.networkAddress,
|
guard let plan = try? self.makeProcessingPlan(data: data, policyRuntime: policyRuntime) else {
|
||||||
dataCipher: self.dataCipher,
|
|
||||||
policyRuntime: self.policyService.policyRuntime()
|
|
||||||
)
|
|
||||||
|
|
||||||
guard let plan = try? processor.makeProcessingPlan(data: data) else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,4 +104,105 @@ actor PacketInboundActor {
|
|||||||
()
|
()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func makeProcessingPlan(data: SDLData, policyRuntime: PolicyRuntime) throws -> ProcessingPlan? {
|
||||||
|
guard let dataCipher = self.dataCipher else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let mac = LayerPacket.MacAddress(data: data.dstMac)
|
||||||
|
guard (data.dstMac == self.networkAddress.mac || mac.isBroadcast() || mac.isMulticast()) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let decryptedData = try dataCipher.decrypt(cipherText: data.data)
|
||||||
|
let layerPacket = try LayerPacketView(layerData: decryptedData)
|
||||||
|
let inboundBytes = decryptedData.count
|
||||||
|
|
||||||
|
switch layerPacket.type {
|
||||||
|
case .arp:
|
||||||
|
return self.makeARPPlan(layerData: layerPacket.data, inboundBytes: inboundBytes)
|
||||||
|
case .ipv4:
|
||||||
|
return self.makeIPv4Plan(
|
||||||
|
layerData: layerPacket.data,
|
||||||
|
identityID: data.identityID,
|
||||||
|
inboundBytes: inboundBytes,
|
||||||
|
policyRuntime: policyRuntime
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
SDLLogger.log("[SDLContext] get invalid packet", for: .debug)
|
||||||
|
return .init(inboundBytes: inboundBytes, action: .none)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeARPPlan(layerData: Data, inboundBytes: Int) -> ProcessingPlan {
|
||||||
|
if let arpPacket = ARPPacket(data: layerData) {
|
||||||
|
if arpPacket.targetIP == self.networkAddress.ip {
|
||||||
|
switch arpPacket.opcode {
|
||||||
|
case .request:
|
||||||
|
let response = ARPPacket.arpResponse(for: arpPacket, mac: self.networkAddress.mac, ip: self.networkAddress.ip)
|
||||||
|
return .init(
|
||||||
|
inboundBytes: inboundBytes,
|
||||||
|
action: .sendARPReply(dstMac: arpPacket.senderMAC, data: response.marshal())
|
||||||
|
)
|
||||||
|
case .response:
|
||||||
|
return .init(
|
||||||
|
inboundBytes: inboundBytes,
|
||||||
|
action: .appendARP(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SDLLogger.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(self.networkAddress.ip))")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SDLLogger.log("[SDLContext] get invalid arp packet")
|
||||||
|
}
|
||||||
|
|
||||||
|
return .init(inboundBytes: inboundBytes, action: .none)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeIPv4Plan(layerData: Data, identityID: UInt32, inboundBytes: Int, policyRuntime: PolicyRuntime) -> ProcessingPlan {
|
||||||
|
guard let ipPacket = IPPacket(layerData) else {
|
||||||
|
return .init(inboundBytes: inboundBytes, action: .none)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch policyRuntime.evaluateInbound(srcIdentityID: identityID, ipPacket: ipPacket) {
|
||||||
|
case .allow:
|
||||||
|
return .init(
|
||||||
|
inboundBytes: inboundBytes,
|
||||||
|
action: .writeToTun(packetData: ipPacket.data, identityID: identityID)
|
||||||
|
)
|
||||||
|
case .deny:
|
||||||
|
return .init(
|
||||||
|
inboundBytes: inboundBytes,
|
||||||
|
action: .dropByPolicy(self.makePolicyPacketContext(identityID: identityID, ipPacket: ipPacket))
|
||||||
|
)
|
||||||
|
case .missingPolicy:
|
||||||
|
return .init(
|
||||||
|
inboundBytes: inboundBytes,
|
||||||
|
action: .requestPolicy(self.makePolicyPacketContext(identityID: identityID, ipPacket: ipPacket))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makePolicyPacketContext(identityID: UInt32, ipPacket: IPPacket) -> PolicyPacketContext {
|
||||||
|
let ports: (UInt16?, UInt16?)
|
||||||
|
switch ipPacket.transportPacket {
|
||||||
|
case .tcp(let tcpPacket):
|
||||||
|
ports = (tcpPacket.header.srcPort, tcpPacket.header.dstPort)
|
||||||
|
case .udp(let udpPacket):
|
||||||
|
ports = (udpPacket.srcPort, udpPacket.dstPort)
|
||||||
|
default:
|
||||||
|
ports = (nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PolicyPacketContext(
|
||||||
|
srcIdentityID: identityID,
|
||||||
|
proto: ipPacket.header.proto,
|
||||||
|
srcIP: ipPacket.header.source,
|
||||||
|
dstIP: ipPacket.header.destination,
|
||||||
|
srcPort: ports.0,
|
||||||
|
dstPort: ports.1
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,150 +0,0 @@
|
|||||||
//
|
|
||||||
// PacketInboundProcessor.swift
|
|
||||||
// Tun
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2026/4/14.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
final class PacketInboundProcessor {
|
|
||||||
struct PolicyPacketContext {
|
|
||||||
let srcIdentityID: UInt32
|
|
||||||
let proto: UInt8
|
|
||||||
let srcIP: UInt32
|
|
||||||
let dstIP: UInt32
|
|
||||||
let srcPort: UInt16?
|
|
||||||
let dstPort: UInt16?
|
|
||||||
|
|
||||||
var logDescription: String {
|
|
||||||
let srcPort = self.srcPort.map(String.init) ?? "-"
|
|
||||||
let dstPort = self.dstPort.map(String.init) ?? "-"
|
|
||||||
return "srcIdentityID: \(self.srcIdentityID), proto: \(self.proto), srcIP: \(SDLUtil.int32ToIp(self.srcIP)), dstIP: \(SDLUtil.int32ToIp(self.dstIP)), srcPort: \(srcPort), dstPort: \(dstPort)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ProcessingAction {
|
|
||||||
case sendARPReply(dstMac: Data, data: Data)
|
|
||||||
case appendARP(ip: UInt32, mac: Data)
|
|
||||||
case writeToTun(packetData: Data, identityID: UInt32)
|
|
||||||
case requestPolicy(PolicyPacketContext)
|
|
||||||
case dropByPolicy(PolicyPacketContext)
|
|
||||||
case none
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ProcessingPlan {
|
|
||||||
let inboundBytes: Int
|
|
||||||
let action: ProcessingAction
|
|
||||||
}
|
|
||||||
|
|
||||||
private let networkAddress: SDLConfiguration.NetworkAddress
|
|
||||||
private let dataCipher: CCDataCipher?
|
|
||||||
private let policyRuntime: PolicyRuntime
|
|
||||||
|
|
||||||
init(networkAddress: SDLConfiguration.NetworkAddress,
|
|
||||||
dataCipher: CCDataCipher?,
|
|
||||||
policyRuntime: PolicyRuntime) {
|
|
||||||
self.networkAddress = networkAddress
|
|
||||||
self.dataCipher = dataCipher
|
|
||||||
self.policyRuntime = policyRuntime
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeProcessingPlan(data: SDLData) throws -> ProcessingPlan? {
|
|
||||||
guard let dataCipher = self.dataCipher else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let mac = LayerPacket.MacAddress(data: data.dstMac)
|
|
||||||
guard (data.dstMac == self.networkAddress.mac || mac.isBroadcast() || mac.isMulticast()) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let decryptedData = try dataCipher.decrypt(cipherText: data.data)
|
|
||||||
let layerPacket = try LayerPacketView(layerData: decryptedData)
|
|
||||||
let inboundBytes = decryptedData.count
|
|
||||||
|
|
||||||
// 处理arp请求
|
|
||||||
switch layerPacket.type {
|
|
||||||
case .arp:
|
|
||||||
return self.makeARPPlan(layerData: layerPacket.data, inboundBytes: inboundBytes)
|
|
||||||
case .ipv4:
|
|
||||||
return self.makeIPv4Plan(layerData: layerPacket.data, identityID: data.identityID, inboundBytes: inboundBytes)
|
|
||||||
default:
|
|
||||||
SDLLogger.log("[SDLContext] get invalid packet", for: .debug)
|
|
||||||
return .init(inboundBytes: inboundBytes, action: .none)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func makeARPPlan(layerData: Data, inboundBytes: Int) -> ProcessingPlan {
|
|
||||||
// 判断如果收到的是arp请求
|
|
||||||
if let arpPacket = ARPPacket(data: layerData) {
|
|
||||||
if arpPacket.targetIP == self.networkAddress.ip {
|
|
||||||
switch arpPacket.opcode {
|
|
||||||
case .request:
|
|
||||||
let response = ARPPacket.arpResponse(for: arpPacket, mac: self.networkAddress.mac, ip: self.networkAddress.ip)
|
|
||||||
return .init(
|
|
||||||
inboundBytes: inboundBytes,
|
|
||||||
action: .sendARPReply(dstMac: arpPacket.senderMAC, data: response.marshal())
|
|
||||||
)
|
|
||||||
case .response:
|
|
||||||
return .init(
|
|
||||||
inboundBytes: inboundBytes,
|
|
||||||
action: .appendARP(ip: arpPacket.senderIP, mac: arpPacket.senderMAC)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SDLLogger.log("[SDLContext] get invalid arp packet: \(arpPacket), target_ip: \(SDLUtil.int32ToIp(arpPacket.targetIP)), net ip: \(SDLUtil.int32ToIp(self.networkAddress.ip))")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SDLLogger.log("[SDLContext] get invalid arp packet")
|
|
||||||
}
|
|
||||||
|
|
||||||
return .init(inboundBytes: inboundBytes, action: .none)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func makeIPv4Plan(layerData: Data, identityID: UInt32, inboundBytes: Int) -> ProcessingPlan {
|
|
||||||
// 有数据是通过出口网关转发的,所有只判断是合法的ip包
|
|
||||||
guard let ipPacket = IPPacket(layerData) else {
|
|
||||||
return .init(inboundBytes: inboundBytes, action: .none)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch self.policyRuntime.evaluateInbound(srcIdentityID: identityID, ipPacket: ipPacket) {
|
|
||||||
case .allow:
|
|
||||||
return .init(
|
|
||||||
inboundBytes: inboundBytes,
|
|
||||||
action: .writeToTun(packetData: ipPacket.data, identityID: identityID)
|
|
||||||
)
|
|
||||||
case .deny:
|
|
||||||
return .init(
|
|
||||||
inboundBytes: inboundBytes,
|
|
||||||
action: .dropByPolicy(self.makePolicyPacketContext(identityID: identityID, ipPacket: ipPacket))
|
|
||||||
)
|
|
||||||
case .missingPolicy:
|
|
||||||
return .init(
|
|
||||||
inboundBytes: inboundBytes,
|
|
||||||
action: .requestPolicy(self.makePolicyPacketContext(identityID: identityID, ipPacket: ipPacket))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func makePolicyPacketContext(identityID: UInt32, ipPacket: IPPacket) -> PolicyPacketContext {
|
|
||||||
let ports: (UInt16?, UInt16?)
|
|
||||||
switch ipPacket.transportPacket {
|
|
||||||
case .tcp(let tcpPacket):
|
|
||||||
ports = (tcpPacket.header.srcPort, tcpPacket.header.dstPort)
|
|
||||||
case .udp(let udpPacket):
|
|
||||||
ports = (udpPacket.srcPort, udpPacket.dstPort)
|
|
||||||
default:
|
|
||||||
ports = (nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
return PolicyPacketContext(
|
|
||||||
srcIdentityID: identityID,
|
|
||||||
proto: ipPacket.header.proto,
|
|
||||||
srcIP: ipPacket.header.source,
|
|
||||||
dstIP: ipPacket.header.destination,
|
|
||||||
srcPort: ports.0,
|
|
||||||
dstPort: ports.1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user