ios proxy pass domains (#527)

This commit is contained in:
wanghongenpin
2026-02-15 01:25:05 +08:00
parent a3e744ee2e
commit c4d3421373
6 changed files with 42 additions and 11 deletions

View File

@@ -24,6 +24,15 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
let proxyPort = conf["proxyPort"] as! Int
let ipProxy = conf["ipProxy"] as! Bool? ?? false
// parse proxyPassDomains: accept either [String] or comma-separated String
var proxyPassDomains: [String]? = nil
if let arr = conf["proxyPassDomains"] as? [String] {
proxyPassDomains = arr.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }.filter { !$0.isEmpty }
} else if let csv = conf["proxyPassDomains"] as? String {
let list = csv.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }.filter { !$0.isEmpty }
proxyPassDomains = list.isEmpty ? nil : list
}
// let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1")
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: host)
NSLog(conf.debugDescription)
@@ -57,8 +66,12 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
proxySettings.httpServer = NEProxyServer(address: host, port: proxyPort)
proxySettings.httpsEnabled = true
proxySettings.httpsServer = NEProxyServer(address: host, port: proxyPort)
// If a proxyPassDomains list was provided, use it as the exceptionList so these domains bypass the proxy.
if let pass = proxyPassDomains {
proxySettings.exceptionList = pass
}
proxySettings.matchDomains = [""]
networkSettings.proxySettings = proxySettings
networkSettings.ipv4Settings = ipv4Settings

View File

@@ -21,10 +21,10 @@ import NetworkExtension
} else if ("restartVpn" == call.method){
let arguments = call.arguments as? Dictionary<String, AnyObject>
// VpnManager.shared.disconnect()
VpnManager.shared.restartConnect(host: arguments?["proxyHost"] as? String ,port: arguments?["proxyPort"] as? Int, ipProxy: arguments?["ipProxy"] as? Bool)
VpnManager.shared.restartConnect(host: arguments?["proxyHost"] as? String ,port: arguments?["proxyPort"] as? Int, ipProxy: arguments?["ipProxy"] as? Bool, proxyPassDomains: arguments?["proxyPassDomains"] as? [String])
} else {
let arguments = call.arguments as? Dictionary<String, AnyObject>
VpnManager.shared.connect(host: arguments?["proxyHost"] as? String ,port: arguments?["proxyPort"] as? Int, ipProxy: arguments?["ipProxy"] as? Bool)
VpnManager.shared.connect(host: arguments?["proxyHost"] as? String ,port: arguments?["proxyPort"] as? Int, ipProxy: arguments?["ipProxy"] as? Bool, proxyPassDomains: arguments?["proxyPassDomains"] as? [String])
}
})

View File

@@ -17,6 +17,7 @@ class VpnManager{
public var proxyHost: String = "127.0.0.1"
public var proxyPort: Int = 9099
public var ipProxy: Bool = false
public var proxyPassDomains: [String]?
static let shared = VpnManager()
var observerAdded: Bool = false
@@ -103,7 +104,11 @@ extension VpnManager{
conf["proxyHost"] = self.proxyHost as AnyObject
conf["proxyPort"] = self.proxyPort as AnyObject
conf["ipProxy"] = self.ipProxy as AnyObject
// Bridge Swift [String] to NSArray (Objective-C) before inserting into AnyObject dictionary
if let passDomains = self.proxyPassDomains {
conf["proxyPassDomains"] = passDomains as NSArray
}
let orignConf = manager.protocolConfiguration as! NETunnelProviderProtocol
orignConf.providerConfiguration = conf
@@ -147,10 +152,11 @@ extension VpnManager{
// Actions
extension VpnManager{
func connect(host: String?, port: Int?, ipProxy: Bool? = false) {
func connect(host: String?, port: Int?, ipProxy: Bool? = false, proxyPassDomains: [String]? = nil) {
self.proxyHost = host ?? self.proxyHost
self.proxyPort = port ?? self.proxyPort
self.ipProxy = ipProxy ?? false
self.proxyPassDomains = proxyPassDomains ?? self.proxyPassDomains
self.loadAndCreatePrividerManager { (manager) in
guard let manager = manager else{return}
@@ -163,7 +169,7 @@ extension VpnManager{
}
}
func restartConnect(host: String?, port: Int?, ipProxy: Bool? = false) {
func restartConnect(host: String?, port: Int?, ipProxy: Bool? = false, proxyPassDomains: [String]? = nil) {
self.proxyHost = host ?? self.proxyHost
self.proxyPort = port ?? self.proxyPort
self.ipProxy = ipProxy ?? false
@@ -173,7 +179,7 @@ extension VpnManager{
activeVPN = nil
}
self.connect(host: host, port: port, ipProxy: ipProxy)
self.connect(host: host, port: port, ipProxy: ipProxy, proxyPassDomains: proxyPassDomains)
}
func disconnect() {

View File

@@ -55,6 +55,9 @@ class SystemProxy {
if (Platform.isAndroid) {
return '192.168.0.0/16;10.0.0.0/8;172.16.0.0/12;127.0.0.1;localhost';
}
if (Platform.isIOS) {
return '192.168.0.0/16;10.0.0.0/8;172.16.0.0/12;127.0.0.1;localhost;*.local;timestamp.apple.com';
}
return '';
}

View File

@@ -280,7 +280,8 @@ class SettingPage extends StatelessWidget {
children: [
Text(localizations.proxyIgnoreDomain, style: const TextStyle(fontSize: 14)),
const SizedBox(height: 3),
Text(isEn ? "Use ';' to separate multiple entries": "多个使用;分割", style: TextStyle(fontSize: 11, color: Colors.grey.shade600)),
Text(isEn ? "Use ';' to separate multiple entries" : "多个使用;分割",
style: TextStyle(fontSize: 11, color: Colors.grey.shade600)),
],
),
Padding(
@@ -299,10 +300,14 @@ class SettingPage extends StatelessWidget {
textInputAction: TextInputAction.done,
style: const TextStyle(fontSize: 13),
controller: textEditingController,
onSubmitted: (_) {
configuration.proxyPassDomains = textEditingController.text;
proxyServer.configuration.flushConfig();
},
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(10),
border: OutlineInputBorder(),
),
contentPadding: EdgeInsets.all(10),
border: OutlineInputBorder(),
),
maxLines: 5,
minLines: 1)),
// const SizedBox(height: 10),

View File

@@ -289,6 +289,10 @@ class _SettingPage extends StatelessWidget {
textInputAction: TextInputAction.done,
style: const TextStyle(fontSize: 13),
controller: textEditingController,
onSubmitted: (_) {
configuration.proxyPassDomains = textEditingController.text;
proxyServer.configuration.flushConfig();
},
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(10),
border: OutlineInputBorder()),