This commit is contained in:
Owen Qwen
2026-08-31 16:44:54 -05:00
parent e71b3ada71
commit 5f99d9b137
21 changed files with 1045 additions and 47 deletions
+30 -6
View File
@@ -1,9 +1,24 @@
import Foundation
public enum FirewallProtocol: String, Codable, CaseIterable, Sendable {
case overlay, tcp, udp
}
public struct FirewallRule: Codable, Hashable, Sendable {
public let protocolKind: FirewallProtocol
public let port: UInt16
public let source: MeshAddress?
public init(port: UInt16, source: MeshAddress?) { self.port = port; self.source = source }
public init(protocolKind: FirewallProtocol = .overlay, port: UInt16, source: MeshAddress?) {
self.protocolKind = protocolKind; self.port = port; self.source = source
}
private enum CodingKeys: String, CodingKey { case protocolKind = "protocol", port, source }
public init(from decoder: Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
protocolKind = try c.decodeIfPresent(FirewallProtocol.self, forKey: .protocolKind) ?? .overlay
port = try c.decode(UInt16.self, forKey: .port)
source = try c.decodeIfPresent(MeshAddress.self, forKey: .source)
}
}
public final class MeshFirewall: @unchecked Sendable {
@@ -11,11 +26,20 @@ public final class MeshFirewall: @unchecked Sendable {
private let lock = NSLock()
public init(rules: Set<FirewallRule> = []) { self.rules = rules }
public func allows(port: UInt16, source: MeshAddress) -> Bool {
public func allows(protocol protocolKind: FirewallProtocol = .overlay, port: UInt16, source: MeshAddress) -> Bool {
lock.lock(); defer { lock.unlock() }
return rules.contains(FirewallRule(port: port, source: nil)) || rules.contains(FirewallRule(port: port, source: source))
return rules.contains(FirewallRule(protocolKind: protocolKind, port: port, source: nil)) ||
rules.contains(FirewallRule(protocolKind: protocolKind, port: port, source: source))
}
public func allow(protocol protocolKind: FirewallProtocol = .overlay, port: UInt16, source: MeshAddress?) {
lock.lock(); rules.insert(.init(protocolKind: protocolKind, port: port, source: source)); lock.unlock()
}
public func revoke(protocol protocolKind: FirewallProtocol = .overlay, port: UInt16, source: MeshAddress?) {
lock.lock(); rules.remove(.init(protocolKind: protocolKind, port: port, source: source)); lock.unlock()
}
public func allRules() -> [FirewallRule] {
lock.lock(); defer { lock.unlock() }
return rules.sorted { ($0.protocolKind.rawValue, $0.port, $0.source?.description ?? "") <
($1.protocolKind.rawValue, $1.port, $1.source?.description ?? "") }
}
public func allow(port: UInt16, source: MeshAddress?) { lock.lock(); rules.insert(.init(port: port, source: source)); lock.unlock() }
public func revoke(port: UInt16, source: MeshAddress?) { lock.lock(); rules.remove(.init(port: port, source: source)); lock.unlock() }
public func allRules() -> [FirewallRule] { lock.lock(); defer { lock.unlock() }; return rules.sorted { $0.port < $1.port } }
}