fix: outbound freedom for xray (#2479)

* fix: outbound freedom for xray on linux

* fix: outbound freedom for xray on macOS

* build: auto-generate pf rules based on the build type
This commit is contained in:
cd-amn
2026-05-04 15:39:07 +04:00
committed by GitHub
parent c28452a5da
commit c0cae0ff01
15 changed files with 221 additions and 7 deletions
+33 -4
View File
@@ -1,5 +1,8 @@
#include "xray.h"
#include "core/utils/networkUtilities.h"
#ifdef Q_OS_MAC
#include "router_mac.h"
#endif
#include <QDebug>
#include <QNetworkInterface>
@@ -25,18 +28,34 @@
#endif
#ifdef Q_OS_LINUX
#include <sys/socket.h>
#include "xray_defs.h"
#endif
bool Xray::startXray(const QString &cfg)
{
qDebug() << "Xray::startXray()";
auto defaultIface = NetworkUtilities::getGatewayAndIface().second;
const auto gatewayAndIface = NetworkUtilities::getGatewayAndIface();
const QString defaultGateway = gatewayAndIface.first;
const QNetworkInterface defaultIface = gatewayAndIface.second;
#ifdef Q_OS_LINUX
m_defaultIfaceName = defaultIface.name().toUtf8();
#else
m_defaultIfaceIdx = defaultIface.index();
#endif
if (defaultIface.index() > 0) {
qDebug() << "[xray] using uplink interface:" << defaultIface.name() << "(" << defaultIface.index() << ")";
}
#ifdef Q_OS_MAC
m_uplinkIfaceName = defaultIface.name();
m_uplinkGateway = defaultGateway;
if (!m_uplinkIfaceName.isEmpty()) {
const bool installed = RouterMac::Instance().routeAddXray(m_uplinkIfaceName, m_uplinkGateway);
if (!installed) {
qWarning() << "[xray] failed to install xray routes on" << m_uplinkIfaceName;
}
}
#endif
if (auto err = amnezia_xray_setsockcallback(ctxSockCallback, this); err != nullptr) {
qDebug() << "[xray] sockopt failed: " << err;
@@ -65,13 +84,22 @@ bool Xray::startXray(const QString &cfg)
bool Xray::stopXray()
{
qDebug() << "Xray::stopXray()";
bool success = true;
if (auto err = amnezia_xray_stop(); err != nullptr) {
qDebug() << "[xray] failed to stop: " << err;
amnezia_xray_free(err);
return false;
success = false;
}
return true;
#ifdef Q_OS_MAC
if (!m_uplinkIfaceName.isEmpty()) {
RouterMac::Instance().routeDeleteXray(m_uplinkIfaceName, m_uplinkGateway);
}
m_uplinkIfaceName.clear();
m_uplinkGateway.clear();
#endif
return success;
}
void Xray::logHandler(char* str)
@@ -99,6 +127,7 @@ void Xray::sockCallback(uintptr_t fd)
#ifdef Q_OS_LINUX
if (!m_defaultIfaceName.isEmpty()) {
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, m_defaultIfaceName.data(), m_defaultIfaceName.size());
setsockopt(fd, SOL_SOCKET, SO_MARK, &amnezia::xray::xrayTrafficMark, sizeof(amnezia::xray::xrayTrafficMark));
}
#endif
}