Add iPad support, auto-pinning, and comprehensive logging
- Adaptive iPhone/iPad layout with NavigationSplitView sidebar - Auto-detect SSL-pinned domains, fall back to passthrough - Certificate install via local HTTP server (Safari profile flow) - App Group-backed CA, per-domain leaf cert LRU cache - DB-backed config repository, Darwin notification throttling - Rules engine, breakpoint rules, pinned domain tracking - os.Logger instrumentation across tunnel/proxy/mitm/capture/cert/rules/db/ipc/ui - Fix dyld framework embed, race conditions, thread safety
This commit is contained in:
@@ -117,6 +117,26 @@ extension CapturedTraffic {
|
||||
return dict
|
||||
}
|
||||
|
||||
public func requestHeaderValue(named name: String) -> String? {
|
||||
HTTPBodyDecoder.headerValue(named: name, in: decodedRequestHeaders)
|
||||
}
|
||||
|
||||
public func responseHeaderValue(named name: String) -> String? {
|
||||
HTTPBodyDecoder.headerValue(named: name, in: decodedResponseHeaders)
|
||||
}
|
||||
|
||||
public var decodedResponseBodyData: Data? {
|
||||
HTTPBodyDecoder.decodedBodyData(from: responseBody, headers: decodedResponseHeaders)
|
||||
}
|
||||
|
||||
public var searchableResponseBodyText: String? {
|
||||
HTTPBodyDecoder.searchableText(from: responseBody, headers: decodedResponseHeaders)
|
||||
}
|
||||
|
||||
public var responseBodyDecodingHint: String {
|
||||
HTTPBodyDecoder.decodingHint(for: responseBody, headers: decodedResponseHeaders)
|
||||
}
|
||||
|
||||
public var decodedQueryParameters: [String: String] {
|
||||
guard let data = queryParameters?.data(using: .utf8),
|
||||
let dict = try? JSONDecoder().decode([String: String].self, from: data) else {
|
||||
|
||||
24
ProxyCore/Sources/DataLayer/Models/PinnedDomain.swift
Normal file
24
ProxyCore/Sources/DataLayer/Models/PinnedDomain.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
/// A domain detected as using SSL pinning. MITM will automatically skip these
|
||||
/// and fall back to passthrough mode.
|
||||
public struct PinnedDomain: Codable, FetchableRecord, MutablePersistableRecord, Identifiable, Sendable {
|
||||
public var id: Int64?
|
||||
public var domain: String
|
||||
public var reason: String?
|
||||
public var detectedAt: Double
|
||||
|
||||
public static let databaseTableName = "pinned_domains"
|
||||
|
||||
public mutating func didInsert(_ inserted: InsertionSuccess) {
|
||||
id = inserted.rowID
|
||||
}
|
||||
|
||||
public init(id: Int64? = nil, domain: String, reason: String? = nil, detectedAt: Double = Date().timeIntervalSince1970) {
|
||||
self.id = id
|
||||
self.domain = domain
|
||||
self.reason = reason
|
||||
self.detectedAt = detectedAt
|
||||
}
|
||||
}
|
||||
35
ProxyCore/Sources/DataLayer/Models/ProxyConfiguration.swift
Normal file
35
ProxyCore/Sources/DataLayer/Models/ProxyConfiguration.swift
Normal file
@@ -0,0 +1,35 @@
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
public struct ProxyConfiguration: Codable, FetchableRecord, MutablePersistableRecord, Sendable {
|
||||
public static let databaseTableName = "proxy_configuration"
|
||||
|
||||
public var id: Int64
|
||||
public var sslProxyingEnabled: Bool
|
||||
public var blockListEnabled: Bool
|
||||
public var breakpointEnabled: Bool
|
||||
public var noCachingEnabled: Bool
|
||||
public var dnsSpoofingEnabled: Bool
|
||||
public var hideSystemTraffic: Bool
|
||||
public var updatedAt: Double
|
||||
|
||||
public init(
|
||||
id: Int64 = 1,
|
||||
sslProxyingEnabled: Bool = false,
|
||||
blockListEnabled: Bool = false,
|
||||
breakpointEnabled: Bool = false,
|
||||
noCachingEnabled: Bool = false,
|
||||
dnsSpoofingEnabled: Bool = false,
|
||||
hideSystemTraffic: Bool = false,
|
||||
updatedAt: Double = Date().timeIntervalSince1970
|
||||
) {
|
||||
self.id = id
|
||||
self.sslProxyingEnabled = sslProxyingEnabled
|
||||
self.blockListEnabled = blockListEnabled
|
||||
self.breakpointEnabled = breakpointEnabled
|
||||
self.noCachingEnabled = noCachingEnabled
|
||||
self.dnsSpoofingEnabled = dnsSpoofingEnabled
|
||||
self.hideSystemTraffic = hideSystemTraffic
|
||||
self.updatedAt = updatedAt
|
||||
}
|
||||
}
|
||||
61
ProxyCore/Sources/DataLayer/Models/ProxyRuntimeStatus.swift
Normal file
61
ProxyCore/Sources/DataLayer/Models/ProxyRuntimeStatus.swift
Normal file
@@ -0,0 +1,61 @@
|
||||
import Foundation
|
||||
import GRDB
|
||||
|
||||
public enum ProxyRuntimeState: String, Codable, Sendable {
|
||||
case stopped
|
||||
case starting
|
||||
case running
|
||||
case failed
|
||||
}
|
||||
|
||||
public struct ProxyRuntimeStatus: Codable, FetchableRecord, MutablePersistableRecord, Sendable {
|
||||
public static let databaseTableName = "proxy_runtime_status"
|
||||
|
||||
public var id: Int64
|
||||
public var tunnelState: String
|
||||
public var proxyHost: String?
|
||||
public var proxyPort: Int?
|
||||
public var caFingerprint: String?
|
||||
public var lastProxyError: String?
|
||||
public var lastMITMError: String?
|
||||
public var lastConnectError: String?
|
||||
public var lastSuccessfulMITMDomain: String?
|
||||
public var lastSuccessfulMITMAt: Double?
|
||||
public var lastExtensionStartAt: Double?
|
||||
public var lastExtensionStopAt: Double?
|
||||
public var updatedAt: Double
|
||||
|
||||
public init(
|
||||
id: Int64 = 1,
|
||||
tunnelState: ProxyRuntimeState = .stopped,
|
||||
proxyHost: String? = nil,
|
||||
proxyPort: Int? = nil,
|
||||
caFingerprint: String? = nil,
|
||||
lastProxyError: String? = nil,
|
||||
lastMITMError: String? = nil,
|
||||
lastConnectError: String? = nil,
|
||||
lastSuccessfulMITMDomain: String? = nil,
|
||||
lastSuccessfulMITMAt: Double? = nil,
|
||||
lastExtensionStartAt: Double? = nil,
|
||||
lastExtensionStopAt: Double? = nil,
|
||||
updatedAt: Double = Date().timeIntervalSince1970
|
||||
) {
|
||||
self.id = id
|
||||
self.tunnelState = tunnelState.rawValue
|
||||
self.proxyHost = proxyHost
|
||||
self.proxyPort = proxyPort
|
||||
self.caFingerprint = caFingerprint
|
||||
self.lastProxyError = lastProxyError
|
||||
self.lastMITMError = lastMITMError
|
||||
self.lastConnectError = lastConnectError
|
||||
self.lastSuccessfulMITMDomain = lastSuccessfulMITMDomain
|
||||
self.lastSuccessfulMITMAt = lastSuccessfulMITMAt
|
||||
self.lastExtensionStartAt = lastExtensionStartAt
|
||||
self.lastExtensionStopAt = lastExtensionStopAt
|
||||
self.updatedAt = updatedAt
|
||||
}
|
||||
|
||||
public var state: ProxyRuntimeState {
|
||||
ProxyRuntimeState(rawValue: tunnelState) ?? .stopped
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user