iOS AWG/WG split tunnel
This commit is contained in:
parent
f0b872e86b
commit
22b14dff5f
5 changed files with 97 additions and 10 deletions
|
|
@ -28,6 +28,8 @@ struct MessageKey
|
||||||
static const char *host;
|
static const char *host;
|
||||||
static const char *port;
|
static const char *port;
|
||||||
static const char *isOnDemand;
|
static const char *isOnDemand;
|
||||||
|
static const char *SplitTunnelType;
|
||||||
|
static const char *SplitTunnelSites;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IosController : public QObject
|
class IosController : public QObject
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ const char* MessageKey::errorCode = "errorCode";
|
||||||
const char* MessageKey::host = "host";
|
const char* MessageKey::host = "host";
|
||||||
const char* MessageKey::port = "port";
|
const char* MessageKey::port = "port";
|
||||||
const char* MessageKey::isOnDemand = "is-on-demand";
|
const char* MessageKey::isOnDemand = "is-on-demand";
|
||||||
|
const char* MessageKey::SplitTunnelType = "SplitTunnelType";
|
||||||
|
const char* MessageKey::SplitTunnelSites = "SplitTunnelSites";
|
||||||
|
|
||||||
|
|
||||||
Vpn::ConnectionState iosStatusToState(NEVPNStatus status) {
|
Vpn::ConnectionState iosStatusToState(NEVPNStatus status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
|
@ -351,6 +354,15 @@ void IosController::startTunnel()
|
||||||
{
|
{
|
||||||
m_rxBytes = 0;
|
m_rxBytes = 0;
|
||||||
m_txBytes = 0;
|
m_txBytes = 0;
|
||||||
|
|
||||||
|
qDebug() << "m_rawConfig " << m_rawConfig;
|
||||||
|
|
||||||
|
int STT = m_rawConfig["splitTunnelType"].toInt();
|
||||||
|
QJsonArray splitTunnelSites = m_rawConfig["splitTunnelSites"].toArray();
|
||||||
|
QJsonDocument doc;
|
||||||
|
doc.setArray(splitTunnelSites);
|
||||||
|
QString STS(doc.toJson());
|
||||||
|
|
||||||
[m_currentTunnel setEnabled:YES];
|
[m_currentTunnel setEnabled:YES];
|
||||||
|
|
||||||
[m_currentTunnel saveToPreferencesWithCompletionHandler:^(NSError *saveError) {
|
[m_currentTunnel saveToPreferencesWithCompletionHandler:^(NSError *saveError) {
|
||||||
|
|
@ -376,8 +388,16 @@ void IosController::startTunnel()
|
||||||
NSString *actionValue = [NSString stringWithUTF8String:Action::start];
|
NSString *actionValue = [NSString stringWithUTF8String:Action::start];
|
||||||
NSString *tunnelIdKey = [NSString stringWithUTF8String:MessageKey::tunnelId];
|
NSString *tunnelIdKey = [NSString stringWithUTF8String:MessageKey::tunnelId];
|
||||||
NSString *tunnelIdValue = !m_tunnelId.isEmpty() ? m_tunnelId.toNSString() : @"";
|
NSString *tunnelIdValue = !m_tunnelId.isEmpty() ? m_tunnelId.toNSString() : @"";
|
||||||
|
NSString *SplitTunnelTypeKey = [NSString stringWithUTF8String:MessageKey::SplitTunnelType];
|
||||||
|
NSString *SplitTunnelTypeValue = [NSString stringWithFormat:@"%d",STT];
|
||||||
|
NSString *SplitTunnelSitesKey = [NSString stringWithUTF8String:MessageKey::SplitTunnelSites];
|
||||||
|
NSString *SplitTunnelSitesValue = STS.toNSString();
|
||||||
|
|
||||||
|
|
||||||
NSDictionary* message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue};
|
NSDictionary* message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue,
|
||||||
|
SplitTunnelTypeKey: SplitTunnelTypeValue, SplitTunnelSitesKey: SplitTunnelSitesValue};
|
||||||
|
|
||||||
|
qDebug() << "sendVpnExtensionMessage " << message;
|
||||||
sendVpnExtensionMessage(message);
|
sendVpnExtensionMessage(message);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ struct Constants {
|
||||||
static let kMessageKeyHost = "host"
|
static let kMessageKeyHost = "host"
|
||||||
static let kMessageKeyPort = "port"
|
static let kMessageKeyPort = "port"
|
||||||
static let kMessageKeyOnDemand = "is-on-demand"
|
static let kMessageKeyOnDemand = "is-on-demand"
|
||||||
|
static let kMessageKeySplitTunnelType = "SplitTunnelType"
|
||||||
|
static let kMessageKeySplitTunnelSites = "SplitTunnelSites"
|
||||||
}
|
}
|
||||||
|
|
||||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
|
|
@ -49,6 +51,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
private let dispatchQueue = DispatchQueue(label: "PacketTunnel", qos: .utility)
|
private let dispatchQueue = DispatchQueue(label: "PacketTunnel", qos: .utility)
|
||||||
|
|
||||||
private var openVPNConfig: Data? = nil
|
private var openVPNConfig: Data? = nil
|
||||||
|
private var SplitTunnelType: String? = nil
|
||||||
|
private var SplitTunnelSites: String? = nil
|
||||||
|
|
||||||
let vpnReachability = OpenVPNReachability()
|
let vpnReachability = OpenVPNReachability()
|
||||||
|
|
||||||
|
|
@ -63,6 +67,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
||||||
|
|
||||||
|
let tmpStr = String(data: messageData, encoding: .utf8)!
|
||||||
|
wg_log(.error, message: tmpStr)
|
||||||
guard let message = try? JSONSerialization.jsonObject(with: messageData, options: []) as? [String: Any] else {
|
guard let message = try? JSONSerialization.jsonObject(with: messageData, options: []) as? [String: Any] else {
|
||||||
Logger.global?.log(message: "Failed to serialize message from app")
|
Logger.global?.log(message: "Failed to serialize message from app")
|
||||||
return
|
return
|
||||||
|
|
@ -83,6 +90,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
handleStatusAppMessage(messageData, completionHandler: completionHandler)
|
handleStatusAppMessage(messageData, completionHandler: completionHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if action == Constants.kActionStart {
|
||||||
|
SplitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String
|
||||||
|
SplitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String
|
||||||
|
}
|
||||||
|
|
||||||
let callbackWrapper: (NSNumber?) -> Void = { errorCode in
|
let callbackWrapper: (NSNumber?) -> Void = { errorCode in
|
||||||
//let tunnelId = self.tunnelConfig?.id ?? ""
|
//let tunnelId = self.tunnelConfig?.id ?? ""
|
||||||
let response: [String: Any] = [
|
let response: [String: Any] = [
|
||||||
|
|
@ -175,6 +187,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let wgConfigStr = String(data: wgConfig, encoding: .utf8)!
|
let wgConfigStr = String(data: wgConfig, encoding: .utf8)!
|
||||||
|
|
||||||
guard let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr) else {
|
guard let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr) else {
|
||||||
|
|
@ -182,7 +195,63 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wg_log(.error, message: tunnelConfiguration.peers.first!.allowedIPs.map { $0.stringRepresentation }.joined(separator: ", "))
|
||||||
|
|
||||||
|
if (tunnelConfiguration.peers.first!.allowedIPs.map { $0.stringRepresentation }.joined(separator: ", ") == "0.0.0.0/0, ::/0"){
|
||||||
|
if (SplitTunnelType == "1") {
|
||||||
|
wg_log(.error, message: SplitTunnelSites!)
|
||||||
|
for index in tunnelConfiguration.peers.indices {
|
||||||
|
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
||||||
|
var allowedIPs = [IPAddressRange]()
|
||||||
|
|
||||||
|
let data = Data(SplitTunnelSites!.utf8)
|
||||||
|
do {
|
||||||
|
let array = try JSONSerialization.jsonObject(with: data) as! [String]
|
||||||
|
for allowedIPString in array {
|
||||||
|
wg_log(.error,message: allowedIPString)
|
||||||
|
guard let allowedIP = IPAddressRange(from: allowedIPString) else {
|
||||||
|
wg_log(.error,message: "Parse SplitTunnelSites Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
allowedIPs.append(allowedIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
wg_log(.error,message: "Parse JSONSerialization Error")
|
||||||
|
}
|
||||||
|
tunnelConfiguration.peers[index].allowedIPs = allowedIPs
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (SplitTunnelType == "2")
|
||||||
|
{
|
||||||
|
wg_log(.error, message: SplitTunnelSites!)
|
||||||
|
for index in tunnelConfiguration.peers.indices {
|
||||||
|
var excludeIPs = [IPAddressRange]()
|
||||||
|
|
||||||
|
let data = Data(SplitTunnelSites!.utf8)
|
||||||
|
do {
|
||||||
|
let array = try JSONSerialization.jsonObject(with: data) as! [String]
|
||||||
|
for excludeIPString in array {
|
||||||
|
wg_log(.error,message: excludeIPString)
|
||||||
|
guard let excludeIP = IPAddressRange(from: excludeIPString) else {
|
||||||
|
wg_log(.error,message: "Parse SplitTunnelSites Error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
excludeIPs.append(excludeIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
wg_log(.error,message: "Parse JSONSerialization Error")
|
||||||
|
}
|
||||||
|
tunnelConfiguration.peers[index].excludeIPs = excludeIPs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wg_log(.error, message: tunnelConfiguration.peers.first!.allowedIPs.map { $0.stringRepresentation }.joined(separator: ", "))
|
||||||
|
|
||||||
wg_log(.info, message: "Starting wireguard tunnel from the " + (activationAttemptId == nil ? "OS directly, rather than the app" : "app"))
|
wg_log(.info, message: "Starting wireguard tunnel from the " + (activationAttemptId == nil ? "OS directly, rather than the app" : "app"))
|
||||||
|
|
||||||
// Start the tunnel
|
// Start the tunnel
|
||||||
|
|
|
||||||
|
|
@ -233,10 +233,6 @@ QString Settings::routeModeString(RouteMode mode) const
|
||||||
|
|
||||||
Settings::RouteMode Settings::routeMode() const
|
Settings::RouteMode Settings::routeMode() const
|
||||||
{
|
{
|
||||||
// TODO implement for mobiles
|
|
||||||
#if defined(Q_OS_IOS)
|
|
||||||
return RouteMode::VpnAllSites;
|
|
||||||
#endif
|
|
||||||
return static_cast<RouteMode>(m_settings.value("Conf/routeMode", 0).toInt());
|
return static_cast<RouteMode>(m_settings.value("Conf/routeMode", 0).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ PageType {
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
visible: GC.isDesktop() || Qt.platform.os === "android"
|
visible: true
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
|
@ -108,11 +108,11 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: !GC.isMobile()
|
visible: GC.isDesktop()
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
visible: false//!GC.isMobile()
|
visible: false
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
|
@ -125,7 +125,7 @@ PageType {
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: false//!GC.isMobile()
|
visible: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue