mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
feat: made API port static and proxy port configurable
This commit is contained in:
@@ -37,6 +37,8 @@ CoreController::CoreController(const QSharedPointer<VpnConnection> &vpnConnectio
|
||||
void CoreController::initLocalProxy()
|
||||
{
|
||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
||||
constexpr quint16 kLocalProxyApiPort = 49490;
|
||||
|
||||
m_proxyServer.reset(new ProxyServer(m_settings, this));
|
||||
|
||||
auto syncLocalProxy = [this]() {
|
||||
@@ -45,7 +47,6 @@ void CoreController::initLocalProxy()
|
||||
}
|
||||
|
||||
const bool httpEnabled = m_settings->isLocalProxyHttpEnabled();
|
||||
const quint16 port = m_settings->localProxyPort();
|
||||
|
||||
if (!httpEnabled) {
|
||||
qInfo() << "Local proxy: HTTP API disabled";
|
||||
@@ -53,22 +54,16 @@ void CoreController::initLocalProxy()
|
||||
return;
|
||||
}
|
||||
|
||||
if (port < 1024) {
|
||||
qWarning() << "Local proxy: invalid HTTP API port" << port << ", stopping server";
|
||||
m_proxyServer->stop();
|
||||
m_settings->setLocalProxyHttpEnabled(false);
|
||||
emit m_settings->localProxyStartFailed(tr("Local proxy disabled: invalid HTTP API port."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_proxyServer->start(port)) {
|
||||
qWarning() << "Local proxy: failed to start on port" << port;
|
||||
if (!m_proxyServer->start(kLocalProxyApiPort)) {
|
||||
qWarning() << "Local proxy: failed to start on port" << kLocalProxyApiPort;
|
||||
m_settings->setLocalProxyHttpEnabled(false);
|
||||
emit m_settings->localProxyStartFailed(tr("Local proxy failed to start. Check if the port is available."));
|
||||
return;
|
||||
}
|
||||
|
||||
qInfo() << "Local proxy: running on 127.0.0.1:" << port;
|
||||
m_proxyServer->syncSettings();
|
||||
|
||||
qInfo() << "Local proxy: running on 127.0.0.1:" << kLocalProxyApiPort;
|
||||
};
|
||||
|
||||
syncLocalProxy();
|
||||
|
||||
@@ -38,6 +38,45 @@ constexpr char appVersion[] = "app_version";
|
||||
constexpr char publicKey[] = "public_key";
|
||||
constexpr char vless[] = "vless";
|
||||
} // namespace gateway_key
|
||||
|
||||
constexpr quint16 kDefaultProxyPort = 10808;
|
||||
|
||||
int resolveProxyPort(const std::shared_ptr<Settings> &settings)
|
||||
{
|
||||
if (!settings) {
|
||||
return kDefaultProxyPort;
|
||||
}
|
||||
|
||||
const quint16 port = settings->localProxyPort();
|
||||
if (port < 1024 || port > 65535) {
|
||||
return kDefaultProxyPort;
|
||||
}
|
||||
|
||||
return static_cast<int>(port);
|
||||
}
|
||||
|
||||
bool applyProxyPortToConfig(QJsonObject &config, int port)
|
||||
{
|
||||
if (!config.contains("inbounds") || !config.value("inbounds").isArray()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonArray inbounds = config.value("inbounds").toArray();
|
||||
if (inbounds.isEmpty() || !inbounds.at(0).isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject firstInbound = inbounds.at(0).toObject();
|
||||
firstInbound.insert("port", port);
|
||||
inbounds[0] = firstInbound;
|
||||
config.insert("inbounds", inbounds);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString serializeConfig(const QJsonObject &config)
|
||||
{
|
||||
return QString::fromUtf8(QJsonDocument(config).toJson(QJsonDocument::Compact));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::optional<ConfigManager::ConfigData> ConfigManager::buildConfig(QString &errorDescription) const
|
||||
@@ -96,8 +135,14 @@ std::optional<ConfigManager::ConfigData> ConfigManager::buildConfig(QString &err
|
||||
ConfigData data;
|
||||
data.ownerUuid = ownerUuid;
|
||||
data.serverName = ownerServer->value(amnezia::config_key::name).toString();
|
||||
data.serializedConfig = *serializedConfig;
|
||||
data.parsedConfig = doc.object();
|
||||
const int proxyPort = resolveProxyPort(m_settings);
|
||||
if (applyProxyPortToConfig(data.parsedConfig, proxyPort)) {
|
||||
data.serializedConfig = serializeConfig(data.parsedConfig);
|
||||
} else {
|
||||
ProxyLogger::getInstance().warning(QStringLiteral("Failed to override local proxy inbound port; using original config"));
|
||||
data.serializedConfig = *serializedConfig;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -158,8 +203,14 @@ std::optional<ConfigManager::ConfigData> ConfigManager::buildConfigWithFetch(QSt
|
||||
ConfigData data;
|
||||
data.ownerUuid = ownerUuid;
|
||||
data.serverName = ownerServer->value(amnezia::config_key::name).toString();
|
||||
data.serializedConfig = *serializedConfig;
|
||||
data.parsedConfig = doc.object();
|
||||
const int proxyPort = resolveProxyPort(m_settings);
|
||||
if (applyProxyPortToConfig(data.parsedConfig, proxyPort)) {
|
||||
data.serializedConfig = serializeConfig(data.parsedConfig);
|
||||
} else {
|
||||
ProxyLogger::getInstance().warning(QStringLiteral("Failed to override local proxy inbound port; using original config"));
|
||||
data.serializedConfig = *serializedConfig;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
#include "proxyserver.h"
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QStandardPaths>
|
||||
|
||||
ProxyServer::ProxyServer(const std::shared_ptr<Settings> &settings, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_settings(settings)
|
||||
, m_service(new ProxyService(settings, this))
|
||||
{
|
||||
}
|
||||
@@ -22,7 +18,7 @@ ProxyServer::~ProxyServer()
|
||||
bool ProxyServer::start(quint16 port)
|
||||
{
|
||||
if (m_isRunning) {
|
||||
if (m_currentPort == port) {
|
||||
if (m_currentApiPort == port) {
|
||||
qInfo() << "Local proxy: already running on port" << port;
|
||||
return true;
|
||||
}
|
||||
@@ -37,20 +33,12 @@ bool ProxyServer::start(quint16 port)
|
||||
qWarning() << "Local proxy: port is busy:" << port;
|
||||
m_api.reset();
|
||||
m_isRunning = false;
|
||||
m_currentPort = 0;
|
||||
m_currentApiPort = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Auto-start Xray if config exists
|
||||
QJsonObject config = m_service->getConfig();
|
||||
if (!config.isEmpty()) {
|
||||
startXrayProcess();
|
||||
} else {
|
||||
qDebug() << "No config found, Xray will not start automatically";
|
||||
}
|
||||
|
||||
m_isRunning = true;
|
||||
m_currentPort = port;
|
||||
m_currentApiPort = port;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -63,7 +51,8 @@ void ProxyServer::stop()
|
||||
m_api.reset();
|
||||
}
|
||||
m_isRunning = false;
|
||||
m_currentPort = 0;
|
||||
m_currentApiPort = 0;
|
||||
m_currentProxyPort = 0;
|
||||
}
|
||||
|
||||
bool ProxyServer::startXrayProcess()
|
||||
@@ -74,4 +63,28 @@ bool ProxyServer::startXrayProcess()
|
||||
void ProxyServer::stopXrayProcess()
|
||||
{
|
||||
m_service->stopXray();
|
||||
}
|
||||
|
||||
void ProxyServer::syncSettings()
|
||||
{
|
||||
if (!m_isRunning) {
|
||||
qDebug() << "Local proxy: syncSettings called but server is not running";
|
||||
return;
|
||||
}
|
||||
|
||||
const quint16 newProxyPort = m_settings ? m_settings->localProxyPort() : 0;
|
||||
const bool xrayRunning = m_service->isXrayRunning();
|
||||
|
||||
if (!xrayRunning) {
|
||||
qInfo() << "Local proxy: starting Xray on port" << newProxyPort;
|
||||
m_currentProxyPort = newProxyPort;
|
||||
startXrayProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentProxyPort != newProxyPort) {
|
||||
qInfo() << "Local proxy: proxy port changed from" << m_currentProxyPort << "to" << newProxyPort;
|
||||
m_currentProxyPort = newProxyPort;
|
||||
m_service->restartXray();
|
||||
}
|
||||
}
|
||||
@@ -18,15 +18,18 @@ public:
|
||||
explicit ProxyServer(const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
|
||||
~ProxyServer();
|
||||
|
||||
bool start(quint16 port = 8080);
|
||||
bool start(quint16 port = 49490);
|
||||
void stop();
|
||||
void syncSettings();
|
||||
|
||||
private:
|
||||
bool startXrayProcess();
|
||||
void stopXrayProcess();
|
||||
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
QScopedPointer<HttpApi> m_api;
|
||||
QSharedPointer<ProxyService> m_service;
|
||||
bool m_isRunning {false};
|
||||
quint16 m_currentPort {0};
|
||||
quint16 m_currentApiPort {0};
|
||||
quint16 m_currentProxyPort {0};
|
||||
};
|
||||
@@ -89,4 +89,25 @@ qint64 ProxyService::getXrayProcessId() const
|
||||
QString ProxyService::getXrayError() const
|
||||
{
|
||||
return m_xrayController->getError();
|
||||
}
|
||||
|
||||
void ProxyService::clearCache()
|
||||
{
|
||||
m_cachedConfig = QJsonObject();
|
||||
ProxyLogger::getInstance().debug("ProxyService cache cleared");
|
||||
}
|
||||
|
||||
bool ProxyService::restartXray()
|
||||
{
|
||||
ProxyLogger::getInstance().info("Restarting Xray with updated config");
|
||||
clearCache();
|
||||
|
||||
if (m_xrayController->isXrayRunning()) {
|
||||
if (!stopXray()) {
|
||||
ProxyLogger::getInstance().error("Failed to stop Xray during restart, aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return startXray();
|
||||
}
|
||||
@@ -25,6 +25,9 @@ public:
|
||||
qint64 getXrayProcessId() const override;
|
||||
QString getXrayError() const override;
|
||||
|
||||
void clearCache();
|
||||
bool restartXray();
|
||||
|
||||
signals:
|
||||
void xrayStatusChanged(bool running);
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ void Settings::setLocalProxyOwnerUuid(const QString &uuid)
|
||||
|
||||
quint16 Settings::localProxyPort() const
|
||||
{
|
||||
return value("Conf/localProxyPort", 0).toUInt();
|
||||
return value("Conf/localProxyPort", 10808).toUInt();
|
||||
}
|
||||
|
||||
void Settings::setLocalProxyPort(quint16 port)
|
||||
|
||||
@@ -135,7 +135,7 @@ PageType {
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
headerText: qsTr("HTTP API port")
|
||||
headerText: qsTr("Local proxy port")
|
||||
|
||||
enabled: true
|
||||
|
||||
@@ -182,7 +182,7 @@ PageType {
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("HTTP API controls Xray via /api/v1/up and /api/v1/down. SOCKS inbound stays on port 10808.")
|
||||
text: qsTr("SOCKS inbound listens on the specified port. Connect your client to 127.0.0.1.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user