Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MacOS IPSec protocol #1042

Open
wants to merge 8 commits into
base: feature/linux-ipsec
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion client/cmake/macos.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,22 @@ set(LIBS ${LIBS}
${FW_NETWORK_EXTENSION}
)

set_target_properties(${PROJECT} PROPERTIES MACOSX_BUNDLE TRUE)
set_target_properties(${PROJECT} PROPERTIES
MACOSX_BUNDLE TRUE
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/macos/app/AmneziaVPN.entitlements"
)
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE INTERNAL "" FORCE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15)


set(HEADERS ${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/ui/macos_util.h
${CMAKE_CURRENT_SOURCE_DIR}/protocols/ikev2_vpn_protocol_mac.h
)

set(SOURCES ${SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/ui/macos_util.mm
${CMAKE_CURRENT_SOURCE_DIR}/protocols/ikev2_vpn_protocol_mac.mm
)

set(ICON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/images/app.icns)
Expand Down
2 changes: 1 addition & 1 deletion client/containers/containers_defs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
#elif defined(Q_OS_MAC)
switch (c) {
case DockerContainer::WireGuard: return true;
case DockerContainer::Ipsec: return false;
case DockerContainer::Ipsec: return true;
default: return true;
}

Expand Down
116 changes: 116 additions & 0 deletions client/core/networkUtilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <libproc.h>
#include <netdb.h>
#include <netinet/in.h>
#include <semaphore.h>
#include <unistd.h>
#endif

#include <QHostAddress>
Expand Down Expand Up @@ -463,3 +470,112 @@ QString NetworkUtilities::getGatewayAndIface()
return gateway;
#endif
}

#if defined(Q_OS_MAC)
QString NetworkUtilities::ipAddressByInterfaceName(const QString &interfaceName)
{
struct ifaddrs *ifaddr, *ifa;
char host[NI_MAXHOST];

if (getifaddrs(&ifaddr) == -1)
{
return "";
}

for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
{
continue;
}
int family = ifa->ifa_addr->sa_family;
QString iname = QString::fromStdString(ifa->ifa_name);

if (family == AF_INET && iname == interfaceName)
{
int s = getnameinfo(ifa->ifa_addr,
(family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST,
NULL, 0, NI_NUMERICHOST);
if (s != 0)
{
continue;
}

return QString::fromStdString(host);
}
}

freeifaddrs(ifaddr);
return "";
}

QString NetworkUtilities::lastConnectedNetworkInterfaceName()
{
QString ifname("");

struct ifaddrs * interfaces = NULL;
struct ifaddrs * temp_addr = NULL;

if( getifaddrs(&interfaces) == 0 )
{
//Loop through linked list of interfaces
temp_addr = interfaces;
while( temp_addr != NULL )
{
if( temp_addr->ifa_addr->sa_family == AF_INET )
{
QString tname = temp_addr->ifa_name;
if( tname.startsWith("utun") )
ifname = tname;
else if( tname.startsWith("ipsec") )
ifname = tname;
else if( tname.startsWith("ppp") )
ifname = tname;
}

temp_addr = temp_addr->ifa_next;
}

freeifaddrs(interfaces);
}
return ifname;
}

QString execCmd(const QString &cmd)
{
char buffer[1024];
QString result = "";
FILE* pipe = popen(cmd.toStdString().c_str(), "r");
if (!pipe) return "";
while (!feof(pipe))
{
if (fgets(buffer, 1024, pipe) != NULL)
{
result += buffer;
}
}
pclose(pipe);
return result;
}

QStringList NetworkUtilities::getListOfDnsNetworkServiceEntries()
{
QStringList result;
QString command = "echo 'list' | scutil | grep /Network/Service | grep DNS";
QString cmdOutput = execCmd(command).trimmed();
// qDebug() << "Raw result: " << cmdOutput;

QStringList lines = cmdOutput.split('\n');
for (QString line : lines)
{
if (line.contains("="))
{
QString entry = line.mid(line.indexOf("=")+1).trimmed();
result.append(entry);
}
}
return result;
}
#endif
13 changes: 9 additions & 4 deletions client/core/networkUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,24 @@ class NetworkUtilities : public QObject
static QString getGatewayAndIface();
// Returns the Interface Index that could Route to dst
static int AdapterIndexTo(const QHostAddress& dst);

static QRegularExpression ipAddressRegExp();
static QRegularExpression ipAddressPortRegExp();
static QRegExp ipAddressWithSubnetRegExp();
static QRegExp ipNetwork24RegExp();
static QRegExp ipPortRegExp();
static QRegExp domainRegExp();

static QString netMaskFromIpWithSubnet(const QString ip);
static QString ipAddressFromIpWithSubnet(const QString ip);

static QStringList summarizeRoutes(const QStringList &ips, const QString cidr);


#if defined(Q_OS_MAC)
static QString ipAddressByInterfaceName(const QString &interfaceName);
static QString lastConnectedNetworkInterfaceName();
static QStringList getListOfDnsNetworkServiceEntries();
#endif
};

#endif // NETWORKUTILITIES_H
14 changes: 14 additions & 0 deletions client/macos/app/AmneziaVPN.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
</dict>
</plist>
45 changes: 45 additions & 0 deletions client/protocols/ikev2_vpn_protocol_mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <QObject>
#include <QTimer>


#include "openvpnprotocol.h"


class Ikev2Protocol : public VpnProtocol
{
Q_OBJECT
public:
explicit Ikev2Protocol(const QJsonObject& configuration, QObject* parent = nullptr);
virtual ~Ikev2Protocol() override;

void readIkev2Configuration(const QJsonObject &configuration);
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();
void closeWindscribeActiveConnection();
ErrorCode start() override;
void stop() override;

static QString tunnelName() { return "AmneziaVPN IKEv2"; }

private slots:
void handleNotificationImpl(int status);

private:
mutable QRecursiveMutex mutex_;
void *notificationId_;
QJsonObject m_config;
QJsonObject m_ikev2_config;

QString ipsecAdapterName_;

bool isConnectingStateReachedAfterStartingConnection_;

void handleNotification(void *notification);
bool isFailedAuthError(QMap<time_t, QString> &logs);
bool isSocketError(QMap<time_t, QString> &logs);
bool setCustomDns(const QString &overrideDnsIpAddress);
};
Loading
Loading