Compare commits

...

11 Commits

Author SHA1 Message Date
Mykola Baibuz 2ba6703ca4 Revert iOS OpenVPN version 2024-09-21 22:19:58 +03:00
pokamest c681611102 Bump version to 4.8.1.0 2024-09-20 13:08:28 +01:00
pokamest 4fc2a23f49 Merge pull request #1076 from amnezia-vpn/fix/android-protocol-libs
Exclude protocol libraries from loading at application startup
2024-09-20 05:06:41 -07:00
pokamest 23f4a6ec8e Merge pull request #1077 from amnezia-vpn/bugfix/linux-page-home-drawer-size
bugfix: fixed drawer size to pageHome on first startup
2024-09-20 04:38:24 -07:00
vladimir.kuznetsov 504862c2b8 bugfix: fixed drawer size to pageHome on first startup 2024-09-20 15:36:20 +04:00
Mykola Baibuz a22a9448ca Some XRay improvements (#1075) 2024-09-20 12:12:22 +01:00
pokamest 862e83ddf5 Merge pull request #1073 from amnezia-vpn/bugfix/awg-wg-persistent-keep-alive-variable-type
returned awg/wg persistentKeepAlive variable type to string
2024-09-20 03:08:27 -07:00
albexk 8735eee662 Exclude protocol libraries from loading at application startup 2024-09-19 23:41:37 +03:00
pokamest ff82cf5dc4 Merge pull request #1074 from amnezia-vpn/fix/gh-ios-build
Fix iOS build on GHA
2024-09-19 09:24:32 -07:00
Iurii Egorov 8648790583 Fix iOS build on GHA 2024-09-19 18:47:20 +03:00
vladimir.kuznetsov b881d92a80 bugfix: returned awg/wg persistentKeepAlive variable type to string 2024-09-19 16:04:36 +04:00
31 changed files with 352 additions and 188 deletions
+1 -1
View File
@@ -181,7 +181,7 @@ jobs:
- name: 'Install go'
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.22.1'
cache: false
- name: 'Setup gomobile'
+2 -2
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.8.0.5
project(${PROJECT} VERSION 4.8.1.0
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 61)
set(APP_ANDROID_VERSION_CODE 62)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")
+1
View File
@@ -61,6 +61,7 @@ qt_add_executable(${PROJECT} MANUAL_FINALIZATION)
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep)
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep)
qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_tun2socks.rep)
endif()
qt6_add_resources(QRC ${QRC} ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
@@ -3,10 +3,16 @@ package org.amnezia.vpn.protocol.cloak
import android.util.Base64
import net.openvpn.ovpn3.ClientAPI_Config
import org.amnezia.vpn.protocol.openvpn.OpenVpn
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.json.JSONObject
class Cloak : OpenVpn() {
override fun internalInit() {
super.internalInit()
if (!isInitialized) loadSharedLibrary(context, "ck-ovpn-plugin")
}
override fun parseConfig(config: JSONObject): ClientAPI_Config {
val openVpnConfig = ClientAPI_Config()
@@ -11,6 +11,7 @@ import org.amnezia.vpn.protocol.Protocol
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.getLocalNetworks
import org.amnezia.vpn.util.net.parseInetAddress
@@ -34,7 +35,10 @@ open class OpenVpn : Protocol() {
}
override fun internalInit() {
if (!isInitialized) loadSharedLibrary(context, "ovpn3")
if (!isInitialized) {
loadSharedLibrary(context, "ovpn3")
loadSharedLibrary(context, "ovpnutil")
}
if (this::scope.isInitialized) {
scope.cancel()
}
@@ -2,7 +2,6 @@ package org.amnezia.vpn.protocol
sealed class ProtocolException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
class LoadLibraryException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
class BadConfigException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
class VpnStartException(message: String? = null, cause: Throwable? = null) : ProtocolException(message, cause)
@@ -158,60 +158,6 @@ abstract class Protocol {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
vpnBuilder.setMetered(false)
}
companion object {
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
Log.d(TAG, "Extracting library: $libraryName")
val apks = hashSetOf<String>()
context.applicationInfo.run {
sourceDir?.let { apks += it }
splitSourceDirs?.let { apks += it }
}
for (abi in Build.SUPPORTED_ABIS) {
for (apk in apks) {
ZipFile(File(apk), ZipFile.OPEN_READ).use { zipFile ->
val mappedName = System.mapLibraryName(libraryName)
val libraryZipPath = listOf("lib", abi, mappedName).joinToString(File.separator)
val zipEntry = zipFile.getEntry(libraryZipPath)
zipEntry?.let {
Log.d(TAG, "Extracting apk:/$libraryZipPath to ${destination.absolutePath}")
FileOutputStream(destination).use { outStream ->
zipFile.getInputStream(zipEntry).use { inStream ->
inStream.copyTo(outStream, 32 * 1024)
outStream.fd.sync()
}
}
}
return true
}
}
}
return false
}
@SuppressLint("UnsafeDynamicallyLoadedCode")
fun loadSharedLibrary(context: Context, libraryName: String) {
Log.d(TAG, "Loading library: $libraryName")
try {
System.loadLibrary(libraryName)
return
} catch (_: UnsatisfiedLinkError) {
Log.d(TAG, "Failed to load library, try to extract it from apk")
}
var tempFile: File? = null
try {
tempFile = File.createTempFile("lib", ".so", context.codeCacheDir)
if (extractLibrary(context, libraryName, tempFile)) {
System.load(tempFile.absolutePath)
return
}
} catch (e: Exception) {
throw LoadLibraryException("Failed to load library apk: $libraryName", e)
} finally {
tempFile?.delete()
}
}
}
}
private fun VpnService.Builder.addAddress(addr: InetNetwork) = addAddress(addr.address, addr.mask)
-1
View File
@@ -3,7 +3,6 @@
<!-- DO NOT EDIT THIS: This file is populated automatically by the deployment tool. -->
<array name="bundled_libs">
<!-- %%INSERT_EXTRA_LIBS%% -->
</array>
<array name="qt_libs">
@@ -43,6 +43,7 @@ import kotlinx.coroutines.withContext
import org.amnezia.vpn.protocol.getStatistics
import org.amnezia.vpn.protocol.getStatus
import org.amnezia.vpn.qt.QtAndroidController
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.Prefs
import org.json.JSONException
@@ -158,6 +159,7 @@ class AmneziaActivity : QtActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "Create Amnezia activity: $intent")
loadLibs()
window.apply {
addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
statusBarColor = getColor(R.color.black)
@@ -179,6 +181,17 @@ class AmneziaActivity : QtActivity() {
runBlocking { vpnProto = proto.await() }
}
private fun loadLibs() {
listOf(
"rsapss",
"crypto_3",
"ssl_3",
"ssh"
).forEach {
loadSharedLibrary(this.applicationContext, it)
}
}
private fun registerBroadcastReceivers() {
notificationStateReceiver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
registerBroadcastReceiver(
@@ -40,7 +40,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import org.amnezia.vpn.protocol.BadConfigException
import org.amnezia.vpn.protocol.LoadLibraryException
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.CONNECTING
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
@@ -50,6 +49,7 @@ import org.amnezia.vpn.protocol.ProtocolState.UNKNOWN
import org.amnezia.vpn.protocol.VpnException
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.protocol.putStatus
import org.amnezia.vpn.util.LoadLibraryException
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.Prefs
import org.amnezia.vpn.util.net.NetworkState
@@ -0,0 +1,66 @@
package org.amnezia.vpn.util
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import java.io.File
import java.io.FileOutputStream
import java.util.zip.ZipFile
private const val TAG = "LibraryLoader"
object LibraryLoader {
private fun extractLibrary(context: Context, libraryName: String, destination: File): Boolean {
Log.d(TAG, "Extracting library: $libraryName")
val apks = hashSetOf<String>()
context.applicationInfo.run {
sourceDir?.let { apks += it }
splitSourceDirs?.let { apks += it }
}
for (abi in Build.SUPPORTED_ABIS) {
for (apk in apks) {
ZipFile(File(apk), ZipFile.OPEN_READ).use { zipFile ->
val mappedName = System.mapLibraryName(libraryName)
val libraryZipPath = listOf("lib", abi, mappedName).joinToString(File.separator)
val zipEntry = zipFile.getEntry(libraryZipPath)
zipEntry?.let {
Log.d(TAG, "Extracting apk:/$libraryZipPath to ${destination.absolutePath}")
FileOutputStream(destination).use { outStream ->
zipFile.getInputStream(zipEntry).use { inStream ->
inStream.copyTo(outStream, 32 * 1024)
outStream.fd.sync()
}
}
}
return true
}
}
}
return false
}
@SuppressLint("UnsafeDynamicallyLoadedCode")
fun loadSharedLibrary(context: Context, libraryName: String) {
Log.d(TAG, "Loading library: $libraryName")
try {
System.loadLibrary(libraryName)
return
} catch (_: UnsatisfiedLinkError) {
Log.d(TAG, "Failed to load library, try to extract it from apk")
}
var tempFile: File? = null
try {
tempFile = File.createTempFile("lib", ".so", context.codeCacheDir)
if (extractLibrary(context, libraryName, tempFile)) {
System.load(tempFile.absolutePath)
return
}
} catch (e: Exception) {
throw LoadLibraryException("Failed to load library apk: $libraryName", e)
} finally {
tempFile?.delete()
}
}
}
class LoadLibraryException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
@@ -3,7 +3,6 @@ package org.amnezia.vpn.protocol.wireguard
import android.net.VpnService.Builder
import java.io.IOException
import java.util.Locale
import java.util.TreeMap
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
@@ -13,6 +12,7 @@ import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.asSequence
import org.amnezia.vpn.util.net.InetEndpoint
@@ -199,7 +199,7 @@ QString WireguardConfigurator::createConfig(const ServerCredentials &credentials
jConfig[config_key::server_pub_key] = connData.serverPubKey;
jConfig[config_key::mtu] = wireguarConfig.value(config_key::mtu).toString(protocols::wireguard::defaultMtu);
jConfig[config_key::persistent_keep_alive] = 25;
jConfig[config_key::persistent_keep_alive] = "25";
QJsonArray allowedIps { "0.0.0.0/0", "::/0" };
jConfig[config_key::allowed_ips] = allowedIps;
+14 -2
View File
@@ -29,6 +29,12 @@ QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
return Instance()->m_ipcClient;
}
QSharedPointer<IpcProcessTun2SocksReplica> IpcClient::InterfaceTun2Socks()
{
if (!Instance()) return nullptr;
return Instance()->m_Tun2SocksClient;
}
bool IpcClient::init(IpcClient *instance)
{
m_instance = instance;
@@ -44,6 +50,12 @@ bool IpcClient::init(IpcClient *instance)
qWarning() << "IpcClient replica is not connected!";
}
Instance()->m_Tun2SocksClient.reset(Instance()->m_ClientNode.acquire<IpcProcessTun2SocksReplica>());
Instance()->m_Tun2SocksClient->waitForSource(1000);
if (!Instance()->m_Tun2SocksClient->isReplicaValid()) {
qWarning() << "IpcClient::m_Tun2SocksClient replica is not connected!";
}
});
connect(Instance()->m_localSocket, &QLocalSocket::disconnected, [instance](){
@@ -51,16 +63,16 @@ bool IpcClient::init(IpcClient *instance)
});
Instance()->m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
Instance()->m_localSocket->waitForConnected();
if (!Instance()->m_ipcClient) {
qDebug() << "IpcClient::init failed";
return false;
}
qDebug() << "IpcClient::init succeed";
return Instance()->m_ipcClient->isReplicaValid();
return (Instance()->m_ipcClient->isReplicaValid() && Instance()->m_Tun2SocksClient->isReplicaValid());
}
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
+5
View File
@@ -6,6 +6,7 @@
#include "ipc.h"
#include "rep_ipc_interface_replica.h"
#include "rep_ipc_process_tun2socks_replica.h"
#include "privileged_process.h"
@@ -18,6 +19,7 @@ public:
static IpcClient *Instance();
static bool init(IpcClient *instance);
static QSharedPointer<IpcInterfaceReplica> Interface();
static QSharedPointer<IpcProcessTun2SocksReplica> InterfaceTun2Socks();
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
bool isSocketConnected() const;
@@ -28,8 +30,11 @@ private:
~IpcClient() override;
QRemoteObjectNode m_ClientNode;
QRemoteObjectNode m_Tun2SocksNode;
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
QPointer<QLocalSocket> m_localSocket;
QPointer<QLocalSocket> m_tun2socksSocket;
QSharedPointer<IpcProcessTun2SocksReplica> m_Tun2SocksClient;
struct ProcessDescriptor {
ProcessDescriptor () {
+1 -1
View File
@@ -15,7 +15,7 @@ struct WGConfig: Decodable {
let serverPublicKey: String
let presharedKey: String?
var allowedIPs: [String]
var persistentKeepAlive: Int
var persistentKeepAlive: String
let splitTunnelType: Int
let splitTunnelSites: [String]
+5 -3
View File
@@ -6,6 +6,7 @@
#include <QTcpSocket>
#include <QNetworkInterface>
#include "core/networkUtilities.h"
#include "logger.h"
#include "openvpnprotocol.h"
#include "utilities.h"
@@ -127,7 +128,6 @@ void OpenVpnProtocol::sendManagementCommand(const QString &command)
uint OpenVpnProtocol::selectMgmtPort()
{
for (int i = 0; i < 100; ++i) {
quint32 port = QRandomGenerator::global()->generate();
port = (double)(65000 - 15001) * port / UINT32_MAX + 15001;
@@ -137,7 +137,6 @@ uint OpenVpnProtocol::selectMgmtPort()
if (ok)
return port;
}
return m_managementPort;
}
@@ -343,7 +342,8 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_configData.value(amnezia::config_key::hostName).toString());
m_configData.insert("vpnServer",
NetworkUtilities::getIPAddress(m_configData.value(amnezia::config_key::hostName).toString()));
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
}
@@ -352,6 +352,8 @@ void OpenVpnProtocol::updateVpnGateway(const QString &line)
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
m_configData.insert("vpnServer",
NetworkUtilities::getIPAddress(m_configData.value(amnezia::config_key::hostName).toString()));
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
+75 -110
View File
@@ -17,6 +17,7 @@ XrayProtocol::XrayProtocol(const QJsonObject &configuration, QObject *parent):
m_routeGateway = NetworkUtilities::getGatewayAndIface();
m_vpnGateway = amnezia::protocols::xray::defaultLocalAddr;
m_vpnLocalAddress = amnezia::protocols::xray::defaultLocalAddr;
m_t2sProcess = IpcClient::InterfaceTun2Socks();
}
XrayProtocol::~XrayProtocol()
@@ -65,7 +66,7 @@ ErrorCode XrayProtocol::start()
});
connect(&m_xrayProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "XrayProtocol finished, exitCode, exiStatus" << exitCode << exitStatus;
qDebug().noquote() << "XrayProtocol finished, exitCode, exitStatus" << exitCode << exitStatus;
setConnectionState(Vpn::ConnectionState::Disconnected);
if (exitStatus != QProcess::NormalExit) {
emit protocolError(amnezia::ErrorCode::XrayExecutableCrashed);
@@ -91,116 +92,80 @@ ErrorCode XrayProtocol::start()
ErrorCode XrayProtocol::startTun2Sock()
{
if (!QFileInfo::exists(Utils::tun2socksPath())) {
setLastError(ErrorCode::Tun2SockExecutableMissing);
return lastError();
}
m_t2sProcess = IpcClient::CreatePrivilegedProcess();
if (!m_t2sProcess) {
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
return ErrorCode::AmneziaServiceConnectionFailed;
}
m_t2sProcess->waitForSource(1000);
if (!m_t2sProcess->isInitialized()) {
qWarning() << "IpcProcess replica is not connected!";
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
return ErrorCode::AmneziaServiceConnectionFailed;
}
QString XrayConStr = "socks5://127.0.0.1:" + QString::number(m_localPort);
m_t2sProcess->setProgram(PermittedProcess::Tun2Socks);
#ifdef Q_OS_WIN
m_configData.insert("inetAdapterIndex", NetworkUtilities::AdapterIndexTo(QHostAddress(m_remoteAddress)));
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr, "-tun-post-up",
QString("cmd /c netsh interface ip set address name=\"tun2\" static %1 255.255.255.255").arg(amnezia::protocols::xray::defaultLocalAddr)});
#endif
#ifdef Q_OS_LINUX
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr});
#endif
#ifdef Q_OS_MAC
QStringList arguments({"-device", "utun22", "-proxy", XrayConStr});
#endif
m_t2sProcess->setArguments(arguments);
qDebug() << arguments.join(" ");
connect(m_t2sProcess.data(), &PrivilegedProcess::errorOccurred,
[&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; });
connect(m_t2sProcess.data(), &PrivilegedProcess::stateChanged,
[&](QProcess::ProcessState newState) {
qDebug() << "PrivilegedProcess stateChanged" << newState;
if (newState == QProcess::Running)
{
setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
#ifdef Q_OS_MACOS
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
#endif
#ifdef Q_OS_WINDOWS
QThread::msleep(7000);
#endif
#ifdef Q_OS_LINUX
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
if (m_routeMode == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_remoteAddress);
}
IpcClient::Interface()->StopRoutingIpv6();
#ifdef Q_OS_WIN
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j=0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
}
}
#endif
setConnectionState(Vpn::ConnectionState::Connected);
}
});
#if !defined(Q_OS_MACOS)
connect(m_t2sProcess.data(), &PrivilegedProcess::finished, this,
[&]() {
setConnectionState(Vpn::ConnectionState::Disconnected);
IpcClient::Interface()->deleteTun("tun2");
IpcClient::Interface()->StartRoutingIpv6();
IpcClient::Interface()->clearSavedRoutes();
});
#endif
m_t2sProcess->start();
#ifdef Q_OS_WIN
m_configData.insert("inetAdapterIndex", NetworkUtilities::AdapterIndexTo(QHostAddress(m_remoteAddress)));
#endif
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::stateChanged, this,
[&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; });
connect(m_t2sProcess.data(), &IpcProcessTun2SocksReplica::setConnectionState, this,
[&](int vpnState) {
qDebug() << "PrivilegedProcess setConnectionState " << vpnState;
if (vpnState == Vpn::ConnectionState::Connected)
{
setConnectionState(Vpn::ConnectionState::Connecting);
QList<QHostAddress> dnsAddr;
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns1).toString()));
dnsAddr.push_back(QHostAddress(m_configData.value(config_key::dns2).toString()));
#ifdef Q_OS_WIN
QThread::msleep(8000);
#endif
#ifdef Q_OS_MACOS
QThread::msleep(5000);
IpcClient::Interface()->createTun("utun22", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("utun22", dnsAddr);
#endif
#ifdef Q_OS_LINUX
QThread::msleep(1000);
IpcClient::Interface()->createTun("tun2", amnezia::protocols::xray::defaultLocalAddr);
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
// killSwitch toggle
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enableKillSwitch(m_configData, 0);
}
#endif
if (m_routeMode == 0) {
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "0.0.0.0/1");
IpcClient::Interface()->routeAddList(m_vpnGateway, QStringList() << "128.0.0.0/1");
IpcClient::Interface()->routeAddList(m_routeGateway, QStringList() << m_remoteAddress);
}
IpcClient::Interface()->StopRoutingIpv6();
#ifdef Q_OS_WIN
IpcClient::Interface()->updateResolvers("tun2", dnsAddr);
QList<QNetworkInterface> netInterfaces = QNetworkInterface::allInterfaces();
for (int i = 0; i < netInterfaces.size(); i++) {
for (int j = 0; j < netInterfaces.at(i).addressEntries().size(); j++)
{
// killSwitch toggle
if (m_vpnLocalAddress == netInterfaces.at(i).addressEntries().at(j).ip().toString()) {
if (QVariant(m_configData.value(config_key::killSwitchOption).toString()).toBool()) {
IpcClient::Interface()->enableKillSwitch(QJsonObject(), netInterfaces.at(i).index());
}
m_configData.insert("vpnAdapterIndex", netInterfaces.at(i).index());
m_configData.insert("vpnGateway", m_vpnGateway);
m_configData.insert("vpnServer", m_remoteAddress);
IpcClient::Interface()->enablePeerTraffic(m_configData);
}
}
}
#endif
setConnectionState(Vpn::ConnectionState::Connected);
}
#if !defined(Q_OS_MACOS)
if (vpnState == Vpn::ConnectionState::Disconnected) {
setConnectionState(Vpn::ConnectionState::Disconnected);
IpcClient::Interface()->deleteTun("tun2");
IpcClient::Interface()->StartRoutingIpv6();
IpcClient::Interface()->clearSavedRoutes();
}
#endif
});
return ErrorCode::NoError;
}
@@ -214,7 +179,7 @@ void XrayProtocol::stop()
qDebug() << "XrayProtocol::stop()";
m_xrayProcess.terminate();
if (m_t2sProcess) {
m_t2sProcess->close();
m_t2sProcess->stop();
}
#ifdef Q_OS_WIN
+2 -1
View File
@@ -34,9 +34,10 @@ private:
QString m_secondaryDNS;
#ifndef Q_OS_IOS
QProcess m_xrayProcess;
QSharedPointer<PrivilegedProcess> m_t2sProcess;
QSharedPointer<IpcProcessTun2SocksReplica> m_t2sProcess;
#endif
QTemporaryFile m_xrayCfgFile;
};
#endif // XRAYPROTOCOL_H
+2 -1
View File
@@ -80,7 +80,8 @@ Window {
}
PageStart {
anchors.fill: parent
width: root.width
height: root.height
}
Item {
-1
View File
@@ -7,7 +7,6 @@
class IpcInterface
{
SLOT( int createPrivilegedProcess() ); // return local pid
//SIGNAL(sendMessage(const QByteArray &message));
// Route functions
SLOT( int routeAddList(const QString &gw, const QStringList &ips) );
-1
View File
@@ -3,7 +3,6 @@
class IpcProcessInterface
{
//SLOT( start(const QString &program, const QStringList &args) );
SLOT( start() );
SLOT( close() );
+11
View File
@@ -0,0 +1,11 @@
#include <QtCore>
#include <QString>
class IpcProcessTun2Socks
{
SLOT( start() );
SLOT( stop() );
SIGNAL( setConnectionState(int state) );
SIGNAL( stateChanged(QProcess::ProcessState newState) );
};
+4 -4
View File
@@ -8,6 +8,7 @@
#include "logger.h"
#include "router.h"
#include "../core/networkUtilities.h"
#include "../client/protocols/protocols_defs.h"
#ifdef Q_OS_WIN
#include "../client/platforms/windows/daemon/windowsdaemon.h"
@@ -209,7 +210,7 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
if (splitTunnelType == 0) {
blockAll = true;
allowNets = true;
allownets.append(configStr.value(amnezia::config_key::hostName).toString());
allownets.append(configStr.value("vpnServer").toString());
} else if (splitTunnelType == 1) {
blockNets = true;
for (auto v : splitTunnelSites) {
@@ -218,7 +219,7 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
} else if (splitTunnelType == 2) {
blockAll = true;
allowNets = true;
allownets.append(configStr.value(amnezia::config_key::hostName).toString());
allownets.append(configStr.value("vpnServer").toString());
for (auto v : splitTunnelSites) {
allownets.append(v.toString());
}
@@ -329,7 +330,7 @@ bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
}
}
config.m_excludedAddresses.append(configStr.value(amnezia::config_key::hostName).toString());
config.m_excludedAddresses.append(configStr.value("vpnServer").toString());
if (splitTunnelType == 2) {
for (auto v : splitTunnelSites) {
QString ipRange = v.toString();
@@ -351,7 +352,6 @@ bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
WindowsDaemon::instance()->prepareActivation(config, inetAdapterIndex);
WindowsDaemon::instance()->activateSplitTunnel(config, vpnAdapterIndex);
return true;
#endif
return true;
}
+4
View File
@@ -9,8 +9,10 @@
#include "ipc.h"
#include "ipcserverprocess.h"
#include "ipctun2socksprocess.h"
#include "rep_ipc_interface_source.h"
#include "rep_ipc_process_tun2socks_source.h"
class IpcServer : public IpcInterfaceSource
{
@@ -44,10 +46,12 @@ private:
ProcessDescriptor (QObject *parent = nullptr) {
serverNode = QSharedPointer<QRemoteObjectHost>(new QRemoteObjectHost(parent));
ipcProcess = QSharedPointer<IpcServerProcess>(new IpcServerProcess(parent));
tun2socksProcess = QSharedPointer<IpcProcessTun2Socks>(new IpcProcessTun2Socks(parent));
localServer = QSharedPointer<QLocalServer>(new QLocalServer(parent));
}
QSharedPointer<IpcServerProcess> ipcProcess;
QSharedPointer<IpcProcessTun2Socks> tun2socksProcess;
QSharedPointer<QRemoteObjectHost> serverNode;
QSharedPointer<QLocalServer> localServer;
};
+74
View File
@@ -0,0 +1,74 @@
#include "ipctun2socksprocess.h"
#include "ipc.h"
#include <QProcess>
#include <QString>
#include "../protocols/protocols_defs.h"
#ifndef Q_OS_IOS
IpcProcessTun2Socks::IpcProcessTun2Socks(QObject *parent) :
IpcProcessTun2SocksSource(parent),
m_t2sProcess(QSharedPointer<QProcess>(new QProcess()))
{
connect(m_t2sProcess.data(), &QProcess::stateChanged, this, &IpcProcessTun2Socks::stateChanged);
qDebug() << "IpcProcessTun2Socks::IpcProcessTun2Socks()";
}
IpcProcessTun2Socks::~IpcProcessTun2Socks()
{
qDebug() << "IpcProcessTun2Socks::~IpcProcessTun2Socks()";
}
void IpcProcessTun2Socks::start()
{
qDebug() << "IpcProcessTun2Socks::start()";
m_t2sProcess->setProgram(amnezia::permittedProcessPath(static_cast<amnezia::PermittedProcess>(amnezia::PermittedProcess::Tun2Socks)));
QString XrayConStr = "socks5://127.0.0.1:10808";
#ifdef Q_OS_WIN
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr, "-tun-post-up",
QString("cmd /c netsh interface ip set address name=\"tun2\" static %1 255.255.255.255")
.arg(amnezia::protocols::xray::defaultLocalAddr)});
#endif
#ifdef Q_OS_LINUX
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr});
#endif
#ifdef Q_OS_MAC
QStringList arguments({"-device", "utun22", "-proxy", XrayConStr});
#endif
m_t2sProcess->setArguments(arguments);
Utils::killProcessByName(m_t2sProcess->program());
m_t2sProcess->start();
connect(m_t2sProcess.data(), &QProcess::readyReadStandardOutput, this, [this]() {
QString line = m_t2sProcess.data()->readAllStandardOutput();
if (line.contains("[STACK] tun://") && line.contains("<-> socks5://127.0.0.1")) {
emit setConnectionState(Vpn::ConnectionState::Connected);
}
});
connect(m_t2sProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "tun2socks finished, exitCode, exiStatus" << exitCode << exitStatus;
emit setConnectionState(Vpn::ConnectionState::Disconnected);
if (exitStatus != QProcess::NormalExit){
stop();
}
if (exitCode !=0 ){
stop();
}
});
m_t2sProcess->start();
m_t2sProcess->waitForStarted();
}
void IpcProcessTun2Socks::stop()
{
qDebug() << "IpcProcessTun2Socks::stop()";
m_t2sProcess->close();
}
#endif
+52
View File
@@ -0,0 +1,52 @@
#ifndef IPCTUN2SOCKSPROCESS_H
#define IPCTUN2SOCKSPROCESS_H
#include <QObject>
#ifndef Q_OS_IOS
#include "rep_ipc_process_tun2socks_source.h"
namespace Vpn
{
Q_NAMESPACE
enum ConnectionState {
Unknown,
Disconnected,
Preparing,
Connecting,
Connected,
Disconnecting,
Reconnecting,
Error
};
Q_ENUM_NS(ConnectionState)
}
class IpcProcessTun2Socks : public IpcProcessTun2SocksSource
{
Q_OBJECT
public:
explicit IpcProcessTun2Socks(QObject *parent = nullptr);
virtual ~IpcProcessTun2Socks();
void start() override;
void stop() override;
signals:
private:
QSharedPointer<QProcess> m_t2sProcess;
};
#else
class IpcProcessTun2Socks : public QObject
{
Q_OBJECT
public:
explicit IpcProcessTun2Socks(QObject *parent = nullptr);
};
#endif
#endif // IPCTUN2SOCKSPROCESS_H
+3
View File
@@ -18,6 +18,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc.h
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserver.h
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserverprocess.h
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipctun2socksprocess.h
${CMAKE_CURRENT_LIST_DIR}/localserver.h
${CMAKE_CURRENT_LIST_DIR}/../../common/logger/logger.h
${CMAKE_CURRENT_LIST_DIR}/router.h
@@ -30,6 +31,7 @@ set(SOURCES
${CMAKE_CURRENT_LIST_DIR}/../../client/core/networkUtilities.cpp
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserver.cpp
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipcserverprocess.cpp
${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipctun2socksprocess.cpp
${CMAKE_CURRENT_LIST_DIR}/localserver.cpp
${CMAKE_CURRENT_LIST_DIR}/../../common/logger/logger.cpp
${CMAKE_CURRENT_LIST_DIR}/main.cpp
@@ -279,6 +281,7 @@ endif()
qt_add_repc_sources(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc_interface.rep)
qt_add_repc_sources(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc_process_interface.rep)
qt_add_repc_sources(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../../ipc/ipc_process_tun2socks.rep)
# copy deploy artifacts required to run the application to the debug build folder
if(WIN32)
+1
View File
@@ -37,6 +37,7 @@ LocalServer::LocalServer(QObject *parent) : QObject(parent),
if (!m_isRemotingEnabled) {
m_isRemotingEnabled = true;
m_serverNode.enableRemoting(&m_ipcServer);
m_serverNode.enableRemoting(&m_tun2socks);
}
});
+1
View File
@@ -38,6 +38,7 @@ public:
~LocalServer();
QSharedPointer<QLocalServer> m_server;
IpcServer m_ipcServer;
IpcProcessTun2Socks m_tun2socks;
QRemoteObjectHost m_serverNode;
bool m_isRemotingEnabled = false;
#ifdef Q_OS_LINUX