Compare commits
26 commits
dev
...
feature/li
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f47e4cb729 | ||
|
|
b5cbcc5f2a | ||
|
|
f18d980bdb | ||
|
|
81cfab3566 | ||
|
|
7f123dabac | ||
|
|
de0b400934 | ||
|
|
dcde24649f | ||
|
|
b717560047 | ||
|
|
afd2542a11 | ||
|
|
1438a21902 | ||
|
|
4147632a62 | ||
|
|
948ab4cf71 | ||
|
|
f54308e4f4 | ||
|
|
052261c2b4 | ||
|
|
3cec0dc2a7 | ||
|
|
ad61ef0b22 | ||
|
|
63c569c3d2 | ||
|
|
30df4c6800 | ||
|
|
a96f9dc18a | ||
|
|
fb63cdf7e9 | ||
|
|
2d3b9c2752 | ||
|
|
09c58cb39e | ||
|
|
654d219e7e | ||
|
|
89d4c18e87 | ||
|
|
b0b185027e | ||
|
|
90912f9231 |
17 changed files with 516 additions and 12 deletions
|
|
@ -319,6 +319,15 @@ endif()
|
|||
if(LINUX AND NOT ANDROID)
|
||||
set(LIBS ${LIBS} -static-libstdc++ -static-libgcc -ldl)
|
||||
link_directories(${CMAKE_CURRENT_LIST_DIR}/platforms/linux)
|
||||
|
||||
set(HEADERS ${HEADERS}
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_linux.h
|
||||
)
|
||||
|
||||
set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_linux.cpp
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
||||
|
|
|
|||
|
|
@ -64,6 +64,26 @@ QString Ikev2Configurator::createConfig(const ServerCredentials &credentials, Do
|
|||
return "";
|
||||
}
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::ipsec_template, container),
|
||||
m_serverController->genVarsForScript(credentials, container, containerConfig));
|
||||
|
||||
config.replace("$CLIENT_NAME", connData.clientId);
|
||||
config.replace("$UUID1", QUuid::createUuid().toString());
|
||||
config.replace("$SERVER_ADDR", connData.host);
|
||||
|
||||
QJsonObject jConfig;
|
||||
jConfig[config_key::config] = config;
|
||||
|
||||
jConfig[config_key::hostName] = connData.host;
|
||||
jConfig[config_key::userName] = connData.clientId;
|
||||
jConfig[config_key::cert] = QString(connData.clientCert.toBase64());
|
||||
jConfig[config_key::cacert] = QString(connData.caCert);
|
||||
jConfig[config_key::password] = connData.password;
|
||||
|
||||
return QJsonDocument(jConfig).toJson();
|
||||
#endif
|
||||
|
||||
return genIkev2Config(connData);
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +93,7 @@ QString Ikev2Configurator::genIkev2Config(const ConnectionData &connData)
|
|||
config[config_key::hostName] = connData.host;
|
||||
config[config_key::userName] = connData.clientId;
|
||||
config[config_key::cert] = QString(connData.clientCert.toBase64());
|
||||
config[config_key::cacert] = QString(connData.caCert);
|
||||
config[config_key::password] = connData.password;
|
||||
|
||||
return QJsonDocument(config).toJson();
|
||||
|
|
@ -115,3 +136,22 @@ QString Ikev2Configurator::genStrongSwanConfig(const ConnectionData &connData)
|
|||
|
||||
return config;
|
||||
}
|
||||
|
||||
QString Ikev2Configurator::processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
|
||||
QJsonObject json;
|
||||
json[config_key::config] = protocolConfigString;
|
||||
return QJsonDocument(json).toJson();
|
||||
}
|
||||
|
||||
QString Ikev2Configurator::processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig,
|
||||
QString &protocolConfigString)
|
||||
{
|
||||
processConfigWithDnsSettings(dns, protocolConfigString);
|
||||
QJsonObject json;
|
||||
json[config_key::config] = protocolConfigString;
|
||||
return QJsonDocument(json).toJson();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ public:
|
|||
QString genIkev2Config(const ConnectionData &connData);
|
||||
QString genMobileConfig(const ConnectionData &connData);
|
||||
QString genStrongSwanConfig(const ConnectionData &connData);
|
||||
QString genIPSecConfig(const ConnectionData &connData);
|
||||
|
||||
QString processConfigWithLocalSettings(const QPair<QString, QString> &dns, const bool isApiConfig, QString &protocolConfigString);
|
||||
QString processConfigWithExportSettings(const QPair<QString, QString> &dns, const bool isApiConfig, QString &protocolConfigString);
|
||||
|
||||
ConnectionData prepareIkev2Config(const ServerCredentials &credentials,
|
||||
DockerContainer container, ErrorCode &errorCode);
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ Proto ContainerProps::defaultProtocol(DockerContainer c)
|
|||
|
||||
bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX)
|
||||
return true;
|
||||
|
||||
#elif defined(Q_OS_IOS)
|
||||
|
|
@ -304,13 +304,6 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
|
|||
case DockerContainer::SSXray: return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_LINUX)
|
||||
switch (c) {
|
||||
case DockerContainer::Ipsec: return false;
|
||||
default: return true;
|
||||
}
|
||||
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ QString amnezia::scriptName(ProtocolScriptType type)
|
|||
case ProtocolScriptType::wireguard_template: return QLatin1String("template.conf");
|
||||
case ProtocolScriptType::awg_template: return QLatin1String("template.conf");
|
||||
case ProtocolScriptType::xray_template: return QLatin1String("template.json");
|
||||
case ProtocolScriptType::ipsec_template: return QLatin1String("template.conf");
|
||||
default: return QString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ enum ProtocolScriptType {
|
|||
openvpn_template,
|
||||
wireguard_template,
|
||||
awg_template,
|
||||
xray_template
|
||||
xray_template,
|
||||
ipsec_template
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
158
client/protocols/ikev2_vpn_protocol_linux.cpp
Normal file
158
client/protocols/ikev2_vpn_protocol_linux.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "core/networkUtilities.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "logger.h"
|
||||
#include "ikev2_vpn_protocol_linux.h"
|
||||
#include "utilities.h"
|
||||
#include "core/ipcclient.h"
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
|
||||
static Ikev2Protocol* self = nullptr;
|
||||
|
||||
|
||||
Ikev2Protocol::Ikev2Protocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
self = this;
|
||||
readIkev2Configuration(configuration);
|
||||
m_routeGateway = NetworkUtilities::getGatewayAndIface();
|
||||
m_vpnGateway = "192.168.43.10";
|
||||
m_vpnLocalAddress = "192.168.43.10";
|
||||
m_remoteAddress = NetworkUtilities::getIPAddress(configuration.value(amnezia::config_key::hostName).toString());
|
||||
m_routeMode = static_cast<Settings::RouteMode>(configuration.value(amnezia::config_key::splitTunnelType).toInt());
|
||||
}
|
||||
|
||||
Ikev2Protocol::~Ikev2Protocol()
|
||||
{
|
||||
qDebug() << "IpsecProtocol::~IpsecProtocol()";
|
||||
Ikev2Protocol::stop();
|
||||
}
|
||||
|
||||
void Ikev2Protocol::stop()
|
||||
{
|
||||
setConnectionState(Vpn::ConnectionState::Disconnected);
|
||||
Ikev2Protocol::disconnect_vpn();
|
||||
qDebug() << "IpsecProtocol::stop()";
|
||||
}
|
||||
|
||||
void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration)
|
||||
{
|
||||
QJsonObject ikev2_data = configuration.value(ProtocolProps::key_proto_config_data(Proto::Ikev2)).toObject();
|
||||
m_config = QJsonDocument::fromJson(ikev2_data.value(config_key::config).toString().toUtf8()).object();
|
||||
}
|
||||
|
||||
ErrorCode Ikev2Protocol::start()
|
||||
{
|
||||
STACK_OF(X509) *certstack = sk_X509_new_null();
|
||||
BIO *p12 = BIO_new(BIO_s_mem());
|
||||
|
||||
EVP_PKEY *pkey;
|
||||
X509 *cert;
|
||||
|
||||
BIO_write(p12, QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8()),
|
||||
QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8()).size());
|
||||
|
||||
PKCS12 *pkcs12 = d2i_PKCS12_bio(p12, NULL);
|
||||
PKCS12_parse(pkcs12, m_config[config_key::password].toString().toStdString().c_str(), &pkey, &cert, &certstack);
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
PEM_write_bio_X509(bio, cert);
|
||||
|
||||
BUF_MEM *mem = NULL;
|
||||
BIO_get_mem_ptr(bio, &mem);
|
||||
|
||||
std::string pem(mem->data, mem->length);
|
||||
QString alias(pem.c_str());
|
||||
|
||||
IpcClient::Interface()->writeIPsecUserCert(alias, m_config[config_key::userName].toString());
|
||||
IpcClient::Interface()->writeIPsecConfig(m_config[config_key::config].toString());
|
||||
IpcClient::Interface()->writeIPsecCaCert(m_config[config_key::cacert].toString(), m_config[config_key::userName].toString());
|
||||
IpcClient::Interface()->writeIPsecPrivate(m_config[config_key::cert].toString(), m_config[config_key::userName].toString());
|
||||
IpcClient::Interface()->writeIPsecPrivatePass(m_config[config_key::password].toString(), m_config[config_key::hostName].toString(),
|
||||
m_config[config_key::userName].toString());
|
||||
|
||||
connect_to_vpn("ikev2-vpn");
|
||||
|
||||
if (!IpcClient::Interface()) {
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
QString connectionStatus;
|
||||
|
||||
auto futureResult = IpcClient::Interface()->getTunnelStatus("ikev2-vpn");
|
||||
futureResult.waitForFinished();
|
||||
|
||||
if (futureResult.returnValue().isEmpty()) {
|
||||
auto futureResult = IpcClient::Interface()->getTunnelStatus("ikev2-vpn");
|
||||
futureResult.waitForFinished();
|
||||
}
|
||||
|
||||
connectionStatus = futureResult.returnValue();
|
||||
|
||||
if (connectionStatus.contains("ESTABLISHED")) {
|
||||
QStringList lines = connectionStatus.split('\n');
|
||||
for (auto iter = lines.begin(); iter!=lines.end(); iter++)
|
||||
{
|
||||
if (iter->contains("0.0.0.0/0")) {
|
||||
m_vpnGateway = iter->split("===", Qt::SkipEmptyParts).first();
|
||||
m_vpnGateway = m_vpnGateway.split(" ").at(2);
|
||||
m_vpnGateway = m_vpnGateway.split("/").first();
|
||||
m_vpnLocalAddress = m_vpnGateway;
|
||||
qDebug() << "m_vpnGateway " << m_vpnGateway;
|
||||
|
||||
// killSwitch toggle
|
||||
if (QVariant(m_config.value(config_key::killSwitchOption).toString()).toBool()) {
|
||||
m_config.insert("vpnServer", m_remoteAddress);
|
||||
IpcClient::Interface()->enableKillSwitch(m_config, 0);
|
||||
}
|
||||
|
||||
if (m_routeMode == Settings::RouteMode::VpnAllSites) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
setConnectionState(Vpn::ConnectionState::Connected);
|
||||
} else {
|
||||
setConnectionState(Vpn::ConnectionState::Disconnected);
|
||||
}
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::create_new_vpn(const QString & vpn_name,
|
||||
const QString & serv_addr) {
|
||||
qDebug() << "Ikev2Protocol::create_new_vpn()";
|
||||
return true;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::delete_vpn_connection(const QString &vpn_name) {
|
||||
|
||||
return false;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::connect_to_vpn(const QString &vpn_name) {
|
||||
IpcClient::Interface()->startIPsec(vpn_name);
|
||||
QThread::msleep(3000);
|
||||
return true;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::disconnect_vpn() {
|
||||
IpcClient::Interface()->stopIPsec("ikev2-vpn");
|
||||
IpcClient::Interface()->disableKillSwitch();
|
||||
IpcClient::Interface()->StartRoutingIpv6();
|
||||
return true;
|
||||
}
|
||||
51
client/protocols/ikev2_vpn_protocol_linux.h
Normal file
51
client/protocols/ikev2_vpn_protocol_linux.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef IKEV2_VPN_PROTOCOL_LINUX_H
|
||||
#define IKEV2_VPN_PROTOCOL_LINUX_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include "vpnprotocol.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
class Ikev2Protocol : public VpnProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Ikev2Protocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~Ikev2Protocol() override;
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
static QString tunnelName() { return "AmneziaVPN IKEv2"; }
|
||||
|
||||
|
||||
private:
|
||||
void readIkev2Configuration(const QJsonObject &configuration);
|
||||
|
||||
private:
|
||||
QJsonObject m_config;
|
||||
QString m_remoteAddress;
|
||||
int m_routeMode;
|
||||
|
||||
|
||||
bool create_new_vpn(const QString & vpn_name,
|
||||
const QString & serv_addr);
|
||||
bool delete_vpn_connection(const QString &vpn_name);
|
||||
|
||||
bool connect_to_vpn(const QString & vpn_name);
|
||||
bool disconnect_vpn();
|
||||
};
|
||||
|
||||
|
||||
#endif // IKEV2_VPN_PROTOCOL_LINUX_H
|
||||
|
|
@ -172,7 +172,8 @@ void Ikev2Protocol::newConnectionStateEventReceived(UINT unMsg, tagRASCONNSTATE
|
|||
|
||||
void Ikev2Protocol::readIkev2Configuration(const QJsonObject &configuration)
|
||||
{
|
||||
m_config = configuration.value(ProtocolProps::key_proto_config_data(Proto::Ikev2)).toObject();
|
||||
QJsonObject ikev2_data = configuration.value(ProtocolProps::key_proto_config_data(Proto::Ikev2)).toObject();
|
||||
m_config = QJsonDocument::fromJson(ikev2_data.value(config_key::config).toString().toUtf8()).object();
|
||||
}
|
||||
|
||||
ErrorCode Ikev2Protocol::start()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace amnezia
|
|||
constexpr char description[] = "description";
|
||||
constexpr char name[] = "name";
|
||||
constexpr char cert[] = "cert";
|
||||
constexpr char cacert[] = "cacert";
|
||||
constexpr char config[] = "config";
|
||||
|
||||
constexpr char containers[] = "containers";
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
#include "ikev2_vpn_protocol_windows.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "ikev2_vpn_protocol_linux.h"
|
||||
#endif
|
||||
|
||||
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_connectionState(Vpn::ConnectionState::Unknown),
|
||||
|
|
@ -106,7 +110,7 @@ QString VpnProtocol::vpnGateway() const
|
|||
VpnProtocol *VpnProtocol::factory(DockerContainer container, const QJsonObject &configuration)
|
||||
{
|
||||
switch (container) {
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
#if defined(Q_OS_WINDOWS) || defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
case DockerContainer::Ipsec: return new Ikev2Protocol(configuration);
|
||||
#endif
|
||||
#if defined(Q_OS_WINDOWS) || defined(Q_OS_MACX) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@
|
|||
<file>server_scripts/ipsec/mobileconfig.plist</file>
|
||||
<file>server_scripts/ipsec/run_container.sh</file>
|
||||
<file>server_scripts/ipsec/start.sh</file>
|
||||
<file>server_scripts/ipsec/template.conf</file>
|
||||
<file>server_scripts/ipsec/strongswan.profile</file>
|
||||
<file>server_scripts/openvpn_cloak/configure_container.sh</file>
|
||||
<file>server_scripts/openvpn_cloak/Dockerfile</file>
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ conn ikev2-cp
|
|||
dpdtimeout=120
|
||||
dpdaction=clear
|
||||
auto=add
|
||||
authby=rsa-sha1
|
||||
ikev2=insist
|
||||
rekey=no
|
||||
pfs=yes
|
||||
|
|
|
|||
28
client/server_scripts/ipsec/template.conf
Normal file
28
client/server_scripts/ipsec/template.conf
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
config setup
|
||||
charondebug="ike 1, knl 1, cfg 0"
|
||||
uniqueids=no
|
||||
|
||||
conn ikev2-vpn
|
||||
auto=add
|
||||
type=tunnel
|
||||
keyexchange=ikev2
|
||||
fragmentation=yes
|
||||
forceencaps=yes
|
||||
dpdaction=clear
|
||||
dpddelay=300s
|
||||
rekey=no
|
||||
leftid=$CLIENT_NAME
|
||||
leftcert=$CLIENT_NAME.crt
|
||||
leftdns=$PRIMARY_DNS,$SECONDARY_DNS
|
||||
leftsendcert=always
|
||||
leftsourceip=%config
|
||||
right=$SERVER_IP_ADDRESS
|
||||
rightsubnet=0.0.0.0/0
|
||||
rightsendcert=never
|
||||
eap_identity=%identity
|
||||
encapsulation=yes
|
||||
pfs=yes
|
||||
ike=aes256-sha256-modp2048,aes256-sha1-modp1024,3des-sha1-modp1024
|
||||
esp=aes256-sha256,aes256-sha1,3des-sha1
|
||||
|
||||
|
||||
|
|
@ -32,5 +32,17 @@ class IpcInterface
|
|||
SLOT( bool enablePeerTraffic( const QJsonObject &configStr) );
|
||||
SLOT( bool enableKillSwitch( const QJsonObject &excludeAddr, int vpnAdapterIndex) );
|
||||
SLOT( bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) );
|
||||
|
||||
SLOT( bool writeIPsecCaCert(QString cacert, QString uuid) );
|
||||
SLOT( bool writeIPsecPrivate(QString privKey, QString uuid) );
|
||||
SLOT( bool writeIPsecConfig(QString config) );
|
||||
SLOT( bool writeIPsecUserCert(QString usercert, QString uuid) );
|
||||
SLOT( bool writeIPsecPrivatePass(QString pass, QString host, QString uuid) );
|
||||
|
||||
SLOT( bool stopIPsec(QString tunnelName) );
|
||||
SLOT( bool startIPsec(QString tunnelName) );
|
||||
|
||||
SLOT( QString getTunnelStatus(QString tunnelName) );
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <QFileInfo>
|
||||
#include <QLocalSocket>
|
||||
#include <QObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "logger.h"
|
||||
#include "router.h"
|
||||
|
|
@ -170,6 +171,7 @@ void IpcServer::StartRoutingIpv6()
|
|||
{
|
||||
Router::StartRoutingIpv6();
|
||||
}
|
||||
|
||||
void IpcServer::StopRoutingIpv6()
|
||||
{
|
||||
Router::StopRoutingIpv6();
|
||||
|
|
@ -275,7 +277,6 @@ bool IpcServer::enableKillSwitch(const QJsonObject &configStr, int vpnAdapterInd
|
|||
MacOSFirewall::setAnchorEnabled(QStringLiteral("310.blockDNS"), true);
|
||||
MacOSFirewall::setAnchorTable(QStringLiteral("310.blockDNS"), true, QStringLiteral("dnsaddr"), dnsServers);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -298,6 +299,196 @@ bool IpcServer::disableKillSwitch()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::startIPsec(QString tunnelName)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
QProcess processSystemd;
|
||||
QStringList commandsSystemd;
|
||||
commandsSystemd << "systemctl" << "restart" << "ipsec";
|
||||
processSystemd.start("sudo", commandsSystemd);
|
||||
if (!processSystemd.waitForStarted(1000))
|
||||
{
|
||||
qDebug().noquote() << "Could not start ipsec tunnel!\n";
|
||||
return false;
|
||||
}
|
||||
else if (!processSystemd.waitForFinished(2000))
|
||||
{
|
||||
qDebug().noquote() << "Could not start ipsec tunnel\n";
|
||||
return false;
|
||||
}
|
||||
commandsSystemd.clear();
|
||||
|
||||
QThread::msleep(5000);
|
||||
|
||||
QProcess process;
|
||||
QStringList commands;
|
||||
commands << "ipsec" << "up" << QString("%1").arg(tunnelName);
|
||||
process.start("sudo", commands);
|
||||
if (!process.waitForStarted(1000))
|
||||
{
|
||||
qDebug().noquote() << "Could not start ipsec tunnel!\n";
|
||||
return false;
|
||||
}
|
||||
else if (!process.waitForFinished(2000))
|
||||
{
|
||||
qDebug().noquote() << "Could not start ipsec tunnel\n";
|
||||
return false;
|
||||
}
|
||||
commands.clear();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::stopIPsec(QString tunnelName)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
QProcess process;
|
||||
QStringList commands;
|
||||
commands << "ipsec" << "down" << QString("%1").arg(tunnelName);
|
||||
process.start("sudo", commands);
|
||||
if (!process.waitForStarted(1000))
|
||||
{
|
||||
qDebug().noquote() << "Could not stop ipsec tunnel\n";
|
||||
return false;
|
||||
}
|
||||
else if (!process.waitForFinished(2000))
|
||||
{
|
||||
qDebug().noquote() << "Could not stop ipsec tunnel\n";
|
||||
return false;
|
||||
}
|
||||
commands.clear();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::writeIPsecConfig(QString config)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
qDebug() << "IPSEC: IPSec config file";
|
||||
QString configFile = QString("/etc/ipsec.conf");
|
||||
QFile ipSecConfFile(configFile);
|
||||
if (ipSecConfFile.open(QIODevice::WriteOnly)) {
|
||||
ipSecConfFile.write(config.toUtf8());
|
||||
ipSecConfFile.close();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::writeIPsecUserCert(QString usercert, QString uuid)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
qDebug() << "IPSEC: Write user cert " << uuid;
|
||||
QString certName = QString("/etc/ipsec.d/certs/%1.crt").arg(uuid);
|
||||
QFile userCertFile(certName);
|
||||
if (userCertFile.open(QIODevice::WriteOnly)) {
|
||||
userCertFile.write(usercert.toUtf8());
|
||||
userCertFile.close();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::writeIPsecCaCert(QString cacert, QString uuid)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
qDebug() << "IPSEC: Write CA cert user " << uuid;
|
||||
QString certName = QString("/etc/ipsec.d/cacerts/%1.crt").arg(uuid);
|
||||
QFile caCertFile(certName);
|
||||
if (caCertFile.open(QIODevice::WriteOnly)) {
|
||||
caCertFile.write(cacert.toUtf8());
|
||||
caCertFile.close();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IpcServer::writeIPsecPrivate(QString privKey, QString uuid)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
qDebug() << "IPSEC: User private key " << uuid;
|
||||
QString privateKey = QString("/etc/ipsec.d/private/%1.p12").arg(uuid);
|
||||
QFile pKeyFile(privateKey);
|
||||
if (pKeyFile.open(QIODevice::WriteOnly)) {
|
||||
pKeyFile.write(QByteArray::fromBase64(privKey.toUtf8()));
|
||||
pKeyFile.close();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IpcServer::writeIPsecPrivatePass(QString pass, QString host, QString uuid)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
qDebug() << "IPSEC: User private key " << uuid;
|
||||
const QString secretsFilename = "/etc/ipsec.secrets";
|
||||
QStringList lines;
|
||||
|
||||
{
|
||||
QFile secretsFile(secretsFilename);
|
||||
if (secretsFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QTextStream edit(&secretsFile);
|
||||
while (!edit.atEnd()) lines.push_back(edit.readLine());
|
||||
}
|
||||
secretsFile.close();
|
||||
}
|
||||
|
||||
for (auto iter = lines.begin(); iter!=lines.end();)
|
||||
{
|
||||
if (iter->contains(host))
|
||||
{
|
||||
iter = lines.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QFile secretsFile(secretsFilename);
|
||||
if (secretsFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
QTextStream edit(&secretsFile);
|
||||
for (int i=0; i<lines.size(); i++) edit << lines[i] << Qt::endl;
|
||||
}
|
||||
QString P12 = QString("%any %1 : P12 %2.p12 \"%3\" \n").arg(host, uuid, pass);
|
||||
secretsFile.write(P12.toUtf8());
|
||||
secretsFile.close();
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
QString IpcServer::getTunnelStatus(QString tunnelName)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
QProcess process;
|
||||
QStringList commands;
|
||||
commands << "ipsec" << "status" << QString("%1").arg(tunnelName);
|
||||
process.start("sudo", commands);
|
||||
if (!process.waitForStarted(1000))
|
||||
{
|
||||
qDebug().noquote() << "Could not stop ipsec tunnel\n";
|
||||
return "";
|
||||
}
|
||||
else if (!process.waitForFinished(2000))
|
||||
{
|
||||
qDebug().noquote() << "Could not stop ipsec tunnel\n";
|
||||
return "";
|
||||
}
|
||||
commands.clear();
|
||||
|
||||
|
||||
QString status = process.readAll();
|
||||
return status;
|
||||
#endif
|
||||
return QString();
|
||||
|
||||
}
|
||||
|
||||
bool IpcServer::enablePeerTraffic(const QJsonObject &configStr)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
|
|
|
|||
|
|
@ -38,6 +38,14 @@ public:
|
|||
virtual bool enableKillSwitch(const QJsonObject &excludeAddr, int vpnAdapterIndex) override;
|
||||
virtual bool disableKillSwitch() override;
|
||||
virtual bool updateResolvers(const QString& ifname, const QList<QHostAddress>& resolvers) override;
|
||||
virtual bool writeIPsecCaCert(QString cacert, QString uuid) override;
|
||||
virtual bool writeIPsecPrivate(QString privKey, QString uuid) override;
|
||||
virtual bool writeIPsecConfig(QString config) override;
|
||||
virtual bool writeIPsecUserCert(QString usercert, QString uuid) override;
|
||||
virtual bool writeIPsecPrivatePass(QString pass, QString host, QString uuid) override;
|
||||
virtual bool stopIPsec(QString tunnelName) override;
|
||||
virtual bool startIPsec(QString tunnelName) override;
|
||||
virtual QString getTunnelStatus(QString tunnelName) override;
|
||||
|
||||
private:
|
||||
int m_localpid = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue