Merge pull request #125 from ThinkChaos/proxy_auto_conf
Add Proxy Auto-Configuration (PAC) support
This commit is contained in:
commit
7d0cba8df8
|
@ -183,6 +183,8 @@ extension OpenVPNTunnelProvider {
|
||||||
|
|
||||||
static let httpsProxy = "HTTPSProxy"
|
static let httpsProxy = "HTTPSProxy"
|
||||||
|
|
||||||
|
static let proxyAutoConfigurationURL = "ProxyAutoConfigurationURL"
|
||||||
|
|
||||||
static let proxyBypassDomains = "ProxyBypassDomains"
|
static let proxyBypassDomains = "ProxyBypassDomains"
|
||||||
|
|
||||||
static let routingPolicies = "RoutingPolicies"
|
static let routingPolicies = "RoutingPolicies"
|
||||||
|
@ -603,6 +605,9 @@ private extension OpenVPN.Configuration {
|
||||||
if let httpsProxy = httpsProxy {
|
if let httpsProxy = httpsProxy {
|
||||||
dict[S.httpsProxy] = httpsProxy.rawValue
|
dict[S.httpsProxy] = httpsProxy.rawValue
|
||||||
}
|
}
|
||||||
|
if let proxyAutoConfigurationURL = proxyAutoConfigurationURL {
|
||||||
|
dict[S.proxyAutoConfigurationURL] = proxyAutoConfigurationURL.absoluteString
|
||||||
|
}
|
||||||
if let proxyBypassDomains = proxyBypassDomains {
|
if let proxyBypassDomains = proxyBypassDomains {
|
||||||
dict[S.proxyBypassDomains] = proxyBypassDomains
|
dict[S.proxyBypassDomains] = proxyBypassDomains
|
||||||
}
|
}
|
||||||
|
@ -681,6 +686,9 @@ private extension OpenVPN.Configuration {
|
||||||
if let httpsProxy = httpsProxy {
|
if let httpsProxy = httpsProxy {
|
||||||
log.info("\tHTTPS proxy: \(httpsProxy.maskedDescription)")
|
log.info("\tHTTPS proxy: \(httpsProxy.maskedDescription)")
|
||||||
}
|
}
|
||||||
|
if let proxyAutoConfigurationURL = proxyAutoConfigurationURL {
|
||||||
|
log.info("\tPAC: \(proxyAutoConfigurationURL)")
|
||||||
|
}
|
||||||
if let proxyBypassDomains = proxyBypassDomains {
|
if let proxyBypassDomains = proxyBypassDomains {
|
||||||
log.info("\tProxy bypass domains: \(proxyBypassDomains.maskedDescription)")
|
log.info("\tProxy bypass domains: \(proxyBypassDomains.maskedDescription)")
|
||||||
}
|
}
|
||||||
|
|
|
@ -514,6 +514,9 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
|
||||||
if let proxy = options.httpsProxy {
|
if let proxy = options.httpsProxy {
|
||||||
log.info("\t\tHTTPS: \(proxy.maskedDescription)")
|
log.info("\t\tHTTPS: \(proxy.maskedDescription)")
|
||||||
}
|
}
|
||||||
|
if let pacURL = options.proxyAutoConfigurationURL {
|
||||||
|
log.info("\t\tPAC: \(pacURL)")
|
||||||
|
}
|
||||||
if let bypass = options.proxyBypassDomains {
|
if let bypass = options.proxyBypassDomains {
|
||||||
log.info("\t\tBypass domains: \(bypass.maskedDescription)")
|
log.info("\t\tBypass domains: \(bypass.maskedDescription)")
|
||||||
}
|
}
|
||||||
|
@ -677,6 +680,14 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
|
||||||
proxySettings?.httpEnabled = true
|
proxySettings?.httpEnabled = true
|
||||||
log.info("Routing: Setting HTTP proxy \(httpProxy.address.maskedDescription):\(httpProxy.port)")
|
log.info("Routing: Setting HTTP proxy \(httpProxy.address.maskedDescription):\(httpProxy.port)")
|
||||||
}
|
}
|
||||||
|
if let pacURL = cfg.sessionConfiguration.proxyAutoConfigurationURL ?? options.proxyAutoConfigurationURL {
|
||||||
|
if proxySettings == nil {
|
||||||
|
proxySettings = NEProxySettings()
|
||||||
|
}
|
||||||
|
proxySettings?.proxyAutoConfigurationURL = pacURL
|
||||||
|
proxySettings?.autoProxyConfigurationEnabled = true
|
||||||
|
log.info("Routing: Setting PAC \(pacURL)")
|
||||||
|
}
|
||||||
|
|
||||||
// only set if there is a proxy (proxySettings set to non-nil above)
|
// only set if there is a proxy (proxySettings set to non-nil above)
|
||||||
if let bypass = cfg.sessionConfiguration.proxyBypassDomains ?? options.proxyBypassDomains {
|
if let bypass = cfg.sessionConfiguration.proxyBypassDomains ?? options.proxyBypassDomains {
|
||||||
|
|
|
@ -247,6 +247,9 @@ extension OpenVPN {
|
||||||
/// The search domain.
|
/// The search domain.
|
||||||
public var searchDomain: String?
|
public var searchDomain: String?
|
||||||
|
|
||||||
|
/// The Proxy Auto-Configuration (PAC) url.
|
||||||
|
public var proxyAutoConfigurationURL: URL?
|
||||||
|
|
||||||
/// The HTTP proxy.
|
/// The HTTP proxy.
|
||||||
public var httpProxy: Proxy?
|
public var httpProxy: Proxy?
|
||||||
|
|
||||||
|
@ -295,6 +298,7 @@ extension OpenVPN {
|
||||||
searchDomain: searchDomain,
|
searchDomain: searchDomain,
|
||||||
httpProxy: httpProxy,
|
httpProxy: httpProxy,
|
||||||
httpsProxy: httpsProxy,
|
httpsProxy: httpsProxy,
|
||||||
|
proxyAutoConfigurationURL: proxyAutoConfigurationURL,
|
||||||
proxyBypassDomains: proxyBypassDomains,
|
proxyBypassDomains: proxyBypassDomains,
|
||||||
routingPolicies: routingPolicies
|
routingPolicies: routingPolicies
|
||||||
)
|
)
|
||||||
|
@ -396,6 +400,9 @@ extension OpenVPN {
|
||||||
/// - Seealso: `ConfigurationBuilder.httpsProxy`
|
/// - Seealso: `ConfigurationBuilder.httpsProxy`
|
||||||
public let httpsProxy: Proxy?
|
public let httpsProxy: Proxy?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.proxyAutoConfigurationURL`
|
||||||
|
public let proxyAutoConfigurationURL: URL?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.proxyBypassDomains`
|
/// - Seealso: `ConfigurationBuilder.proxyBypassDomains`
|
||||||
public let proxyBypassDomains: [String]?
|
public let proxyBypassDomains: [String]?
|
||||||
|
|
||||||
|
@ -457,6 +464,7 @@ extension OpenVPN.Configuration {
|
||||||
builder.searchDomain = searchDomain
|
builder.searchDomain = searchDomain
|
||||||
builder.httpProxy = httpProxy
|
builder.httpProxy = httpProxy
|
||||||
builder.httpsProxy = httpsProxy
|
builder.httpsProxy = httpsProxy
|
||||||
|
builder.proxyAutoConfigurationURL = proxyAutoConfigurationURL
|
||||||
builder.proxyBypassDomains = proxyBypassDomains
|
builder.proxyBypassDomains = proxyBypassDomains
|
||||||
builder.routingPolicies = routingPolicies
|
builder.routingPolicies = routingPolicies
|
||||||
return builder
|
return builder
|
||||||
|
|
|
@ -96,7 +96,7 @@ extension OpenVPN {
|
||||||
|
|
||||||
static let domain = NSRegularExpression("^dhcp-option +DOMAIN +[^ ]+")
|
static let domain = NSRegularExpression("^dhcp-option +DOMAIN +[^ ]+")
|
||||||
|
|
||||||
static let proxy = NSRegularExpression("^dhcp-option +PROXY_(HTTPS?) +[^ ]+ +\\d+")
|
static let proxy = NSRegularExpression("^dhcp-option +PROXY_(HTTPS? +[^ ]+ +\\d+|AUTO_CONFIG_URL +[^ ]+)")
|
||||||
|
|
||||||
static let proxyBypass = NSRegularExpression("^dhcp-option +PROXY_BYPASS +.+")
|
static let proxyBypass = NSRegularExpression("^dhcp-option +PROXY_BYPASS +.+")
|
||||||
|
|
||||||
|
@ -228,6 +228,7 @@ extension OpenVPN {
|
||||||
var optSearchDomain: String?
|
var optSearchDomain: String?
|
||||||
var optHTTPProxy: Proxy?
|
var optHTTPProxy: Proxy?
|
||||||
var optHTTPSProxy: Proxy?
|
var optHTTPSProxy: Proxy?
|
||||||
|
var optProxyAutoConfigurationURL: URL?
|
||||||
var optProxyBypass: [String]?
|
var optProxyBypass: [String]?
|
||||||
var optRedirectGateway: Set<RedirectGateway>?
|
var optRedirectGateway: Set<RedirectGateway>?
|
||||||
|
|
||||||
|
@ -533,6 +534,15 @@ extension OpenVPN {
|
||||||
optSearchDomain = $0[1]
|
optSearchDomain = $0[1]
|
||||||
}
|
}
|
||||||
Regex.proxy.enumerateArguments(in: line) {
|
Regex.proxy.enumerateArguments(in: line) {
|
||||||
|
if $0.count == 2 {
|
||||||
|
guard let url = URL(string: $0[1]) else {
|
||||||
|
unsupportedError = ConfigurationError.malformed(option: "dhcp-option PROXY_AUTO_CONFIG_URL has malformed URL")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
optProxyAutoConfigurationURL = url
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
guard $0.count == 3, let port = UInt16($0[2]) else {
|
guard $0.count == 3, let port = UInt16($0[2]) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -731,6 +741,7 @@ extension OpenVPN {
|
||||||
sessionBuilder.searchDomain = optSearchDomain
|
sessionBuilder.searchDomain = optSearchDomain
|
||||||
sessionBuilder.httpProxy = optHTTPProxy
|
sessionBuilder.httpProxy = optHTTPProxy
|
||||||
sessionBuilder.httpsProxy = optHTTPSProxy
|
sessionBuilder.httpsProxy = optHTTPSProxy
|
||||||
|
sessionBuilder.proxyAutoConfigurationURL = optProxyAutoConfigurationURL
|
||||||
sessionBuilder.proxyBypassDomains = optProxyBypass
|
sessionBuilder.proxyBypassDomains = optProxyBypass
|
||||||
|
|
||||||
if let flags = optRedirectGateway {
|
if let flags = optRedirectGateway {
|
||||||
|
|
|
@ -56,6 +56,7 @@ class ConfigurationParserTests: XCTestCase {
|
||||||
"dhcp-option DOMAIN example.com",
|
"dhcp-option DOMAIN example.com",
|
||||||
"dhcp-option PROXY_HTTP 1.2.3.4 8081",
|
"dhcp-option PROXY_HTTP 1.2.3.4 8081",
|
||||||
"dhcp-option PROXY_HTTPS 7.8.9.10 8082",
|
"dhcp-option PROXY_HTTPS 7.8.9.10 8082",
|
||||||
|
"dhcp-option PROXY_AUTO_CONFIG_URL https://pac/",
|
||||||
"dhcp-option PROXY_BYPASS foo.com bar.org net.chat"
|
"dhcp-option PROXY_BYPASS foo.com bar.org net.chat"
|
||||||
]
|
]
|
||||||
XCTAssertNoThrow(try OpenVPN.ConfigurationParser.parsed(fromLines: lines))
|
XCTAssertNoThrow(try OpenVPN.ConfigurationParser.parsed(fromLines: lines))
|
||||||
|
@ -67,6 +68,7 @@ class ConfigurationParserTests: XCTestCase {
|
||||||
XCTAssertEqual(parsed.httpProxy?.port, 8081)
|
XCTAssertEqual(parsed.httpProxy?.port, 8081)
|
||||||
XCTAssertEqual(parsed.httpsProxy?.address, "7.8.9.10")
|
XCTAssertEqual(parsed.httpsProxy?.address, "7.8.9.10")
|
||||||
XCTAssertEqual(parsed.httpsProxy?.port, 8082)
|
XCTAssertEqual(parsed.httpsProxy?.port, 8082)
|
||||||
|
XCTAssertEqual(parsed.proxyAutoConfigurationURL?.absoluteString, "https://pac/")
|
||||||
XCTAssertEqual(parsed.proxyBypassDomains, ["foo.com", "bar.org", "net.chat"])
|
XCTAssertEqual(parsed.proxyBypassDomains, ["foo.com", "bar.org", "net.chat"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue