处理权限逻辑
This commit is contained in:
parent
e9392545d3
commit
f7c70d0245
@ -69,11 +69,13 @@ actor PacketInboundActor {
|
|||||||
let packet = NEPacket(data: packetData, protocolFamily: 2)
|
let packet = NEPacket(data: packetData, protocolFamily: 2)
|
||||||
self.provider.packetFlow.writePacketObjects([packet])
|
self.provider.packetFlow.writePacketObjects([packet])
|
||||||
SDLLogger.log("[PacketInboundActor] hole identity: \(identityID), allow, data count: \(packetData.count)", for: .trace)
|
SDLLogger.log("[PacketInboundActor] hole identity: \(identityID), allow, data count: \(packetData.count)", for: .trace)
|
||||||
case .requestPolicy(let srcIdentityID):
|
case .requestPolicy(let context):
|
||||||
SDLLogger.log("[PacketInboundActor] not found identity: \(srcIdentityID) ruleMap", for: .debug)
|
SDLLogger.log("[PacketInboundActor] policy miss, \(context.logDescription)", for: .debug)
|
||||||
if let queryData = await self.policyService.makePolicyRequest(srcIdentityID: srcIdentityID) {
|
if let queryData = await self.policyService.makePolicyRequest(srcIdentityID: context.srcIdentityID) {
|
||||||
await self.superServiceProxy.send(type: .policyRequest, data: queryData)
|
await self.superServiceProxy.send(type: .policyRequest, data: queryData)
|
||||||
}
|
}
|
||||||
|
case .dropByPolicy(let context):
|
||||||
|
SDLLogger.log("[PacketInboundActor] policy denied, \(context.logDescription)", for: .trace)
|
||||||
case .none:
|
case .none:
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,27 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class PacketInboundProcessor {
|
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 {
|
enum ProcessingAction {
|
||||||
case sendARPReply(dstMac: Data, data: Data)
|
case sendARPReply(dstMac: Data, data: Data)
|
||||||
case appendARP(ip: UInt32, mac: Data)
|
case appendARP(ip: UInt32, mac: Data)
|
||||||
case writeToTun(packetData: Data, identityID: UInt32)
|
case writeToTun(packetData: Data, identityID: UInt32)
|
||||||
case requestPolicy(srcIdentityID: UInt32)
|
case requestPolicy(PolicyPacketContext)
|
||||||
|
case dropByPolicy(PolicyPacketContext)
|
||||||
case none
|
case none
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,16 +108,43 @@ final class PacketInboundProcessor {
|
|||||||
return .init(inboundBytes: inboundBytes, action: .none)
|
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(
|
return .init(
|
||||||
inboundBytes: inboundBytes,
|
inboundBytes: inboundBytes,
|
||||||
action: .writeToTun(packetData: ipPacket.data, identityID: identityID)
|
action: .writeToTun(packetData: ipPacket.data, identityID: identityID)
|
||||||
)
|
)
|
||||||
}
|
case .deny:
|
||||||
|
|
||||||
return .init(
|
return .init(
|
||||||
inboundBytes: inboundBytes,
|
inboundBytes: inboundBytes,
|
||||||
action: .requestPolicy(srcIdentityID: identityID)
|
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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,10 @@ actor PolicyRuleStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makePolicyRequest(srcIdentityId: UInt32, dstIdentityId: UInt32) -> Data? {
|
func makePolicyRequest(srcIdentityId: UInt32, dstIdentityId: UInt32) -> Data? {
|
||||||
|
guard self.ruleMapByIdentity[srcIdentityId] == nil else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
guard !coolingDown.contains(srcIdentityId) else {
|
guard !coolingDown.contains(srcIdentityId) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -75,6 +79,7 @@ actor PolicyRuleStore {
|
|||||||
ruleMap[proto, default: [:]][port] = true
|
ruleMap[proto, default: [:]][port] = true
|
||||||
}
|
}
|
||||||
self.ruleMapByIdentity[id] = PolicyRuleMap(version: version, ruleMap: ruleMap)
|
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()
|
let snapshot = compileSnapshot()
|
||||||
|
|||||||
@ -8,6 +8,12 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct PolicyRuntime: @unchecked Sendable {
|
struct PolicyRuntime: @unchecked Sendable {
|
||||||
|
enum InboundDecision {
|
||||||
|
case allow
|
||||||
|
case deny
|
||||||
|
case missingPolicy
|
||||||
|
}
|
||||||
|
|
||||||
private let policyRuleSnapshot: PolicyRuleSnapshot
|
private let policyRuleSnapshot: PolicyRuleSnapshot
|
||||||
private let flowSessionTable: FlowSessionTable
|
private let flowSessionTable: FlowSessionTable
|
||||||
|
|
||||||
@ -16,27 +22,32 @@ struct PolicyRuntime: @unchecked Sendable {
|
|||||||
self.flowSessionTable = flowSessionTable
|
self.flowSessionTable = flowSessionTable
|
||||||
}
|
}
|
||||||
|
|
||||||
func allowsInbound(srcIdentityID: UInt32, ipPacket: IPPacket) -> Bool {
|
func evaluateInbound(srcIdentityID: UInt32, ipPacket: IPPacket) -> InboundDecision {
|
||||||
if let reverseFlowSession = ipPacket.flowSession()?.reverse(),
|
if let reverseFlowSession = ipPacket.flowSession()?.reverse(),
|
||||||
self.flowSessionTable.hasSession(reverseFlowSession) {
|
self.flowSessionTable.hasSession(reverseFlowSession) {
|
||||||
self.flowSessionTable.updateSession(reverseFlowSession)
|
self.flowSessionTable.updateSession(reverseFlowSession)
|
||||||
return true
|
return .allow
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.allowsByRule(srcIdentityID: srcIdentityID, ipPacket: ipPacket)
|
if case .icmp = ipPacket.transportPacket {
|
||||||
|
return .allow
|
||||||
}
|
}
|
||||||
|
|
||||||
private func allowsByRule(srcIdentityID: UInt32, ipPacket: IPPacket) -> Bool {
|
guard let ruleMap = self.policyRuleSnapshot.lookup(srcIdentityID) else {
|
||||||
let ruleMap = self.policyRuleSnapshot.lookup(srcIdentityID)
|
return .missingPolicy
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.isAllowedByRule(ruleMap: ruleMap, ipPacket: ipPacket) ? .allow : .deny
|
||||||
|
}
|
||||||
|
|
||||||
|
private func isAllowedByRule(ruleMap: PolicyRuleMap, ipPacket: IPPacket) -> Bool {
|
||||||
let proto = ipPacket.header.proto
|
let proto = ipPacket.header.proto
|
||||||
|
|
||||||
switch ipPacket.transportPacket {
|
switch ipPacket.transportPacket {
|
||||||
case .tcp(let tcpPacket):
|
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):
|
case .udp(let udpPacket):
|
||||||
return ruleMap?.isAllow(proto: proto, port: udpPacket.dstPort) ?? false
|
return ruleMap.isAllow(proto: proto, port: udpPacket.dstPort)
|
||||||
case .icmp:
|
|
||||||
return true
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user