mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
Compare commits
13 Commits
4.8.11.0
...
feature/wg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61b211995f | ||
|
|
fac3372cb4 | ||
|
|
6a1476af15 | ||
|
|
267222dc59 | ||
|
|
4ac3facc90 | ||
|
|
b5f72080ab | ||
|
|
130bd98abe | ||
|
|
63144ef70f | ||
|
|
24d6e3726e | ||
|
|
dc6eb0546a | ||
|
|
aa7a6770ba | ||
|
|
f802dbfcb8 | ||
|
|
26b8444480 |
@@ -64,7 +64,7 @@ class Awg : Wireguard() {
|
||||
val configDataJson = config.getJSONObject("awg_config_data")
|
||||
val configData = parseConfigData(configDataJson.getString("config"))
|
||||
return AwgConfig.build {
|
||||
configWireguard(configData)
|
||||
configWireguard(configData, configDataJson)
|
||||
configSplitTunneling(config)
|
||||
configData["Jc"]?.let { setJc(it.toInt()) }
|
||||
configData["Jmin"]?.let { setJmin(it.toInt()) }
|
||||
|
||||
@@ -92,12 +92,12 @@ open class Wireguard : Protocol() {
|
||||
val configDataJson = config.getJSONObject("wireguard_config_data")
|
||||
val configData = parseConfigData(configDataJson.getString("config"))
|
||||
return WireguardConfig.build {
|
||||
configWireguard(configData)
|
||||
configWireguard(configData, configDataJson)
|
||||
configSplitTunneling(config)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun WireguardConfig.Builder.configWireguard(configData: Map<String, String>) {
|
||||
protected fun WireguardConfig.Builder.configWireguard(configData: Map<String, String>, configDataJson: JSONObject) {
|
||||
configData["Address"]?.split(",")?.map { address ->
|
||||
InetNetwork.parse(address.trim())
|
||||
}?.forEach(::addAddress)
|
||||
@@ -118,7 +118,14 @@ open class Wireguard : Protocol() {
|
||||
if (routes.any { it !in defRoutes }) disableSplitTunneling()
|
||||
addRoutes(routes)
|
||||
|
||||
configData["MTU"]?.let { setMtu(it.toInt()) }
|
||||
configDataJson.optString("mtu").let { mtu ->
|
||||
if (mtu.isNotEmpty()) {
|
||||
setMtu(mtu.toInt())
|
||||
} else {
|
||||
configData["MTU"]?.let { setMtu(it.toInt()) }
|
||||
}
|
||||
}
|
||||
|
||||
configData["Endpoint"]?.let { setEndpoint(InetEndpoint.parse(it)) }
|
||||
configData["PersistentKeepalive"]?.let { setPersistentKeepalive(it.toInt()) }
|
||||
configData["PrivateKey"]?.let { setPrivateKeyHex(it.base64ToHex()) }
|
||||
|
||||
@@ -41,6 +41,8 @@ QString AwgConfigurator::genAwgConfig(const ServerCredentials &credentials, Dock
|
||||
jsonConfig[config_key::responsePacketMagicHeader] = configMap.value(config_key::responsePacketMagicHeader);
|
||||
jsonConfig[config_key::underloadPacketMagicHeader] = configMap.value(config_key::underloadPacketMagicHeader);
|
||||
jsonConfig[config_key::transportPacketMagicHeader] = configMap.value(config_key::transportPacketMagicHeader);
|
||||
jsonConfig[config_key::mtu] = containerConfig.value(ProtocolProps::protoToString(Proto::Awg)).toObject().
|
||||
value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||
|
||||
return QJsonDocument(jsonConfig).toJson();
|
||||
}
|
||||
|
||||
@@ -194,6 +194,7 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede
|
||||
config.replace("$WIREGUARD_SERVER_PUBLIC_KEY", connData.serverPubKey);
|
||||
config.replace("$WIREGUARD_PSK", connData.pskKey);
|
||||
|
||||
const QJsonObject &wireguarConfig = containerConfig.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject();
|
||||
QJsonObject jConfig;
|
||||
jConfig[config_key::config] = config;
|
||||
|
||||
@@ -205,6 +206,8 @@ QString WireguardConfigurator::genWireguardConfig(const ServerCredentials &crede
|
||||
jConfig[config_key::psk_key] = connData.pskKey;
|
||||
jConfig[config_key::server_pub_key] = connData.serverPubKey;
|
||||
|
||||
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||
|
||||
clientId = connData.clientPubKey;
|
||||
|
||||
return QJsonDocument(jConfig).toJson();
|
||||
|
||||
@@ -365,7 +365,33 @@ bool ServerController::isReinstallContainerRequired(DockerContainer container, c
|
||||
}
|
||||
|
||||
if (container == DockerContainer::Awg) {
|
||||
return true;
|
||||
if ((oldProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::awg::defaultPort))
|
||||
|| (oldProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount)
|
||||
!= newProtoConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount))
|
||||
|| (oldProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize)
|
||||
!= newProtoConfig.value(config_key::junkPacketMinSize).toString(protocols::awg::defaultJunkPacketMinSize))
|
||||
|| (oldProtoConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize)
|
||||
!= newProtoConfig.value(config_key::junkPacketMaxSize).toString(protocols::awg::defaultJunkPacketMaxSize))
|
||||
|| (oldProtoConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize)
|
||||
!= newProtoConfig.value(config_key::initPacketJunkSize).toString(protocols::awg::defaultInitPacketJunkSize))
|
||||
|| (oldProtoConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize)
|
||||
!= newProtoConfig.value(config_key::responsePacketJunkSize).toString(protocols::awg::defaultResponsePacketJunkSize))
|
||||
|| (oldProtoConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::initPacketMagicHeader).toString(protocols::awg::defaultInitPacketMagicHeader))
|
||||
|| (oldProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::responsePacketMagicHeader).toString(protocols::awg::defaultResponsePacketMagicHeader))
|
||||
|| (oldProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::underloadPacketMagicHeader).toString(protocols::awg::defaultUnderloadPacketMagicHeader))
|
||||
|| (oldProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)
|
||||
!= newProtoConfig.value(config_key::transportPacketMagicHeader).toString(protocols::awg::defaultTransportPacketMagicHeader)))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (container == DockerContainer::WireGuard){
|
||||
if (oldProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort)
|
||||
!= newProtoConfig.value(config_key::port).toString(protocols::wireguard::defaultPort))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -251,6 +251,13 @@ bool Daemon::parseConfig(const QJsonObject& obj, InterfaceConfig& config) {
|
||||
GETVALUE("serverPskKey", config.m_serverPskKey, String);
|
||||
GETVALUE("serverPort", config.m_serverPort, Double);
|
||||
|
||||
if (!obj.contains("deviceMTU") || obj.value("deviceMTU").toString().toInt() == 0)
|
||||
{
|
||||
config.m_deviceMTU = 1420;
|
||||
} else {
|
||||
config.m_deviceMTU = obj.value("deviceMTU").toString().toInt();
|
||||
}
|
||||
|
||||
config.m_deviceIpv4Address = obj.value("deviceIpv4Address").toString();
|
||||
config.m_deviceIpv6Address = obj.value("deviceIpv6Address").toString();
|
||||
if (config.m_deviceIpv4Address.isNull() &&
|
||||
|
||||
@@ -23,6 +23,7 @@ QJsonObject InterfaceConfig::toJson() const {
|
||||
json.insert("serverIpv4AddrIn", QJsonValue(m_serverIpv4AddrIn));
|
||||
json.insert("serverIpv6AddrIn", QJsonValue(m_serverIpv6AddrIn));
|
||||
json.insert("serverPort", QJsonValue((double)m_serverPort));
|
||||
json.insert("deviceMTU", QJsonValue(m_deviceMTU));
|
||||
if ((m_hopType == InterfaceConfig::MultiHopExit) ||
|
||||
(m_hopType == InterfaceConfig::SingleHop)) {
|
||||
json.insert("serverIpv4Gateway", QJsonValue(m_serverIpv4Gateway));
|
||||
@@ -85,8 +86,13 @@ QString InterfaceConfig::toWgConf(const QMap<QString, QString>& extra) const {
|
||||
if (addresses.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
out << "Address = " << addresses.join(", ") << "\n";
|
||||
|
||||
if (m_deviceMTU) {
|
||||
out << "MTU = " << m_deviceMTU << "\n";
|
||||
}
|
||||
|
||||
if (!m_dnsServer.isNull()) {
|
||||
QStringList dnsServers(m_dnsServer);
|
||||
// If the DNS is not the Gateway, it's a user defined DNS
|
||||
|
||||
@@ -33,6 +33,7 @@ class InterfaceConfig {
|
||||
QString m_serverIpv6AddrIn;
|
||||
QString m_dnsServer;
|
||||
int m_serverPort = 0;
|
||||
int m_deviceMTU = 1420;
|
||||
QList<IPAddress> m_allowedIPAddressRanges;
|
||||
QStringList m_excludedAddresses;
|
||||
QStringList m_vpnDisabledApps;
|
||||
|
||||
@@ -85,6 +85,7 @@ target_sources(networkextension PRIVATE
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
||||
)
|
||||
|
||||
|
||||
@@ -129,8 +129,9 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
||||
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
|
||||
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));
|
||||
// json.insert("serverIpv6AddrIn", QJsonValue(hop.m_server.ipv6AddrIn()));
|
||||
json.insert("serverPort", wgConfig.value(amnezia::config_key::port).toInt());
|
||||
json.insert("deviceMTU", wgConfig.value(amnezia::config_key::mtu));
|
||||
|
||||
json.insert("serverPort", wgConfig.value(amnezia::config_key::port).toInt());
|
||||
json.insert("serverIpv4Gateway", wgConfig.value(amnezia::config_key::hostName));
|
||||
// json.insert("serverIpv6Gateway", QJsonValue(hop.m_server.ipv6Gateway()));
|
||||
json.insert("dnsServer", rawConfig.value(amnezia::config_key::dns1));
|
||||
|
||||
@@ -38,7 +38,7 @@ struct Log {
|
||||
init(_ str: String) {
|
||||
self.records = str.split(whereSeparator: \.isNewline)
|
||||
.compactMap {
|
||||
Record(String($0))!
|
||||
Record(String($0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,40 +18,32 @@ extension PacketTunnelProvider: OpenVPNAdapterDelegate {
|
||||
// send empty string to NEDNSSettings.matchDomains
|
||||
networkSettings?.dnsSettings?.matchDomains = [""]
|
||||
|
||||
if splitTunnelType == "1" {
|
||||
if splitTunnelType == 1 {
|
||||
var ipv4IncludedRoutes = [NEIPv4Route]()
|
||||
let STSdata = Data(splitTunnelSites!.utf8)
|
||||
do {
|
||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
||||
for allowedIPString in STSArray {
|
||||
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
||||
ipv4IncludedRoutes.append(NEIPv4Route(
|
||||
destinationAddress: "\(allowedIP.address)",
|
||||
subnetMask: "\(allowedIP.subnetMask())"))
|
||||
}
|
||||
|
||||
for allowedIPString in splitTunnelSites {
|
||||
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
||||
ipv4IncludedRoutes.append(NEIPv4Route(
|
||||
destinationAddress: "\(allowedIP.address)",
|
||||
subnetMask: "\(allowedIP.subnetMask())"))
|
||||
}
|
||||
} catch {
|
||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
||||
}
|
||||
|
||||
networkSettings?.ipv4Settings?.includedRoutes = ipv4IncludedRoutes
|
||||
} else {
|
||||
if splitTunnelType == "2" {
|
||||
if splitTunnelType == 2 {
|
||||
var ipv4ExcludedRoutes = [NEIPv4Route]()
|
||||
var ipv4IncludedRoutes = [NEIPv4Route]()
|
||||
var ipv6IncludedRoutes = [NEIPv6Route]()
|
||||
let STSdata = Data(splitTunnelSites!.utf8)
|
||||
do {
|
||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
||||
for excludeIPString in STSArray {
|
||||
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
||||
ipv4ExcludedRoutes.append(NEIPv4Route(
|
||||
destinationAddress: "\(excludeIP.address)",
|
||||
subnetMask: "\(excludeIP.subnetMask())"))
|
||||
}
|
||||
|
||||
for excludeIPString in splitTunnelSites {
|
||||
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
||||
ipv4ExcludedRoutes.append(NEIPv4Route(
|
||||
destinationAddress: "\(excludeIP.address)",
|
||||
subnetMask: "\(excludeIP.subnetMask())"))
|
||||
}
|
||||
} catch {
|
||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
||||
}
|
||||
|
||||
if let allIPv4 = IPAddressRange(from: "0.0.0.0/0") {
|
||||
ipv4IncludedRoutes.append(NEIPv4Route(
|
||||
destinationAddress: "\(allIPv4.address)",
|
||||
|
||||
@@ -50,8 +50,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
private let dispatchQueue = DispatchQueue(label: "PacketTunnel", qos: .utility)
|
||||
|
||||
private var openVPNConfig: Data?
|
||||
var splitTunnelType: String?
|
||||
var splitTunnelSites: String?
|
||||
var splitTunnelType: Int!
|
||||
var splitTunnelSites: [String]!
|
||||
|
||||
let vpnReachability = OpenVPNReachability()
|
||||
|
||||
@@ -59,10 +59,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
var stopHandler: (() -> Void)?
|
||||
var protoType: TunnelProtoType = .none
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
||||
let tmpStr = String(data: messageData, encoding: .utf8)!
|
||||
wg_log(.error, message: tmpStr)
|
||||
@@ -71,7 +67,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
return
|
||||
}
|
||||
|
||||
guard let completionHandler = completionHandler else {
|
||||
guard let completionHandler else {
|
||||
log(.error, message: "Missing message completion handler")
|
||||
return
|
||||
}
|
||||
@@ -87,8 +83,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
}
|
||||
|
||||
if action == Constants.kActionStart {
|
||||
splitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String
|
||||
splitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String
|
||||
// splitTunnelType = message[Constants.kMessageKeySplitTunnelType] as? String
|
||||
// splitTunnelSites = message[Constants.kMessageKeySplitTunnelSites] as? String
|
||||
}
|
||||
|
||||
let callbackWrapper: (NSNumber?) -> Void = { errorCode in
|
||||
@@ -173,108 +169,118 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
completionHandler: @escaping (Error?) -> Void) {
|
||||
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
||||
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
||||
let wgConfig: Data = providerConfiguration[Constants.wireGuardConfigKey] as? Data else {
|
||||
let wgConfigData: Data = providerConfiguration[Constants.wireGuardConfigKey] as? Data else {
|
||||
wg_log(.error, message: "Can't start WireGuard config missing")
|
||||
completionHandler(nil)
|
||||
return
|
||||
}
|
||||
|
||||
let wgConfigStr = String(data: wgConfig, encoding: .utf8)!
|
||||
do {
|
||||
let wgConfig = try JSONDecoder().decode(WGConfig.self, from: wgConfigData)
|
||||
let wgConfigStr = wgConfig.str
|
||||
log(.info, message: "wgConfig: \(wgConfig.redux.replacingOccurrences(of: "\n", with: " "))")
|
||||
|
||||
guard let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr) else {
|
||||
wg_log(.error, message: "Can't parse WireGuard config")
|
||||
completionHandler(nil)
|
||||
return
|
||||
}
|
||||
let tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: wgConfigStr)
|
||||
|
||||
if tunnelConfiguration.peers.first!.allowedIPs
|
||||
.map({ $0.stringRepresentation })
|
||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
||||
if splitTunnelType == "1" {
|
||||
for index in tunnelConfiguration.peers.indices {
|
||||
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
||||
var allowedIPs = [IPAddressRange]()
|
||||
let STSdata = Data(splitTunnelSites!.utf8)
|
||||
do {
|
||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
||||
for allowedIPString in STSArray {
|
||||
if tunnelConfiguration.peers.first!.allowedIPs
|
||||
.map({ $0.stringRepresentation })
|
||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
||||
if wgConfig.splitTunnelType == 1 {
|
||||
for index in tunnelConfiguration.peers.indices {
|
||||
tunnelConfiguration.peers[index].allowedIPs.removeAll()
|
||||
var allowedIPs = [IPAddressRange]()
|
||||
|
||||
for allowedIPString in wgConfig.splitTunnelSites {
|
||||
if let allowedIP = IPAddressRange(from: allowedIPString) {
|
||||
allowedIPs.append(allowedIP)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
||||
|
||||
tunnelConfiguration.peers[index].allowedIPs = allowedIPs
|
||||
}
|
||||
tunnelConfiguration.peers[index].allowedIPs = allowedIPs
|
||||
}
|
||||
} else if splitTunnelType == "2" {
|
||||
for index in tunnelConfiguration.peers.indices {
|
||||
var excludeIPs = [IPAddressRange]()
|
||||
let STSdata = Data(splitTunnelSites!.utf8)
|
||||
do {
|
||||
guard let STSArray = try JSONSerialization.jsonObject(with: STSdata) as? [String] else { return }
|
||||
for excludeIPString in STSArray {
|
||||
} else if wgConfig.splitTunnelType == 2 {
|
||||
for index in tunnelConfiguration.peers.indices {
|
||||
var excludeIPs = [IPAddressRange]()
|
||||
|
||||
for excludeIPString in wgConfig.splitTunnelSites {
|
||||
if let excludeIP = IPAddressRange(from: excludeIPString) {
|
||||
excludeIPs.append(excludeIP)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
wg_log(.error, message: "Parse JSONSerialization Error")
|
||||
|
||||
tunnelConfiguration.peers[index].excludeIPs = excludeIPs
|
||||
}
|
||||
tunnelConfiguration.peers[index].excludeIPs = excludeIPs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
|
||||
guard let adapterError else {
|
||||
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
|
||||
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
|
||||
completionHandler(nil)
|
||||
return
|
||||
}
|
||||
|
||||
switch adapterError {
|
||||
case .cannotLocateTunnelFileDescriptor:
|
||||
wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor")
|
||||
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
||||
completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
||||
case .dnsResolution(let dnsErrors):
|
||||
let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address }
|
||||
.joined(separator: ", ")
|
||||
wg_log(.error, message:
|
||||
"DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure)
|
||||
completionHandler(PacketTunnelProviderError.dnsResolutionFailure)
|
||||
case .setNetworkSettings(let error):
|
||||
wg_log(.error, message:
|
||||
"Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
||||
completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
||||
case .startWireGuardBackend(let errorCode):
|
||||
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
|
||||
completionHandler(PacketTunnelProviderError.couldNotStartBackend)
|
||||
case .invalidState:
|
||||
fatalError()
|
||||
// Start the tunnel
|
||||
wgAdapter.start(tunnelConfiguration: tunnelConfiguration) { adapterError in
|
||||
guard let adapterError else {
|
||||
let interfaceName = self.wgAdapter.interfaceName ?? "unknown"
|
||||
wg_log(.info, message: "Tunnel interface is \(interfaceName)")
|
||||
completionHandler(nil)
|
||||
return
|
||||
}
|
||||
|
||||
switch adapterError {
|
||||
case .cannotLocateTunnelFileDescriptor:
|
||||
wg_log(.error, staticMessage: "Starting tunnel failed: could not determine file descriptor")
|
||||
errorNotifier.notify(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
||||
completionHandler(PacketTunnelProviderError.couldNotDetermineFileDescriptor)
|
||||
case .dnsResolution(let dnsErrors):
|
||||
let hostnamesWithDnsResolutionFailure = dnsErrors.map { $0.address }
|
||||
.joined(separator: ", ")
|
||||
wg_log(.error, message:
|
||||
"DNS resolution failed for the following hostnames: \(hostnamesWithDnsResolutionFailure)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.dnsResolutionFailure)
|
||||
completionHandler(PacketTunnelProviderError.dnsResolutionFailure)
|
||||
case .setNetworkSettings(let error):
|
||||
wg_log(.error, message:
|
||||
"Starting tunnel failed with setTunnelNetworkSettings returning \(error.localizedDescription)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
||||
completionHandler(PacketTunnelProviderError.couldNotSetNetworkSettings)
|
||||
case .startWireGuardBackend(let errorCode):
|
||||
wg_log(.error, message: "Starting tunnel failed with wgTurnOn returning \(errorCode)")
|
||||
errorNotifier.notify(PacketTunnelProviderError.couldNotStartBackend)
|
||||
completionHandler(PacketTunnelProviderError.couldNotStartBackend)
|
||||
case .invalidState:
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
log(.error, message: "Can't parse WG config: \(error.localizedDescription)")
|
||||
completionHandler(nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) {
|
||||
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
|
||||
let providerConfiguration = protocolConfiguration.providerConfiguration,
|
||||
let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else {
|
||||
|
||||
let openVPNConfigData = providerConfiguration[Constants.ovpnConfigKey] as? Data else {
|
||||
wg_log(.error, message: "Can't start startOpenVPN()")
|
||||
return
|
||||
}
|
||||
|
||||
setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler)
|
||||
do {
|
||||
log(.info, message: "providerConfiguration: \(String(decoding: openVPNConfigData, as: UTF8.self).replacingOccurrences(of: "\n", with: " "))")
|
||||
|
||||
let openVPNConfig = try JSONDecoder().decode(OpenVPNConfig.self, from: openVPNConfigData)
|
||||
log(.info, message: "openVPNConfig: \(openVPNConfig.str.replacingOccurrences(of: "\n", with: " "))")
|
||||
let ovpnConfiguration = Data(openVPNConfig.config.utf8)
|
||||
setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler)
|
||||
} catch {
|
||||
log(.error, message: "Can't parse OpenVPN config: \(error.localizedDescription)")
|
||||
|
||||
if let underlyingError = (error as NSError).userInfo[NSUnderlyingErrorKey] as? NSError {
|
||||
log(.error, message: "Can't parse OpenVPN config: \(underlyingError.localizedDescription)")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
|
||||
100
client/platforms/ios/WGConfig.swift
Normal file
100
client/platforms/ios/WGConfig.swift
Normal file
@@ -0,0 +1,100 @@
|
||||
import Foundation
|
||||
|
||||
struct WGConfig: Decodable {
|
||||
let h1, h2, h3, h4: String?
|
||||
let jc, jmax, jmin: String?
|
||||
let s1, s2: String?
|
||||
let dns1: String
|
||||
let dns2: String
|
||||
let mtu: String
|
||||
let hostName: String
|
||||
let port: Int
|
||||
let clientIP: String
|
||||
let clientPrivateKey: String
|
||||
let serverPublicKey: String
|
||||
let presharedKey: String
|
||||
var allowedIPs: [String]
|
||||
var persistentKeepAlive: String
|
||||
let splitTunnelType: Int
|
||||
let splitTunnelSites: [String]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case h1 = "H1", h2 = "H2", h3 = "H3", h4 = "H4"
|
||||
case jc = "Jc", jmax = "Jmax", jmin = "Jmin"
|
||||
case s1 = "S1", s2 = "S2"
|
||||
case dns1
|
||||
case dns2
|
||||
case mtu
|
||||
case hostName
|
||||
case port
|
||||
case clientIP = "client_ip"
|
||||
case clientPrivateKey = "client_priv_key"
|
||||
case serverPublicKey = "server_pub_key"
|
||||
case presharedKey = "psk_key"
|
||||
case allowedIPs = "allowed_ips"
|
||||
case persistentKeepAlive = "persistent_keep_alive"
|
||||
case splitTunnelType
|
||||
case splitTunnelSites
|
||||
}
|
||||
|
||||
var settings: String {
|
||||
jc == nil ? "" :
|
||||
"""
|
||||
Jc = \(jc!)
|
||||
Jmin = \(jmin!)
|
||||
Jmax = \(jmax!)
|
||||
S1 = \(s1!)
|
||||
S2 = \(s2!)
|
||||
H1 = \(h1!)
|
||||
H2 = \(h2!)
|
||||
H3 = \(h3!)
|
||||
H4 = \(h4!)
|
||||
|
||||
"""
|
||||
}
|
||||
|
||||
var str: String {
|
||||
"""
|
||||
[Interface]
|
||||
Address = \(clientIP)/32
|
||||
DNS = \(dns1), \(dns2)
|
||||
MTU = \(mtu)
|
||||
PrivateKey = \(clientPrivateKey)
|
||||
\(settings)
|
||||
[Peer]
|
||||
PublicKey = \(serverPublicKey)
|
||||
PresharedKey = \(presharedKey)
|
||||
AllowedIPs = \(allowedIPs.joined(separator: ", "))
|
||||
Endpoint = \(hostName):\(port)
|
||||
PersistentKeepalive = \(persistentKeepAlive)
|
||||
"""
|
||||
}
|
||||
|
||||
var redux: String {
|
||||
"""
|
||||
[Interface]
|
||||
Address = \(clientIP)/32
|
||||
DNS = \(dns1), \(dns2)
|
||||
MTU = \(mtu)
|
||||
PrivateKey = ***
|
||||
\(settings)
|
||||
[Peer]
|
||||
PublicKey = ***
|
||||
PresharedKey = ***
|
||||
AllowedIPs = \(allowedIPs.joined(separator: ", "))
|
||||
Endpoint = \(hostName):\(port)
|
||||
PersistentKeepalive = \(persistentKeepAlive)
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
struct OpenVPNConfig: Decodable {
|
||||
let config: String
|
||||
let mtu: String
|
||||
let splitTunnelType: Int
|
||||
let splitTunnelSites: [String]
|
||||
|
||||
var str: String {
|
||||
"splitTunnelType: \(splitTunnelType) splitTunnelSites: \(splitTunnelSites) mtu: \(mtu) config: \(config)"
|
||||
}
|
||||
}
|
||||
@@ -357,7 +357,22 @@ bool IosController::setupOpenVPN()
|
||||
QJsonObject ovpn = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::OpenVpn)].toObject();
|
||||
QString ovpnConfig = ovpn[config_key::config].toString();
|
||||
|
||||
return startOpenVPN(ovpnConfig);
|
||||
QJsonObject openVPNConfig {};
|
||||
openVPNConfig.insert(config_key::config, ovpnConfig);
|
||||
|
||||
if (ovpn.contains(config_key::mtu)) {
|
||||
openVPNConfig.insert(config_key::mtu, ovpn[config_key::mtu]);
|
||||
} else {
|
||||
openVPNConfig.insert(config_key::mtu, protocols::openvpn::defaultMtu);
|
||||
}
|
||||
|
||||
openVPNConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||
openVPNConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||
|
||||
QJsonDocument openVPNConfigDoc(openVPNConfig);
|
||||
QString openVPNConfigStr(openVPNConfigDoc.toJson(QJsonDocument::Compact));
|
||||
|
||||
return startOpenVPN(openVPNConfigStr);
|
||||
}
|
||||
|
||||
bool IosController::setupCloak()
|
||||
@@ -394,25 +409,119 @@ bool IosController::setupCloak()
|
||||
ovpnConfig.append(cloakBase64);
|
||||
ovpnConfig.append("\n</cloak>\n");
|
||||
|
||||
return startOpenVPN(ovpnConfig);
|
||||
QJsonObject openVPNConfig {};
|
||||
openVPNConfig.insert(config_key::config, ovpnConfig);
|
||||
|
||||
if (ovpn.contains(config_key::mtu)) {
|
||||
openVPNConfig.insert(config_key::mtu, ovpn[config_key::mtu]);
|
||||
} else {
|
||||
openVPNConfig.insert(config_key::mtu, protocols::openvpn::defaultMtu);
|
||||
}
|
||||
|
||||
openVPNConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||
openVPNConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||
|
||||
QJsonDocument openVPNConfigDoc(openVPNConfig);
|
||||
QString openVPNConfigStr(openVPNConfigDoc.toJson(QJsonDocument::Compact));
|
||||
|
||||
return startOpenVPN(openVPNConfigStr);
|
||||
}
|
||||
|
||||
bool IosController::setupWireGuard()
|
||||
{
|
||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
||||
|
||||
QString wgConfig = config[config_key::config].toString();
|
||||
|
||||
return startWireGuard(wgConfig);
|
||||
QJsonObject wgConfig {};
|
||||
wgConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]);
|
||||
wgConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]);
|
||||
|
||||
if (config.contains(config_key::mtu)) {
|
||||
wgConfig.insert(config_key::mtu, config[config_key::mtu]);
|
||||
} else {
|
||||
wgConfig.insert(config_key::mtu, protocols::wireguard::defaultMtu);
|
||||
}
|
||||
|
||||
wgConfig.insert(config_key::hostName, config[config_key::hostName]);
|
||||
wgConfig.insert(config_key::port, config[config_key::port]);
|
||||
wgConfig.insert(config_key::client_ip, config[config_key::client_ip]);
|
||||
wgConfig.insert(config_key::client_priv_key, config[config_key::client_priv_key]);
|
||||
wgConfig.insert(config_key::server_pub_key, config[config_key::server_pub_key]);
|
||||
wgConfig.insert(config_key::psk_key, config[config_key::psk_key]);
|
||||
wgConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||
wgConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||
|
||||
if (config.contains(config_key::allowed_ips)) {
|
||||
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||
} else {
|
||||
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
||||
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||
}
|
||||
|
||||
if (config.contains(config_key::persistent_keep_alive)) {
|
||||
wgConfig.insert(config_key::persistent_keep_alive, config[config_key::persistent_keep_alive]);
|
||||
} else {
|
||||
wgConfig.insert(config_key::persistent_keep_alive, "25");
|
||||
}
|
||||
|
||||
QJsonDocument wgConfigDoc(wgConfig);
|
||||
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
||||
|
||||
return startWireGuard(wgConfigDocStr);
|
||||
}
|
||||
|
||||
bool IosController::setupAwg()
|
||||
{
|
||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
||||
|
||||
QString wgConfig = config[config_key::config].toString();
|
||||
|
||||
return startWireGuard(wgConfig);
|
||||
QJsonObject wgConfig {};
|
||||
wgConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]);
|
||||
wgConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]);
|
||||
|
||||
if (config.contains(config_key::mtu)) {
|
||||
wgConfig.insert(config_key::mtu, config[config_key::mtu]);
|
||||
} else {
|
||||
wgConfig.insert(config_key::mtu, protocols::awg::defaultMtu);
|
||||
}
|
||||
|
||||
wgConfig.insert(config_key::mtu, config[config_key::mtu]);
|
||||
wgConfig.insert(config_key::hostName, config[config_key::hostName]);
|
||||
wgConfig.insert(config_key::port, config[config_key::port]);
|
||||
wgConfig.insert(config_key::client_ip, config[config_key::client_ip]);
|
||||
wgConfig.insert(config_key::client_priv_key, config[config_key::client_priv_key]);
|
||||
wgConfig.insert(config_key::server_pub_key, config[config_key::server_pub_key]);
|
||||
wgConfig.insert(config_key::psk_key, config[config_key::psk_key]);
|
||||
wgConfig.insert(config_key::splitTunnelType, m_rawConfig[config_key::splitTunnelType]);
|
||||
wgConfig.insert(config_key::splitTunnelSites, m_rawConfig[config_key::splitTunnelSites]);
|
||||
|
||||
if (config.contains(config_key::allowed_ips)) {
|
||||
wgConfig.insert(config_key::allowed_ips, config[config_key::allowed_ips]);
|
||||
} else {
|
||||
QJsonArray allowed_ips { "0.0.0.0/0", "::/0" };
|
||||
wgConfig.insert(config_key::allowed_ips, allowed_ips);
|
||||
}
|
||||
|
||||
if (config.contains(config_key::persistent_keep_alive)) {
|
||||
wgConfig.insert(config_key::persistent_keep_alive, config[config_key::persistent_keep_alive]);
|
||||
} else {
|
||||
wgConfig.insert(config_key::persistent_keep_alive, "25");
|
||||
}
|
||||
|
||||
wgConfig.insert(config_key::initPacketMagicHeader, config[config_key::initPacketMagicHeader]);
|
||||
wgConfig.insert(config_key::responsePacketMagicHeader, config[config_key::responsePacketMagicHeader]);
|
||||
wgConfig.insert(config_key::underloadPacketMagicHeader, config[config_key::underloadPacketMagicHeader]);
|
||||
wgConfig.insert(config_key::transportPacketMagicHeader, config[config_key::transportPacketMagicHeader]);
|
||||
|
||||
wgConfig.insert(config_key::initPacketJunkSize, config[config_key::initPacketJunkSize]);
|
||||
wgConfig.insert(config_key::responsePacketJunkSize, config[config_key::responsePacketJunkSize]);
|
||||
|
||||
wgConfig.insert(config_key::junkPacketCount, config[config_key::junkPacketCount]);
|
||||
wgConfig.insert(config_key::junkPacketMinSize, config[config_key::junkPacketMinSize]);
|
||||
wgConfig.insert(config_key::junkPacketMaxSize, config[config_key::junkPacketMaxSize]);
|
||||
|
||||
QJsonDocument wgConfigDoc(wgConfig);
|
||||
QString wgConfigDocStr(wgConfigDoc.toJson(QJsonDocument::Compact));
|
||||
|
||||
return startWireGuard(wgConfigDocStr);
|
||||
}
|
||||
|
||||
bool IosController::startOpenVPN(const QString &config)
|
||||
@@ -497,7 +606,7 @@ void IosController::startTunnel()
|
||||
NSDictionary* message = @{actionKey: actionValue, tunnelIdKey: tunnelIdValue,
|
||||
SplitTunnelTypeKey: SplitTunnelTypeValue, SplitTunnelSitesKey: SplitTunnelSitesValue};
|
||||
|
||||
sendVpnExtensionMessage(message);
|
||||
// sendVpnExtensionMessage(message);
|
||||
|
||||
|
||||
BOOL started = [m_currentTunnel.connection startVPNTunnelWithOptions:nil andReturnError:&startError];
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
#include "leakdetector.h"
|
||||
#include "logger.h"
|
||||
|
||||
constexpr uint32_t ETH_MTU = 1500;
|
||||
constexpr uint32_t WG_MTU_OVERHEAD = 80;
|
||||
|
||||
namespace {
|
||||
Logger logger("IPUtilsLinux");
|
||||
}
|
||||
@@ -38,8 +35,6 @@ bool IPUtilsLinux::addInterfaceIPs(const InterfaceConfig& config) {
|
||||
}
|
||||
|
||||
bool IPUtilsLinux::setMTUAndUp(const InterfaceConfig& config) {
|
||||
Q_UNUSED(config);
|
||||
|
||||
// Create socket file descriptor to perform the ioctl operations on
|
||||
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (sockfd < 0) {
|
||||
@@ -56,10 +51,10 @@ bool IPUtilsLinux::setMTUAndUp(const InterfaceConfig& config) {
|
||||
// FIXME: We need to know how many layers deep this particular
|
||||
// interface is into a tunnel to work effectively. Otherwise
|
||||
// we will run into fragmentation issues.
|
||||
ifr.ifr_mtu = ETH_MTU - WG_MTU_OVERHEAD;
|
||||
ifr.ifr_mtu = config.m_deviceMTU;
|
||||
int ret = ioctl(sockfd, SIOCSIFMTU, &ifr);
|
||||
if (ret) {
|
||||
logger.error() << "Failed to set MTU -- Return code: " << ret;
|
||||
logger.error() << "Failed to set MTU -- " << config.m_deviceMTU << " -- Return code: " << ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
#include "logger.h"
|
||||
#include "macosdaemon.h"
|
||||
|
||||
constexpr uint32_t ETH_MTU = 1500;
|
||||
constexpr uint32_t WG_MTU_OVERHEAD = 80;
|
||||
|
||||
namespace {
|
||||
Logger logger("IPUtilsMacos");
|
||||
}
|
||||
@@ -56,10 +53,10 @@ bool IPUtilsMacos::setMTUAndUp(const InterfaceConfig& config) {
|
||||
|
||||
// MTU
|
||||
strncpy(ifr.ifr_name, qPrintable(ifname), IFNAMSIZ);
|
||||
ifr.ifr_mtu = ETH_MTU - WG_MTU_OVERHEAD;
|
||||
ifr.ifr_mtu = config.m_deviceMTU;
|
||||
int ret = ioctl(sockfd, SIOCSIFMTU, &ifr);
|
||||
if (ret) {
|
||||
logger.error() << "Failed to set MTU:" << strerror(errno);
|
||||
logger.error() << "Failed to set MTU -- " << config.m_deviceMTU << " -- Return code: " << ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,9 @@ namespace amnezia
|
||||
constexpr char server_priv_key[] = "server_priv_key";
|
||||
constexpr char server_pub_key[] = "server_pub_key";
|
||||
constexpr char psk_key[] = "psk_key";
|
||||
constexpr char mtu[] = "mtu";
|
||||
constexpr char allowed_ips[] = "allowed_ips";
|
||||
constexpr char persistent_keep_alive[] = "persistent_keep_alive";
|
||||
|
||||
constexpr char client_ip[] = "client_ip"; // internal ip address
|
||||
|
||||
@@ -102,6 +104,7 @@ namespace amnezia
|
||||
constexpr char defaultSubnetAddress[] = "10.8.0.0";
|
||||
constexpr char defaultSubnetMask[] = "255.255.255.0";
|
||||
constexpr char defaultSubnetCidr[] = "24";
|
||||
constexpr char defaultMtu[] = "1500";
|
||||
|
||||
constexpr char serverConfigPath[] = "/opt/amnezia/openvpn/server.conf";
|
||||
constexpr char caCertPath[] = "/opt/amnezia/openvpn/pki/ca.crt";
|
||||
@@ -148,6 +151,7 @@ namespace amnezia
|
||||
constexpr char defaultSubnetCidr[] = "24";
|
||||
|
||||
constexpr char defaultPort[] = "51820";
|
||||
constexpr char defaultMtu[] = "1420";
|
||||
constexpr char serverConfigPath[] = "/opt/amnezia/wireguard/wg0.conf";
|
||||
constexpr char serverPublicKeyPath[] = "/opt/amnezia/wireguard/wireguard_server_public_key.key";
|
||||
constexpr char serverPskKeyPath[] = "/opt/amnezia/wireguard/wireguard_psk.key";
|
||||
@@ -163,6 +167,7 @@ namespace amnezia
|
||||
namespace awg
|
||||
{
|
||||
constexpr char defaultPort[] = "55424";
|
||||
constexpr char defaultMtu[] = "1420";
|
||||
|
||||
constexpr char serverConfigPath[] = "/opt/amnezia/awg/wg0.conf";
|
||||
constexpr char serverPublicKeyPath[] = "/opt/amnezia/awg/wireguard_server_public_key.key";
|
||||
|
||||
@@ -225,5 +225,6 @@
|
||||
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
|
||||
<file>images/controls/close.svg</file>
|
||||
<file>images/controls/search.svg</file>
|
||||
<file>ui/qml/Pages2/PageProtocolWireGuardSettings.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -259,6 +259,10 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
// return QJsonObject();
|
||||
// }
|
||||
|
||||
if (!configMap.value("MTU").isEmpty()) {
|
||||
lastConfig[config_key::mtu] = configMap.value("MTU");
|
||||
}
|
||||
|
||||
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(","));
|
||||
|
||||
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;
|
||||
|
||||
@@ -22,6 +22,7 @@ bool AwgConfigModel::setData(const QModelIndex &index, const QVariant &value, in
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||
case Roles::JunkPacketCountRole: m_protocolConfig.insert(config_key::junkPacketCount, value.toString()); break;
|
||||
case Roles::JunkPacketMinSizeRole: m_protocolConfig.insert(config_key::junkPacketMinSize, value.toString()); break;
|
||||
case Roles::JunkPacketMaxSizeRole: m_protocolConfig.insert(config_key::junkPacketMaxSize, value.toString()); break;
|
||||
@@ -57,6 +58,7 @@ QVariant AwgConfigModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
||||
case Roles::JunkPacketCountRole: return m_protocolConfig.value(config_key::junkPacketCount);
|
||||
case Roles::JunkPacketMinSizeRole: return m_protocolConfig.value(config_key::junkPacketMinSize);
|
||||
case Roles::JunkPacketMaxSizeRole: return m_protocolConfig.value(config_key::junkPacketMaxSize);
|
||||
@@ -82,6 +84,8 @@ void AwgConfigModel::updateModel(const QJsonObject &config)
|
||||
|
||||
m_protocolConfig[config_key::port] =
|
||||
protocolConfig.value(config_key::port).toString(protocols::awg::defaultPort);
|
||||
m_protocolConfig[config_key::mtu] =
|
||||
protocolConfig.value(config_key::mtu).toString(protocols::awg::defaultMtu);
|
||||
m_protocolConfig[config_key::junkPacketCount] =
|
||||
protocolConfig.value(config_key::junkPacketCount).toString(protocols::awg::defaultJunkPacketCount);
|
||||
m_protocolConfig[config_key::junkPacketMinSize] =
|
||||
@@ -123,6 +127,7 @@ QHash<int, QByteArray> AwgConfigModel::roleNames() const
|
||||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[PortRole] = "port";
|
||||
roles[MtuRole] = "mtu";
|
||||
roles[JunkPacketCountRole] = "junkPacketCount";
|
||||
roles[JunkPacketMinSizeRole] = "junkPacketMinSize";
|
||||
roles[JunkPacketMaxSizeRole] = "junkPacketMaxSize";
|
||||
|
||||
@@ -13,6 +13,7 @@ class AwgConfigModel : public QAbstractListModel
|
||||
public:
|
||||
enum Roles {
|
||||
PortRole = Qt::UserRole + 1,
|
||||
MtuRole,
|
||||
JunkPacketCountRole,
|
||||
JunkPacketMinSizeRole,
|
||||
JunkPacketMaxSizeRole,
|
||||
|
||||
@@ -19,8 +19,8 @@ bool WireGuardConfigModel::setData(const QModelIndex &index, const QVariant &val
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::CipherRole: m_protocolConfig.insert(config_key::cipher, value.toString()); break;
|
||||
case Roles::PortRole: m_protocolConfig.insert(config_key::port, value.toString()); break;
|
||||
case Roles::MtuRole: m_protocolConfig.insert(config_key::mtu, value.toString()); break;
|
||||
}
|
||||
|
||||
emit dataChanged(index, index, QList { role });
|
||||
@@ -34,9 +34,8 @@ QVariant WireGuardConfigModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
|
||||
switch (role) {
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort);
|
||||
case Roles::CipherRole:
|
||||
return m_protocolConfig.value(config_key::cipher).toString(protocols::shadowsocks::defaultCipher);
|
||||
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
|
||||
case Roles::MtuRole: return m_protocolConfig.value(config_key::mtu).toString();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@@ -50,6 +49,12 @@ void WireGuardConfigModel::updateModel(const QJsonObject &config)
|
||||
m_fullConfig = config;
|
||||
QJsonObject protocolConfig = config.value(config_key::wireguard).toObject();
|
||||
|
||||
m_protocolConfig[config_key::port] =
|
||||
protocolConfig.value(config_key::port).toString(protocols::wireguard::defaultPort);
|
||||
|
||||
m_protocolConfig[config_key::mtu] =
|
||||
protocolConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
@@ -64,7 +69,7 @@ QHash<int, QByteArray> WireGuardConfigModel::roleNames() const
|
||||
QHash<int, QByteArray> roles;
|
||||
|
||||
roles[PortRole] = "port";
|
||||
roles[CipherRole] = "cipher";
|
||||
roles[MtuRole] = "mtu";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class WireGuardConfigModel : public QAbstractListModel
|
||||
public:
|
||||
enum Roles {
|
||||
PortRole = Qt::UserRole + 1,
|
||||
CipherRole
|
||||
MtuRole
|
||||
};
|
||||
|
||||
explicit WireGuardConfigModel(QObject *parent = nullptr);
|
||||
|
||||
@@ -58,10 +58,8 @@ ListView {
|
||||
break
|
||||
}
|
||||
case ContainerEnum.WireGuard: {
|
||||
ProtocolsModel.updateModel(config)
|
||||
PageController.goToPage(PageEnum.PageProtocolRaw)
|
||||
// WireGuardConfigModel.updateModel(config)
|
||||
// goToPage(PageEnum.PageProtocolWireGuardSettings)
|
||||
WireGuardConfigModel.updateModel(config)
|
||||
PageController.goToPage(PageEnum.PageProtocolWireGuardSettings)
|
||||
break
|
||||
}
|
||||
case ContainerEnum.Awg: {
|
||||
@@ -72,8 +70,6 @@ ListView {
|
||||
case ContainerEnum.Ipsec: {
|
||||
ProtocolsModel.updateModel(config)
|
||||
PageController.goToPage(PageEnum.PageProtocolRaw)
|
||||
// Ikev2ConfigModel.updateModel(config)
|
||||
// goToPage(PageEnum.PageProtocolIKev2Settings)
|
||||
break
|
||||
}
|
||||
case ContainerEnum.Sftp: {
|
||||
|
||||
@@ -95,6 +95,26 @@ PageType {
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: mtuTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("MTU")
|
||||
textFieldText: mtu
|
||||
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText === "") {
|
||||
textFieldText = "0"
|
||||
}
|
||||
if (textFieldText !== mtu) {
|
||||
mtu = textFieldText
|
||||
}
|
||||
}
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: junkPacketCountTextField
|
||||
Layout.fillWidth: true
|
||||
|
||||
172
client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml
Normal file
172
client/ui/qml/Pages2/PageProtocolWireGuardSettings.qml
Normal file
@@ -0,0 +1,172 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
ColumnLayout {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.topMargin: 20
|
||||
|
||||
BackButtonType {
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
contentHeight: content.implicitHeight
|
||||
|
||||
Column {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
||||
|
||||
ListView {
|
||||
id: listview
|
||||
|
||||
width: parent.width
|
||||
height: listview.contentItem.height
|
||||
|
||||
clip: true
|
||||
interactive: false
|
||||
|
||||
model: WireGuardConfigModel
|
||||
|
||||
delegate: Item {
|
||||
implicitWidth: listview.width
|
||||
implicitHeight: col.implicitHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: col
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 0
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
headerText: qsTr("WG settings")
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: portTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 40
|
||||
|
||||
headerText: qsTr("Port")
|
||||
textFieldText: port
|
||||
textField.maximumLength: 5
|
||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText !== port) {
|
||||
port = textFieldText
|
||||
}
|
||||
}
|
||||
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: mtuTextField
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
headerText: qsTr("MTU")
|
||||
textFieldText: mtu
|
||||
textField.validator: IntValidator { bottom: 576; top: 65535 }
|
||||
|
||||
textField.onEditingFinished: {
|
||||
if (textFieldText === "") {
|
||||
textFieldText = "0"
|
||||
}
|
||||
if (textFieldText !== mtu) {
|
||||
mtu = textFieldText
|
||||
}
|
||||
}
|
||||
checkEmptyText: true
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.topMargin: 24
|
||||
Layout.leftMargin: -8
|
||||
implicitHeight: 32
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
textColor: "#EB5757"
|
||||
|
||||
text: qsTr("Remove WG")
|
||||
|
||||
onClicked: {
|
||||
questionDrawer.headerText = qsTr("Remove WG from server?")
|
||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||
questionDrawer.yesButtonText = qsTr("Continue")
|
||||
questionDrawer.noButtonText = qsTr("Cancel")
|
||||
|
||||
questionDrawer.yesButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||
InstallController.removeCurrentlyProcessedContainer()
|
||||
}
|
||||
questionDrawer.noButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
}
|
||||
questionDrawer.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 24
|
||||
|
||||
enabled: mtuTextField.errorText === "" &&
|
||||
portTextField.errorText === ""
|
||||
|
||||
text: qsTr("Save and Restart Amnezia")
|
||||
|
||||
onClicked: {
|
||||
forceActiveFocus()
|
||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||
InstallController.updateContainer(WireGuardConfigModel.getConfig())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QuestionDrawer {
|
||||
id: questionDrawer
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user