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:
Davide De Rosa 2019-10-22 10:51:27 +02:00 committed by GitHub
commit eb09493882
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 6 deletions

View File

@ -163,6 +163,8 @@ extension OpenVPNTunnelProvider {
static let keepAlive = "KeepAlive"
static let keepAliveTimeout = "KeepAliveTimeout"
static let endpointProtocols = "EndpointProtocols"
static let renegotiatesAfter = "RenegotiatesAfter"
@ -497,6 +499,9 @@ private extension OpenVPN.Configuration {
if let keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval {
builder.keepAliveInterval = keepAliveInterval
}
if let keepAliveTimeout = providerConfiguration[S.keepAliveTimeout] as? TimeInterval {
builder.keepAliveTimeout = keepAliveTimeout
}
if let renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval {
builder.renegotiatesAfter = renegotiatesAfter
}
@ -571,6 +576,9 @@ private extension OpenVPN.Configuration {
if let keepAliveSeconds = keepAliveInterval {
dict[S.keepAlive] = keepAliveSeconds
}
if let keepAliveTimeoutSeconds = keepAliveTimeout {
dict[S.keepAliveTimeout] = keepAliveTimeoutSeconds
}
if let renegotiatesAfterSeconds = renegotiatesAfter {
dict[S.renegotiatesAfter] = renegotiatesAfterSeconds
}
@ -632,9 +640,14 @@ private extension OpenVPN.Configuration {
log.info("\tTLS security level: default")
}
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
log.info("\tKeep-alive: \(keepAliveSeconds) seconds")
log.info("\tKeep-alive interval: \(keepAliveSeconds) seconds")
} 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 {
log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds")

View File

@ -202,6 +202,9 @@ extension OpenVPN {
/// Sends periodical keep-alive packets if set.
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.
public var renegotiatesAfter: TimeInterval?
@ -277,6 +280,7 @@ extension OpenVPN {
tlsWrap: tlsWrap,
tlsSecurityLevel: tlsSecurityLevel,
keepAliveInterval: keepAliveInterval,
keepAliveTimeout: keepAliveTimeout,
renegotiatesAfter: renegotiatesAfter,
hostname: hostname,
endpointProtocols: endpointProtocols,
@ -347,6 +351,9 @@ extension OpenVPN {
/// - Seealso: `ConfigurationBuilder.keepAliveInterval`
public let keepAliveInterval: TimeInterval?
/// - Seealso: `ConfigurationBuilder.keepAliveTimeout`
public let keepAliveTimeout: TimeInterval?
/// - Seealso: `ConfigurationBuilder.renegotiatesAfter`
public let renegotiatesAfter: TimeInterval?
@ -435,6 +442,7 @@ extension OpenVPN.Configuration {
builder.tlsWrap = tlsWrap
builder.tlsSecurityLevel = tlsSecurityLevel
builder.keepAliveInterval = keepAliveInterval
builder.keepAliveTimeout = keepAliveTimeout
builder.renegotiatesAfter = renegotiatesAfter
builder.hostname = hostname
builder.endpointProtocols = endpointProtocols

View File

@ -52,6 +52,8 @@ extension OpenVPN {
static let ping = NSRegularExpression("^ping +\\d+")
static let pingRestart = NSRegularExpression("^ping-restart +\\d+")
static let renegSec = NSRegularExpression("^reneg-sec +\\d+")
static let blockBegin = NSRegularExpression("^<[\\w\\-]+>")
@ -203,6 +205,7 @@ extension OpenVPN {
var optTLSKeyLines: [Substring]?
var optTLSStrategy: TLSWrap.Strategy?
var optKeepAliveSeconds: TimeInterval?
var optKeepAliveTimeoutSeconds: TimeInterval?
var optRenegotiateAfterSeconds: TimeInterval?
//
var optHostname: String?
@ -398,6 +401,13 @@ extension OpenVPN {
}
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) {
isHandled = true
guard let arg = $0.first else {
@ -599,6 +609,7 @@ extension OpenVPN {
}
sessionBuilder.keepAliveInterval = optKeepAliveSeconds
sessionBuilder.keepAliveTimeout = optKeepAliveTimeoutSeconds
sessionBuilder.renegotiatesAfter = optRenegotiateAfterSeconds
// MARK: Client

View File

@ -87,8 +87,8 @@ public class OpenVPNSession: Session {
private var keepAliveInterval: TimeInterval? {
let interval: TimeInterval?
if let negInterval = pushReply?.options.keepAliveInterval, negInterval > 0 {
interval = TimeInterval(negInterval)
if let negInterval = pushReply?.options.keepAliveInterval, negInterval > 0.0 {
interval = negInterval
} else if let cfgInterval = configuration.keepAliveInterval, cfgInterval > 0.0 {
interval = cfgInterval
} else {
@ -97,6 +97,16 @@ public class OpenVPNSession: Session {
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.
public weak var delegate: OpenVPNSessionDelegate?
@ -535,7 +545,7 @@ public class OpenVPNSession: Session {
}
let now = Date()
guard (now.timeIntervalSince(lastPing.inbound) <= CoreConfiguration.OpenVPN.pingTimeout) else {
guard (now.timeIntervalSince(lastPing.inbound) <= keepAliveTimeout) else {
deferStop(.shutdown, OpenVPNError.pingTimeout)
return
}
@ -1070,7 +1080,10 @@ public class OpenVPNSession: Session {
log.info("\tNegotiated compression algorithm: \(negCompression)")
}
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

View File

@ -156,6 +156,14 @@ class PushTests: XCTestCase {
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() {
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)!