Parse --redirect-gateway from configuration

FIXME: for now only redirects ALL traffic when the option is found
in the configuration file, whatever the arguments.

Also drop unnecessary base options in tests as everything was made
optional recently.
This commit is contained in:
Davide De Rosa 2019-04-25 13:06:22 +02:00
parent 1b8647bcac
commit 224a76ac58
3 changed files with 82 additions and 12 deletions

View File

@ -96,6 +96,8 @@ public class ConfigurationParser {
static let proxyBypass = NSRegularExpression("^dhcp-option +PROXY_BYPASS +.+")
static let redirectGateway = NSRegularExpression("^redirect-gateway.*")
// MARK: Unsupported
// static let fragment = NSRegularExpression("^fragment +\\d+")
@ -120,6 +122,26 @@ public class ConfigurationParser {
case subnet
}
private enum RedirectGateway: String {
case local
case autolocal
case def1
case bypassDHCP = "bypass-dhcp"
case bypassDNS = "bypass-dns"
case blockLocal = "block-local"
case ipv4
case noIPv4 = "!ipv4"
case ipv6
}
/// Result of the parser.
public struct Result {
@ -204,6 +226,7 @@ public class ConfigurationParser {
var optHTTPProxy: Proxy?
var optHTTPSProxy: Proxy?
var optProxyBypass: [String]?
var optRedirectGateway: Set<RedirectGateway>?
log.verbose("Configuration file:")
for line in lines {
@ -515,6 +538,22 @@ public class ConfigurationParser {
optProxyBypass = $0
optProxyBypass?.removeFirst()
}
Regex.redirectGateway.enumerateArguments(in: line) {
// redirect IPv4 by default
optRedirectGateway = [.ipv4]
for arg in $0 {
guard let opt = RedirectGateway(rawValue: arg) else {
continue
}
if opt == .noIPv4 {
optRedirectGateway?.remove(.ipv4)
} else {
optRedirectGateway?.insert(opt)
}
}
}
//
@ -681,6 +720,11 @@ public class ConfigurationParser {
sessionBuilder.httpsProxy = optHTTPSProxy
sessionBuilder.proxyBypassDomains = optProxyBypass
// FIXME: only redirects all traffic until --redirect-gateway is properly interpreted
if let _ = optRedirectGateway {
sessionBuilder.routingPolicies = [.IPv4, .IPv6]
}
//
return Result(

View File

@ -146,6 +146,16 @@ extension SessionProxy {
}
}
/// Routing policy.
public enum RoutingPolicy: String, Codable {
/// All IPv4 traffic goes through the VPN.
case IPv4
/// All IPv6 traffic goes through the VPN.
case IPv6
}
/// :nodoc:
private struct Fallback {
static let cipher: Cipher = .aes128cbc
@ -238,6 +248,9 @@ extension SessionProxy {
/// The list of domains not passing through the proxy.
public var proxyBypassDomains: [String]?
/// Policies for redirecting traffic through the VPN gateway.
public var routingPolicies: [RoutingPolicy]?
/// :nodoc:
public init() {
}
@ -272,7 +285,8 @@ extension SessionProxy {
searchDomain: searchDomain,
httpProxy: httpProxy,
httpsProxy: httpsProxy,
proxyBypassDomains: proxyBypassDomains
proxyBypassDomains: proxyBypassDomains,
routingPolicies: routingPolicies
)
}
@ -369,6 +383,9 @@ extension SessionProxy {
/// - Seealso: `SessionProxy.ConfigurationBuilder.proxyBypassDomains`
public var proxyBypassDomains: [String]?
/// - Seealso: `SessionProxy.ConfigurationBuilder.routingPolicies`
public var routingPolicies: [RoutingPolicy]?
// MARK: Shortcuts
/// :nodoc:
@ -422,6 +439,7 @@ extension SessionProxy.Configuration {
builder.httpProxy = httpProxy
builder.httpsProxy = httpsProxy
builder.proxyBypassDomains = proxyBypassDomains
builder.routingPolicies = routingPolicies
return builder
}
}

View File

@ -27,8 +27,6 @@ import XCTest
import TunnelKit
class ConfigurationParserTests: XCTestCase {
let base: [String] = ["<ca>", "</ca>", "remote 1.2.3.4"]
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
@ -42,18 +40,18 @@ class ConfigurationParserTests: XCTestCase {
// from lines
func testCompression() throws {
// XCTAssertNotNil(try OptionsBundle.parsed(fromLines: base + ["comp-lzo"]).warning)
XCTAssertNil(try ConfigurationParser.parsed(fromLines: base + ["comp-lzo"]).warning)
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: base + ["comp-lzo no"]))
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: base + ["comp-lzo yes"]))
// XCTAssertThrowsError(try ConfigurationParser.parsed(fromLines: base + ["comp-lzo yes"]))
// XCTAssertNotNil(try OptionsBundle.parsed(fromLines: ["comp-lzo"]).warning)
XCTAssertNil(try ConfigurationParser.parsed(fromLines: ["comp-lzo"]).warning)
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: ["comp-lzo no"]))
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: ["comp-lzo yes"]))
// XCTAssertThrowsError(try ConfigurationParser.parsed(fromLines: ["comp-lzo yes"]))
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: base + ["compress"]))
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: base + ["compress lzo"]))
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: ["compress"]))
XCTAssertNoThrow(try ConfigurationParser.parsed(fromLines: ["compress lzo"]))
}
func testDHCPOption() throws {
let lines = base + [
let lines = [
"dhcp-option DNS 8.8.8.8",
"dhcp-option DNS6 ffff::1",
"dhcp-option DOMAIN example.com",
@ -73,8 +71,18 @@ class ConfigurationParserTests: XCTestCase {
XCTAssertEqual(parsed.proxyBypassDomains, ["foo.com", "bar.org", "net.chat"])
}
func testRedirectGateway() throws {
var parsed: SessionProxy.Configuration
parsed = try! ConfigurationParser.parsed(fromLines: []).configuration
XCTAssertEqual(parsed.routingPolicies, nil)
XCTAssertNotEqual(parsed.routingPolicies, [])
parsed = try! ConfigurationParser.parsed(fromLines: ["redirect-gateway ipv4 block-local"]).configuration
XCTAssertEqual(parsed.routingPolicies, [.IPv4, .IPv6])
}
func testConnectionBlock() throws {
let lines = base + ["<connection>", "</connection>"]
let lines = ["<connection>", "</connection>"]
XCTAssertThrowsError(try ConfigurationParser.parsed(fromLines: lines))
}