Revisit WireGuard.Configuration
- Make Configuration Codable - Expose WireGuard ConfigurationError - Produce ConfigurationBuilder from Configuration - Support multiple peers - Make private key a requirement
This commit is contained in:
parent
c019cecbe0
commit
2bcd11fd7e
|
@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- Parse OpenVPN authentication requirement from `--auth-user-pass`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Support multiple peers in WireGuard.
|
||||
|
||||
## 4.1.0 (2022-02-09)
|
||||
|
||||
### Added
|
||||
|
|
|
@ -200,13 +200,14 @@ extension WireGuard {
|
|||
serverAddress: String,
|
||||
serverPort: String
|
||||
) -> WireGuardProvider.Configuration? {
|
||||
var builder = WireGuard.ConfigurationBuilder()
|
||||
builder.privateKey = clientPrivateKey
|
||||
var builder = WireGuard.ConfigurationBuilder(privateKey: clientPrivateKey)
|
||||
builder.addresses = [clientAddress]
|
||||
builder.peerPublicKey = serverPublicKey
|
||||
builder.peerAddress = serverAddress
|
||||
builder.peerPort = UInt16(serverPort)
|
||||
builder.allowedIPs = ["0.0.0.0/0"]
|
||||
|
||||
var peer = Peer(publicKey: serverPublicKey)
|
||||
peer.endpoint = "\(serverAddress):\(serverPort)"
|
||||
peer.allowedIPs = ["0.0.0.0/0"]
|
||||
builder.peers = [peer]
|
||||
|
||||
builder.dns = ["1.1.1.1", "1.0.0.1"]
|
||||
guard let cfg = builder.build() else {
|
||||
return nil
|
||||
|
|
|
@ -26,9 +26,17 @@
|
|||
import Foundation
|
||||
import WireGuardKit
|
||||
|
||||
public struct ConfigurationError: Error {
|
||||
let parseError: TunnelConfiguration.ParseError
|
||||
}
|
||||
|
||||
extension WireGuard.Configuration {
|
||||
public init(wgQuickConfig: String) throws {
|
||||
tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: wgQuickConfig)
|
||||
do {
|
||||
tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: wgQuickConfig)
|
||||
} catch let parseError as TunnelConfiguration.ParseError {
|
||||
throw ConfigurationError(parseError: parseError)
|
||||
}
|
||||
}
|
||||
|
||||
public func asWgQuickConfig() -> String {
|
||||
|
|
|
@ -25,10 +25,31 @@
|
|||
|
||||
import Foundation
|
||||
import WireGuardKit
|
||||
import NetworkExtension
|
||||
|
||||
extension WireGuard {
|
||||
public struct Peer {
|
||||
public var publicKey: String
|
||||
|
||||
public var preSharedKey: String?
|
||||
|
||||
public var endpoint: String?
|
||||
|
||||
public var allowedIPs: [String]?
|
||||
|
||||
public var keepAliveInterval: UInt16?
|
||||
|
||||
public init(publicKey: String) {
|
||||
self.publicKey = publicKey
|
||||
}
|
||||
}
|
||||
|
||||
public struct ConfigurationBuilder {
|
||||
public var privateKey: String?
|
||||
public var privateKey: String
|
||||
|
||||
public var publicKey: String? {
|
||||
return PrivateKey(base64Key: privateKey)?.publicKey.base64Key
|
||||
}
|
||||
|
||||
public var addresses: [String]?
|
||||
|
||||
|
@ -36,31 +57,17 @@ extension WireGuard {
|
|||
|
||||
public var mtu: UInt16?
|
||||
|
||||
public var peerPublicKey: String?
|
||||
public var peers: [Peer]
|
||||
|
||||
public var peerPreSharedKey: String?
|
||||
|
||||
public var peerAddress: String?
|
||||
|
||||
public var peerPort: UInt16?
|
||||
|
||||
public var allowedIPs: [String]?
|
||||
|
||||
public var keepAliveInterval: UInt16?
|
||||
|
||||
public init() {
|
||||
public init(privateKey: String) {
|
||||
self.privateKey = privateKey
|
||||
peers = []
|
||||
}
|
||||
|
||||
public func build() -> Configuration? {
|
||||
guard let privateKey = privateKey, let clientPrivateKey = PrivateKey(base64Key: privateKey) else {
|
||||
guard let clientPrivateKey = PrivateKey(base64Key: privateKey) else {
|
||||
return nil
|
||||
}
|
||||
guard let peerPublicKey = peerPublicKey, let serverPublicKey = PublicKey(base64Key: peerPublicKey) else {
|
||||
return nil
|
||||
}
|
||||
guard let peerAddress = peerAddress, let peerPort = peerPort, let endpoint = Endpoint(from: "\(peerAddress):\(peerPort)") else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var interfaceConfiguration = InterfaceConfiguration(privateKey: clientPrivateKey)
|
||||
if let clientAddresses = addresses?.mapOptional({ IPAddressRange(from: $0) }) {
|
||||
|
@ -70,23 +77,76 @@ extension WireGuard {
|
|||
interfaceConfiguration.dns = dnsServers
|
||||
}
|
||||
interfaceConfiguration.mtu = mtu
|
||||
var peerConfiguration = PeerConfiguration(publicKey: serverPublicKey)
|
||||
if let peerPreSharedKey = peerPreSharedKey {
|
||||
peerConfiguration.preSharedKey = PreSharedKey(base64Key: peerPreSharedKey)
|
||||
}
|
||||
if let peerAllowedIPs = allowedIPs?.mapOptional({ IPAddressRange(from: $0) }) {
|
||||
peerConfiguration.allowedIPs = peerAllowedIPs
|
||||
}
|
||||
peerConfiguration.endpoint = endpoint
|
||||
peerConfiguration.persistentKeepAlive = keepAliveInterval
|
||||
|
||||
let tunnelConfiguration = TunnelConfiguration(name: nil, interface: interfaceConfiguration, peers: [peerConfiguration])
|
||||
var peerConfigurations: [PeerConfiguration] = []
|
||||
for peer in peers {
|
||||
guard let publicKey = PublicKey(base64Key: peer.publicKey) else {
|
||||
continue
|
||||
}
|
||||
// XXX: this is actually optional in WireGuard
|
||||
guard let endpointString = peer.endpoint, let endpoint = Endpoint(from: endpointString) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var cfg = PeerConfiguration(publicKey: publicKey)
|
||||
if let preSharedKey = peer.preSharedKey {
|
||||
cfg.preSharedKey = PreSharedKey(base64Key: preSharedKey)
|
||||
}
|
||||
if let allowedIPs = peer.allowedIPs?.mapOptional(IPAddressRange.init(from:)) {
|
||||
cfg.allowedIPs = allowedIPs
|
||||
}
|
||||
cfg.endpoint = endpoint
|
||||
cfg.persistentKeepAlive = peer.keepAliveInterval
|
||||
|
||||
peerConfigurations.append(cfg)
|
||||
}
|
||||
guard !peers.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let tunnelConfiguration = TunnelConfiguration(name: nil, interface: interfaceConfiguration, peers: peerConfigurations)
|
||||
return Configuration(tunnelConfiguration: tunnelConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
public struct Configuration {
|
||||
public struct Configuration: Codable {
|
||||
public let tunnelConfiguration: TunnelConfiguration
|
||||
|
||||
public init(tunnelConfiguration: TunnelConfiguration) {
|
||||
self.tunnelConfiguration = tunnelConfiguration
|
||||
}
|
||||
|
||||
public func builder() -> WireGuard.ConfigurationBuilder {
|
||||
let privateKey = tunnelConfiguration.interface.privateKey.base64Key
|
||||
var builder = WireGuard.ConfigurationBuilder(privateKey: privateKey)
|
||||
builder.addresses = tunnelConfiguration.interface.addresses.map(\.stringRepresentation)
|
||||
builder.dns = tunnelConfiguration.interface.dns.map(\.stringRepresentation)
|
||||
builder.mtu = tunnelConfiguration.interface.mtu
|
||||
builder.peers = tunnelConfiguration.peers.map {
|
||||
var peer = Peer(publicKey: $0.publicKey.base64Key)
|
||||
peer.preSharedKey = $0.preSharedKey?.base64Key
|
||||
peer.endpoint = $0.endpoint?.stringRepresentation
|
||||
peer.allowedIPs = $0.allowedIPs.map(\.stringRepresentation)
|
||||
peer.keepAliveInterval = $0.persistentKeepAlive
|
||||
return peer
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let wg = try container.decode(String.self)
|
||||
let cfg = try TunnelConfiguration(fromWgQuickConfig: wg, called: nil)
|
||||
self.init(tunnelConfiguration: cfg)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
let wg = tunnelConfiguration.asWgQuickConfig()
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(wg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue