处理权限逻辑

This commit is contained in:
anlicheng 2026-05-21 15:15:32 +08:00
parent e9392545d3
commit f7c70d0245
4 changed files with 78 additions and 18 deletions

View File

@ -69,11 +69,13 @@ actor PacketInboundActor {
let packet = NEPacket(data: packetData, protocolFamily: 2)
self.provider.packetFlow.writePacketObjects([packet])
SDLLogger.log("[PacketInboundActor] hole identity: \(identityID), allow, data count: \(packetData.count)", for: .trace)
case .requestPolicy(let srcIdentityID):
SDLLogger.log("[PacketInboundActor] not found identity: \(srcIdentityID) ruleMap", for: .debug)
if let queryData = await self.policyService.makePolicyRequest(srcIdentityID: srcIdentityID) {
case .requestPolicy(let context):
SDLLogger.log("[PacketInboundActor] policy miss, \(context.logDescription)", for: .debug)
if let queryData = await self.policyService.makePolicyRequest(srcIdentityID: context.srcIdentityID) {
await self.superServiceProxy.send(type: .policyRequest, data: queryData)
}
case .dropByPolicy(let context):
SDLLogger.log("[PacketInboundActor] policy denied, \(context.logDescription)", for: .trace)
case .none:
()
}

View File

@ -8,12 +8,27 @@
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(srcIdentityID: UInt32)
case requestPolicy(PolicyPacketContext)
case dropByPolicy(PolicyPacketContext)
case none
}
@ -93,16 +108,43 @@ final class PacketInboundProcessor {
return .init(inboundBytes: inboundBytes, action: .none)
}
if self.policyRuntime.allowsInbound(srcIdentityID: identityID, ipPacket: ipPacket) {
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 .init(
inboundBytes: inboundBytes,
action: .requestPolicy(srcIdentityID: identityID)
return PolicyPacketContext(
srcIdentityID: identityID,
proto: ipPacket.header.proto,
srcIP: ipPacket.header.source,
dstIP: ipPacket.header.destination,
srcPort: ports.0,
dstPort: ports.1
)
}
}

View File

@ -36,6 +36,10 @@ actor PolicyRuleStore {
}
func makePolicyRequest(srcIdentityId: UInt32, dstIdentityId: UInt32) -> Data? {
guard self.ruleMapByIdentity[srcIdentityId] == nil else {
return nil
}
guard !coolingDown.contains(srcIdentityId) else {
return nil
}
@ -75,6 +79,7 @@ actor PolicyRuleStore {
ruleMap[proto, default: [:]][port] = true
}
self.ruleMapByIdentity[id] = PolicyRuleMap(version: version, ruleMap: ruleMap)
SDLLogger.log("[PolicyRuleStore] apply policy response, srcIdentityID: \(id), version: \(version), rulesCount: \(ruleMap.reduce(0) { $0 + $1.value.count })", for: .debug)
//
let snapshot = compileSnapshot()

View File

@ -8,6 +8,12 @@
import Foundation
struct PolicyRuntime: @unchecked Sendable {
enum InboundDecision {
case allow
case deny
case missingPolicy
}
private let policyRuleSnapshot: PolicyRuleSnapshot
private let flowSessionTable: FlowSessionTable
@ -16,27 +22,32 @@ struct PolicyRuntime: @unchecked Sendable {
self.flowSessionTable = flowSessionTable
}
func allowsInbound(srcIdentityID: UInt32, ipPacket: IPPacket) -> Bool {
func evaluateInbound(srcIdentityID: UInt32, ipPacket: IPPacket) -> InboundDecision {
if let reverseFlowSession = ipPacket.flowSession()?.reverse(),
self.flowSessionTable.hasSession(reverseFlowSession) {
self.flowSessionTable.updateSession(reverseFlowSession)
return true
return .allow
}
return self.allowsByRule(srcIdentityID: srcIdentityID, ipPacket: ipPacket)
if case .icmp = ipPacket.transportPacket {
return .allow
}
guard let ruleMap = self.policyRuleSnapshot.lookup(srcIdentityID) else {
return .missingPolicy
}
return self.isAllowedByRule(ruleMap: ruleMap, ipPacket: ipPacket) ? .allow : .deny
}
private func allowsByRule(srcIdentityID: UInt32, ipPacket: IPPacket) -> Bool {
let ruleMap = self.policyRuleSnapshot.lookup(srcIdentityID)
private func isAllowedByRule(ruleMap: PolicyRuleMap, ipPacket: IPPacket) -> Bool {
let proto = ipPacket.header.proto
switch ipPacket.transportPacket {
case .tcp(let tcpPacket):
return ruleMap?.isAllow(proto: proto, port: tcpPacket.header.dstPort) ?? false
return ruleMap.isAllow(proto: proto, port: tcpPacket.header.dstPort)
case .udp(let udpPacket):
return ruleMap?.isAllow(proto: proto, port: udpPacket.dstPort) ?? false
case .icmp:
return true
return ruleMap.isAllow(proto: proto, port: udpPacket.dstPort)
default:
return false
}