Merge pull request #122 from rob-patchett/ping-timeout
Allow keep-alive timeout to be configured by the server or client
This commit is contained in:
commit
eb09493882
|
@ -163,6 +163,8 @@ extension OpenVPNTunnelProvider {
|
||||||
|
|
||||||
static let keepAlive = "KeepAlive"
|
static let keepAlive = "KeepAlive"
|
||||||
|
|
||||||
|
static let keepAliveTimeout = "KeepAliveTimeout"
|
||||||
|
|
||||||
static let endpointProtocols = "EndpointProtocols"
|
static let endpointProtocols = "EndpointProtocols"
|
||||||
|
|
||||||
static let renegotiatesAfter = "RenegotiatesAfter"
|
static let renegotiatesAfter = "RenegotiatesAfter"
|
||||||
|
@ -497,6 +499,9 @@ private extension OpenVPN.Configuration {
|
||||||
if let keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval {
|
if let keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval {
|
||||||
builder.keepAliveInterval = keepAliveInterval
|
builder.keepAliveInterval = keepAliveInterval
|
||||||
}
|
}
|
||||||
|
if let keepAliveTimeout = providerConfiguration[S.keepAliveTimeout] as? TimeInterval {
|
||||||
|
builder.keepAliveTimeout = keepAliveTimeout
|
||||||
|
}
|
||||||
if let renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval {
|
if let renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval {
|
||||||
builder.renegotiatesAfter = renegotiatesAfter
|
builder.renegotiatesAfter = renegotiatesAfter
|
||||||
}
|
}
|
||||||
|
@ -571,6 +576,9 @@ private extension OpenVPN.Configuration {
|
||||||
if let keepAliveSeconds = keepAliveInterval {
|
if let keepAliveSeconds = keepAliveInterval {
|
||||||
dict[S.keepAlive] = keepAliveSeconds
|
dict[S.keepAlive] = keepAliveSeconds
|
||||||
}
|
}
|
||||||
|
if let keepAliveTimeoutSeconds = keepAliveTimeout {
|
||||||
|
dict[S.keepAliveTimeout] = keepAliveTimeoutSeconds
|
||||||
|
}
|
||||||
if let renegotiatesAfterSeconds = renegotiatesAfter {
|
if let renegotiatesAfterSeconds = renegotiatesAfter {
|
||||||
dict[S.renegotiatesAfter] = renegotiatesAfterSeconds
|
dict[S.renegotiatesAfter] = renegotiatesAfterSeconds
|
||||||
}
|
}
|
||||||
|
@ -632,9 +640,14 @@ private extension OpenVPN.Configuration {
|
||||||
log.info("\tTLS security level: default")
|
log.info("\tTLS security level: default")
|
||||||
}
|
}
|
||||||
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
|
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
|
||||||
log.info("\tKeep-alive: \(keepAliveSeconds) seconds")
|
log.info("\tKeep-alive interval: \(keepAliveSeconds) seconds")
|
||||||
} else {
|
} else {
|
||||||
log.info("\tKeep-alive: never")
|
log.info("\tKeep-alive interval: never")
|
||||||
|
}
|
||||||
|
if let keepAliveTimeoutSeconds = keepAliveTimeout, keepAliveTimeoutSeconds > 0 {
|
||||||
|
log.info("\tKeep-alive timeout: \(keepAliveTimeoutSeconds) seconds")
|
||||||
|
} else {
|
||||||
|
log.info("\tKeep-alive timeout: never")
|
||||||
}
|
}
|
||||||
if let renegotiatesAfterSeconds = renegotiatesAfter, renegotiatesAfterSeconds > 0 {
|
if let renegotiatesAfterSeconds = renegotiatesAfter, renegotiatesAfterSeconds > 0 {
|
||||||
log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds")
|
log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds")
|
||||||
|
|
|
@ -202,6 +202,9 @@ extension OpenVPN {
|
||||||
/// Sends periodical keep-alive packets if set.
|
/// Sends periodical keep-alive packets if set.
|
||||||
public var keepAliveInterval: TimeInterval?
|
public var keepAliveInterval: TimeInterval?
|
||||||
|
|
||||||
|
/// Disconnects after no keep-alive packets are received within timeout interval if set.
|
||||||
|
public var keepAliveTimeout: TimeInterval?
|
||||||
|
|
||||||
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
||||||
public var renegotiatesAfter: TimeInterval?
|
public var renegotiatesAfter: TimeInterval?
|
||||||
|
|
||||||
|
@ -277,6 +280,7 @@ extension OpenVPN {
|
||||||
tlsWrap: tlsWrap,
|
tlsWrap: tlsWrap,
|
||||||
tlsSecurityLevel: tlsSecurityLevel,
|
tlsSecurityLevel: tlsSecurityLevel,
|
||||||
keepAliveInterval: keepAliveInterval,
|
keepAliveInterval: keepAliveInterval,
|
||||||
|
keepAliveTimeout: keepAliveTimeout,
|
||||||
renegotiatesAfter: renegotiatesAfter,
|
renegotiatesAfter: renegotiatesAfter,
|
||||||
hostname: hostname,
|
hostname: hostname,
|
||||||
endpointProtocols: endpointProtocols,
|
endpointProtocols: endpointProtocols,
|
||||||
|
@ -346,6 +350,9 @@ extension OpenVPN {
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.keepAliveInterval`
|
/// - Seealso: `ConfigurationBuilder.keepAliveInterval`
|
||||||
public let keepAliveInterval: TimeInterval?
|
public let keepAliveInterval: TimeInterval?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.keepAliveTimeout`
|
||||||
|
public let keepAliveTimeout: TimeInterval?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.renegotiatesAfter`
|
/// - Seealso: `ConfigurationBuilder.renegotiatesAfter`
|
||||||
public let renegotiatesAfter: TimeInterval?
|
public let renegotiatesAfter: TimeInterval?
|
||||||
|
@ -435,6 +442,7 @@ extension OpenVPN.Configuration {
|
||||||
builder.tlsWrap = tlsWrap
|
builder.tlsWrap = tlsWrap
|
||||||
builder.tlsSecurityLevel = tlsSecurityLevel
|
builder.tlsSecurityLevel = tlsSecurityLevel
|
||||||
builder.keepAliveInterval = keepAliveInterval
|
builder.keepAliveInterval = keepAliveInterval
|
||||||
|
builder.keepAliveTimeout = keepAliveTimeout
|
||||||
builder.renegotiatesAfter = renegotiatesAfter
|
builder.renegotiatesAfter = renegotiatesAfter
|
||||||
builder.hostname = hostname
|
builder.hostname = hostname
|
||||||
builder.endpointProtocols = endpointProtocols
|
builder.endpointProtocols = endpointProtocols
|
||||||
|
|
|
@ -52,6 +52,8 @@ extension OpenVPN {
|
||||||
|
|
||||||
static let ping = NSRegularExpression("^ping +\\d+")
|
static let ping = NSRegularExpression("^ping +\\d+")
|
||||||
|
|
||||||
|
static let pingRestart = NSRegularExpression("^ping-restart +\\d+")
|
||||||
|
|
||||||
static let renegSec = NSRegularExpression("^reneg-sec +\\d+")
|
static let renegSec = NSRegularExpression("^reneg-sec +\\d+")
|
||||||
|
|
||||||
static let blockBegin = NSRegularExpression("^<[\\w\\-]+>")
|
static let blockBegin = NSRegularExpression("^<[\\w\\-]+>")
|
||||||
|
@ -203,6 +205,7 @@ extension OpenVPN {
|
||||||
var optTLSKeyLines: [Substring]?
|
var optTLSKeyLines: [Substring]?
|
||||||
var optTLSStrategy: TLSWrap.Strategy?
|
var optTLSStrategy: TLSWrap.Strategy?
|
||||||
var optKeepAliveSeconds: TimeInterval?
|
var optKeepAliveSeconds: TimeInterval?
|
||||||
|
var optKeepAliveTimeoutSeconds: TimeInterval?
|
||||||
var optRenegotiateAfterSeconds: TimeInterval?
|
var optRenegotiateAfterSeconds: TimeInterval?
|
||||||
//
|
//
|
||||||
var optHostname: String?
|
var optHostname: String?
|
||||||
|
@ -398,6 +401,13 @@ extension OpenVPN {
|
||||||
}
|
}
|
||||||
optKeepAliveSeconds = TimeInterval(arg)
|
optKeepAliveSeconds = TimeInterval(arg)
|
||||||
}
|
}
|
||||||
|
Regex.pingRestart.enumerateArguments(in: line) {
|
||||||
|
isHandled = true
|
||||||
|
guard let arg = $0.first else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
optKeepAliveTimeoutSeconds = TimeInterval(arg)
|
||||||
|
}
|
||||||
Regex.renegSec.enumerateArguments(in: line) {
|
Regex.renegSec.enumerateArguments(in: line) {
|
||||||
isHandled = true
|
isHandled = true
|
||||||
guard let arg = $0.first else {
|
guard let arg = $0.first else {
|
||||||
|
@ -599,6 +609,7 @@ extension OpenVPN {
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionBuilder.keepAliveInterval = optKeepAliveSeconds
|
sessionBuilder.keepAliveInterval = optKeepAliveSeconds
|
||||||
|
sessionBuilder.keepAliveTimeout = optKeepAliveTimeoutSeconds
|
||||||
sessionBuilder.renegotiatesAfter = optRenegotiateAfterSeconds
|
sessionBuilder.renegotiatesAfter = optRenegotiateAfterSeconds
|
||||||
|
|
||||||
// MARK: Client
|
// MARK: Client
|
||||||
|
|
|
@ -87,8 +87,8 @@ public class OpenVPNSession: Session {
|
||||||
|
|
||||||
private var keepAliveInterval: TimeInterval? {
|
private var keepAliveInterval: TimeInterval? {
|
||||||
let interval: TimeInterval?
|
let interval: TimeInterval?
|
||||||
if let negInterval = pushReply?.options.keepAliveInterval, negInterval > 0 {
|
if let negInterval = pushReply?.options.keepAliveInterval, negInterval > 0.0 {
|
||||||
interval = TimeInterval(negInterval)
|
interval = negInterval
|
||||||
} else if let cfgInterval = configuration.keepAliveInterval, cfgInterval > 0.0 {
|
} else if let cfgInterval = configuration.keepAliveInterval, cfgInterval > 0.0 {
|
||||||
interval = cfgInterval
|
interval = cfgInterval
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,6 +97,16 @@ public class OpenVPNSession: Session {
|
||||||
return interval
|
return interval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var keepAliveTimeout: TimeInterval {
|
||||||
|
if let negTimeout = pushReply?.options.keepAliveTimeout, negTimeout > 0.0 {
|
||||||
|
return negTimeout
|
||||||
|
} else if let cfgTimeout = configuration.keepAliveTimeout, cfgTimeout > 0.0 {
|
||||||
|
return cfgTimeout
|
||||||
|
} else {
|
||||||
|
return CoreConfiguration.OpenVPN.pingTimeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An optional `OpenVPNSessionDelegate` for receiving session events.
|
/// An optional `OpenVPNSessionDelegate` for receiving session events.
|
||||||
public weak var delegate: OpenVPNSessionDelegate?
|
public weak var delegate: OpenVPNSessionDelegate?
|
||||||
|
|
||||||
|
@ -535,7 +545,7 @@ public class OpenVPNSession: Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
let now = Date()
|
let now = Date()
|
||||||
guard (now.timeIntervalSince(lastPing.inbound) <= CoreConfiguration.OpenVPN.pingTimeout) else {
|
guard (now.timeIntervalSince(lastPing.inbound) <= keepAliveTimeout) else {
|
||||||
deferStop(.shutdown, OpenVPNError.pingTimeout)
|
deferStop(.shutdown, OpenVPNError.pingTimeout)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1080,10 @@ public class OpenVPNSession: Session {
|
||||||
log.info("\tNegotiated compression algorithm: \(negCompression)")
|
log.info("\tNegotiated compression algorithm: \(negCompression)")
|
||||||
}
|
}
|
||||||
if let negPing = pushReply.options.keepAliveInterval {
|
if let negPing = pushReply.options.keepAliveInterval {
|
||||||
log.info("\tNegotiated keep-alive: \(negPing) seconds")
|
log.info("\tNegotiated keep-alive interval: \(negPing) seconds")
|
||||||
|
}
|
||||||
|
if let negPingRestart = pushReply.options.keepAliveTimeout {
|
||||||
|
log.info("\tNegotiated keep-alive timeout: \(negPingRestart) seconds")
|
||||||
}
|
}
|
||||||
|
|
||||||
let bridge: OpenVPN.EncryptionBridge
|
let bridge: OpenVPN.EncryptionBridge
|
||||||
|
|
|
@ -156,6 +156,14 @@ class PushTests: XCTestCase {
|
||||||
XCTAssertEqual(reply.options.keepAliveInterval, 10)
|
XCTAssertEqual(reply.options.keepAliveInterval, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testPingRestart() {
|
||||||
|
let msg = "PUSH_REPLY,route 192.168.1.0 255.255.255.0,route 10.0.2.0 255.255.255.0,dhcp-option DNS 192.168.1.99,dhcp-option DNS 176.103.130.130,route 10.0.2.1,topology net30,ping 10,ping-restart 60,ifconfig 10.0.2.14 10.0.2.13"
|
||||||
|
let reply = try! OpenVPN.PushReply(message: msg)!
|
||||||
|
reply.debug()
|
||||||
|
|
||||||
|
XCTAssertEqual(reply.options.keepAliveTimeout, 60)
|
||||||
|
}
|
||||||
|
|
||||||
func testProvost() {
|
func testProvost() {
|
||||||
let msg = "PUSH_REPLY,route 87.233.192.218,route 87.233.192.219,route 87.233.192.220,route 87.248.186.252,route 92.241.171.245,route 103.246.200.0 255.255.252.0,route 109.239.140.0 255.255.255.0,route 128.199.0.0 255.255.0.0,route 13.125.0.0 255.255.0.0,route 13.230.0.0 255.254.0.0,route 13.56.0.0 255.252.0.0,route 149.154.160.0 255.255.252.0,route 149.154.164.0 255.255.252.0,route 149.154.168.0 255.255.252.0,route 149.154.172.0 255.255.252.0,route 159.122.128.0 255.255.192.0,route 159.203.0.0 255.255.0.0,route 159.65.0.0 255.255.0.0,route 159.89.0.0 255.255.0.0,route 165.227.0.0 255.255.0.0,route 167.99.0.0 255.255.0.0,route 174.138.0.0 255.255.128.0,route 176.67.169.0 255.255.255.0,route 178.239.88.0 255.255.248.0,route 178.63.0.0 255.255.0.0,route 18.130.0.0 255.255.0.0,route 18.144.0.0 255.255.0.0,route 18.184.0.0 255.254.0.0,route 18.194.0.0 255.254.0.0,route 18.196.0.0 255.254.0.0,route 18.204.0.0 255.252.0.0,push-continuation 2"
|
let msg = "PUSH_REPLY,route 87.233.192.218,route 87.233.192.219,route 87.233.192.220,route 87.248.186.252,route 92.241.171.245,route 103.246.200.0 255.255.252.0,route 109.239.140.0 255.255.255.0,route 128.199.0.0 255.255.0.0,route 13.125.0.0 255.255.0.0,route 13.230.0.0 255.254.0.0,route 13.56.0.0 255.252.0.0,route 149.154.160.0 255.255.252.0,route 149.154.164.0 255.255.252.0,route 149.154.168.0 255.255.252.0,route 149.154.172.0 255.255.252.0,route 159.122.128.0 255.255.192.0,route 159.203.0.0 255.255.0.0,route 159.65.0.0 255.255.0.0,route 159.89.0.0 255.255.0.0,route 165.227.0.0 255.255.0.0,route 167.99.0.0 255.255.0.0,route 174.138.0.0 255.255.128.0,route 176.67.169.0 255.255.255.0,route 178.239.88.0 255.255.248.0,route 178.63.0.0 255.255.0.0,route 18.130.0.0 255.255.0.0,route 18.144.0.0 255.255.0.0,route 18.184.0.0 255.254.0.0,route 18.194.0.0 255.254.0.0,route 18.196.0.0 255.254.0.0,route 18.204.0.0 255.252.0.0,push-continuation 2"
|
||||||
let reply = try? OpenVPN.PushReply(message: msg)!
|
let reply = try? OpenVPN.PushReply(message: msg)!
|
||||||
|
|
Loading…
Reference in New Issue