refactor: refactors for V2rayIntegration

This commit is contained in:
Qv2ray-dev 2020-06-27 22:27:20 +08:00
parent 553dc49cf3
commit 0abf4fc9da
No known key found for this signature in database
GPG Key ID: E7FAEFAFCD031D4B
13 changed files with 157 additions and 100 deletions

View File

@ -1 +1 @@
5675
5676

View File

@ -265,7 +265,7 @@ namespace Qv2ray::base::objects
QList<QString> alpn;
QList<CertificateObject> certificates;
bool disableSystemRoot;
TLSObject() : serverName(), allowInsecure(), allowInsecureCiphers(), disableSessionResumption(), certificates(), disableSystemRoot(){};
TLSObject() : serverName(), allowInsecure(), allowInsecureCiphers(), disableSessionResumption(true), certificates(), disableSystemRoot(){};
JSONSTRUCT_REGISTER(TLSObject, F(serverName, allowInsecure, allowInsecureCiphers, disableSessionResumption, alpn, certificates, disableSystemRoot))
};
} // namespace transfer

View File

@ -94,9 +94,9 @@ namespace Qv2ray::base::config
struct Qv2rayConfig_Advanced
{
bool setAllowInsecure;
bool setAllowInsecureCiphers;
bool setSessionResumption;
bool testLatencyPeriodcally;
JSONSTRUCT_REGISTER(Qv2rayConfig_Advanced, F(setAllowInsecure, setAllowInsecureCiphers, testLatencyPeriodcally))
JSONSTRUCT_REGISTER(Qv2rayConfig_Advanced, F(setAllowInsecure, setSessionResumption, testLatencyPeriodcally))
};
enum Qv2rayLatencyTestingMethod

View File

@ -16,11 +16,11 @@ namespace Qv2ray::core::connection
QList<QPair<QString, CONFIGROOT>> connectionConf;
const auto mkAllowInsecure = [](QJsonObject &conf) {
auto allowI = GlobalConfig.advancedConfig.setAllowInsecure;
auto allowIC = GlobalConfig.advancedConfig.setAllowInsecureCiphers;
if (allowI || allowIC)
auto allowSR = GlobalConfig.advancedConfig.setSessionResumption;
if (allowI || allowSR)
{
QJsonIO::SetValue(conf, allowI, "outbounds", 0, "streamSettings", "tlsSettings", "allowInsecure");
QJsonIO::SetValue(conf, allowIC, "outbounds", 0, "streamSettings", "tlsSettings", "allowInsecureCiphers");
QJsonIO::SetValue(conf, !allowSR, "outbounds", 0, "streamSettings", "tlsSettings", "disableSessionResumption");
}
};
if (link.startsWith("vmess://") && link.contains("@"))

View File

@ -36,31 +36,51 @@ namespace Qv2ray::core::handler
StopConnection();
}
std::optional<QString> KernelInstanceHandler::StartConnection(const ConnectionGroupPair &id, CONFIGROOT fullConfig)
std::optional<QString> KernelInstanceHandler::CheckPort(QMap<QString, QString> hosts, QMap<QString, int> ports, int plugins)
{
StopConnection();
inboundPorts = GetConfigInboundPorts(fullConfig);
inboundHosts = GetConfigInboundHosts(fullConfig);
//
// Check inbound port allocation issue.
QStringList portDetectionErrorMessage;
auto portDetectionMsg = tr("Another process is using the port required to start the connection:") + NEWLINE + NEWLINE;
for (const auto &key : inboundPorts.keys())
for (const auto &key : ports.keys())
{
auto result = components::port::CheckTCPPortStatus(inboundHosts[key], inboundPorts[key]);
auto result = components::port::CheckTCPPortStatus(hosts[key], ports[key]);
if (!result)
{
portDetectionErrorMessage << tr("Port: %1 for listening IP: %2 for inbound tag: \"%3\"") //
.arg(inboundPorts[key])
.arg(inboundHosts[key])
.arg(ports[key])
.arg(hosts[key])
.arg(key);
}
}
if (GlobalConfig.pluginConfig.v2rayIntegration)
{
for (int i = 0; i <= plugins; i++)
{
auto result = components::port::CheckTCPPortStatus("127.0.0.1", GlobalConfig.pluginConfig.portAllocationStart + i);
if (!result)
{
portDetectionErrorMessage << tr("Port: %1 for listening IP: 127.0.0.1 for plugin integration.")
.arg(GlobalConfig.pluginConfig.portAllocationStart + i);
}
}
}
if (!portDetectionErrorMessage.isEmpty())
{
portDetectionMsg += portDetectionErrorMessage.join(NEWLINE);
return portDetectionMsg;
}
else
{
return std::nullopt;
}
}
std::optional<QString> KernelInstanceHandler::StartConnection(const ConnectionGroupPair &id, CONFIGROOT fullConfig)
{
StopConnection();
inboundPorts = GetConfigInboundPorts(fullConfig);
inboundHosts = GetConfigInboundHosts(fullConfig);
//
PluginHost->Send_ConnectivityEvent({ GetDisplayName(id.connectionId), inboundPorts, Events::Connectivity::Connecting });
QList<std::tuple<QString, int, QString>> inboundInfo;
@ -70,7 +90,7 @@ namespace Qv2ray::core::handler
inboundInfo.push_back({ inbound["protocol"].toString(), inbound["port"].toInt(), inbound["tag"].toString() });
}
//
using k = Qv2rayPlugin::QvPluginKernel;
using _k_ = Qv2rayPlugin::QvPluginKernel;
if (GlobalConfig.pluginConfig.v2rayIntegration)
{
//
@ -105,35 +125,44 @@ namespace Qv2ray::core::handler
//
QMap<QvPluginKernel::KernelSetting, QVariant> _inboundSettings;
_inboundSettings[k::KERNEL_HTTP_ENABLED] = false;
_inboundSettings[k::KERNEL_SOCKS_ENABLED] = true;
_inboundSettings.insert(k::KERNEL_SOCKS_PORT, pluginPort);
_inboundSettings[_k_::KERNEL_HTTP_ENABLED] = false;
_inboundSettings[_k_::KERNEL_SOCKS_ENABLED] = true;
_inboundSettings.insert(_k_::KERNEL_SOCKS_PORT, pluginPort);
LOG(MODULE_VCORE, "V2rayIntegration: " + QSTRN(pluginPort) + "=" + outProtocol)
//
const auto pluginOutSettings = GenerateHTTPSOCKSOut("127.0.0.1", pluginPort, false, "", "");
const auto pluginOut = GenerateOutboundEntry("socks", pluginOutSettings, {}, {}, "0.0.0.0", outbound["tag"].toString());
//
// Add the integration outbound to the list.
processedOutbounds.push_back(pluginOut);
pluginPort++;
_inboundSettings[k::KERNEL_SOCKS_UDP_ENABLED] = GlobalConfig.inboundConfig.socksSettings.enableUDP;
_inboundSettings[k::KERNEL_SOCKS_LOCAL_ADDRESS] = GlobalConfig.inboundConfig.socksSettings.localIP;
_inboundSettings[k::KERNEL_LISTEN_ADDRESS] = "127.0.0.1";
//
_inboundSettings[_k_::KERNEL_SOCKS_UDP_ENABLED] = GlobalConfig.inboundConfig.socksSettings.enableUDP;
_inboundSettings[_k_::KERNEL_SOCKS_LOCAL_ADDRESS] = GlobalConfig.inboundConfig.socksSettings.localIP;
_inboundSettings[_k_::KERNEL_LISTEN_ADDRESS] = "127.0.0.1";
LOG(MODULE_CONNECTION, "Sending connection settings to kernel.")
activeKernels[outProtocol]->SetConnectionSettings(_inboundSettings, outbound["settings"].toObject());
}
LOG(MODULE_CONNECTION, "Applying new outbound settings.")
fullConfig["outbounds"] = processedOutbounds;
}
RemoveEmptyMuxFilter(fullConfig);
}
//
// Process routing entries
//
// No needs to process routing entries since each plugin is map to an unique outbound with the same tag.
//
// ================================================================================================
// ======================================================================= Start Kernels
//
{
const auto portResult = CheckPort(inboundHosts, inboundPorts, activeKernels.size());
if (portResult)
{
LOG(MODULE_CONNECTION, ACCESS_OPTIONAL_VALUE(portResult))
return portResult;
}
auto firstOutbound = fullConfig["outbounds"].toArray().first().toObject();
const auto firstOutboundProtocol = firstOutbound["protocol"].toString();
if (GlobalConfig.pluginConfig.v2rayIntegration)
{
LOG(MODULE_VCORE, "Starting kernels with V2rayIntegration.")
bool hasAllKernelStarted = true;
for (auto &[kernel, kernelObject] : activeKernels)
{
@ -170,39 +199,38 @@ namespace Qv2ray::core::handler
PluginHost->Send_ConnectivityEvent({ GetDisplayName(id.connectionId), inboundPorts, Events::Connectivity::Connected });
}
}
else
else if (outboundKernelMap.contains(firstOutboundProtocol))
{
LOG(MODULE_CONNECTION, "Starting kernel without V2ray Integration")
auto firstOutbound = fullConfig["outbounds"].toArray().first().toObject();
const auto protocol = firstOutbound["protocol"].toString();
if (outboundKernelMap.contains(protocol))
{
LOG(MODULE_CONNECTION, "Found existing kernel for: " + protocol)
LOG(MODULE_CONNECTION, "Starting kernel " + firstOutboundProtocol + " without V2ray Integration")
{
auto kernel = PluginHost->CreatePluginKernel(outboundKernelMap[firstOutbound["protocol"].toString()]);
activeKernels[protocol] = std::move(kernel);
activeKernels[firstOutboundProtocol] = std::move(kernel);
}
#define kernel (activeKernels[firstOutboundProtocol].get())
connect(kernel, &QvPluginKernel::OnKernelStatsAvailable, this, &KernelInstanceHandler::OnStatsDataRcvd_p);
connect(kernel, &QvPluginKernel::OnKernelCrashed, this, &KernelInstanceHandler::OnKernelCrashed_p);
connect(kernel, &QvPluginKernel::OnKernelLogAvailable, this, &KernelInstanceHandler::OnKernelLog_p);
#undef kernel
currentId = id;
//
QMap<QvPluginKernel::KernelSetting, QVariant> pluginInboundPort;
for (const auto &[_protocol, _port, _tag] : inboundInfo)
{
if (_protocol != "http" && _protocol != "socks")
continue;
pluginInboundPort[k::KERNEL_HTTP_ENABLED] = pluginInboundPort[k::KERNEL_HTTP_ENABLED].toBool() || _protocol == "http";
pluginInboundPort[k::KERNEL_SOCKS_ENABLED] = pluginInboundPort[k::KERNEL_SOCKS_ENABLED].toBool() || _protocol == "socks";
pluginInboundPort.insert(_protocol.toLower() == "http" ? k::KERNEL_HTTP_PORT : k::KERNEL_SOCKS_PORT, _port);
pluginInboundPort[_k_::KERNEL_HTTP_ENABLED] = pluginInboundPort[_k_::KERNEL_HTTP_ENABLED].toBool() || _protocol == "http";
pluginInboundPort[_k_::KERNEL_SOCKS_ENABLED] = pluginInboundPort[_k_::KERNEL_SOCKS_ENABLED].toBool() || _protocol == "socks";
pluginInboundPort.insert(_protocol.toLower() == "http" ? _k_::KERNEL_HTTP_PORT : _k_::KERNEL_SOCKS_PORT, _port);
}
connect(activeKernels[protocol].get(), &QvPluginKernel::OnKernelStatsAvailable, this, &KernelInstanceHandler::OnStatsDataRcvd_p);
connect(activeKernels[protocol].get(), &QvPluginKernel::OnKernelCrashed, this, &KernelInstanceHandler::OnKernelCrashed_p);
connect(activeKernels[protocol].get(), &QvPluginKernel::OnKernelLogAvailable, this, &KernelInstanceHandler::OnKernelLog_p);
currentId = id;
//
pluginInboundPort[k::KERNEL_SOCKS_UDP_ENABLED] = GlobalConfig.inboundConfig.socksSettings.enableUDP;
pluginInboundPort[k::KERNEL_SOCKS_LOCAL_ADDRESS] = GlobalConfig.inboundConfig.socksSettings.localIP;
pluginInboundPort[k::KERNEL_LISTEN_ADDRESS] = GlobalConfig.inboundConfig.listenip;
//
activeKernels[protocol]->SetConnectionSettings(pluginInboundPort, firstOutbound["settings"].toObject());
bool kernelStarted = activeKernels[protocol]->StartKernel();
pluginInboundPort[_k_::KERNEL_SOCKS_UDP_ENABLED] = GlobalConfig.inboundConfig.socksSettings.enableUDP;
pluginInboundPort[_k_::KERNEL_SOCKS_LOCAL_ADDRESS] = GlobalConfig.inboundConfig.socksSettings.localIP;
pluginInboundPort[_k_::KERNEL_LISTEN_ADDRESS] = GlobalConfig.inboundConfig.listenip;
//
activeKernels[firstOutboundProtocol]->SetConnectionSettings(pluginInboundPort, firstOutbound["settings"].toObject());
bool kernelStarted = activeKernels[firstOutboundProtocol]->StartKernel();
if (kernelStarted)
{
emit OnConnected(id);
@ -216,7 +244,7 @@ namespace Qv2ray::core::handler
}
else
{
LOG(MODULE_CONNECTION, "Starting V2ray without kernel")
LOG(MODULE_CONNECTION, "Starting V2ray without plugin.")
currentId = id;
auto result = vCoreInstance->StartConnection(fullConfig);
if (result.has_value())

View File

@ -20,6 +20,10 @@ namespace Qv2ray::core::handler
{
return currentId;
}
int ActivePluginKernelsCount() const
{
return activeKernels.size();
}
const QMap<QString, int> InboundPorts() const
{
return inboundPorts;
@ -41,6 +45,9 @@ namespace Qv2ray::core::handler
void OnKernelLog_p(const QString &log);
void OnStatsDataRcvd_p(const quint64 uploadSpeed, const quint64 downloadSpeed);
private:
static std::optional<QString> CheckPort(QMap<QString, QString> hosts, QMap<QString, int> ports, int plugins);
private:
QMap<QString, QString> outboundKernelMap;
// Since QMap does not support std::unique_ptr, we use std::map<>

View File

@ -143,6 +143,7 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QvDialog(parent), Curren
//
pluginKernelV2rayIntegrationCB->setChecked(CurrentConfig.pluginConfig.v2rayIntegration);
pluginKernelPortAllocateCB->setValue(CurrentConfig.pluginConfig.portAllocationStart);
pluginKernelPortAllocateCB->setEnabled(CurrentConfig.pluginConfig.v2rayIntegration);
//
//
latencyTCPingRB->setChecked(CurrentConfig.networkConfig.latencyTestingMethod == TCPING);
@ -163,7 +164,7 @@ PreferencesWindow::PreferencesWindow(QWidget *parent) : QvDialog(parent), Curren
//
// Advanced config.
setAllowInsecureCB->setChecked(CurrentConfig.advancedConfig.setAllowInsecure);
setAllowInsecureCiphersCB->setChecked(CurrentConfig.advancedConfig.setAllowInsecureCiphers);
setSessionResumptionCB->setChecked(CurrentConfig.advancedConfig.setSessionResumption);
setTestLatenctCB->setChecked(CurrentConfig.advancedConfig.testLatencyPeriodcally);
//
dnsSettingsWidget = new DnsSettingsWidget(this);
@ -854,12 +855,17 @@ void PreferencesWindow::on_updateChannelCombo_currentIndexChanged(int index)
void PreferencesWindow::on_pluginKernelV2rayIntegrationCB_stateChanged(int arg1)
{
LOADINGCHECK
if (KernelInstance->ActivePluginKernelsCount() > 0)
NEEDRESTART;
CurrentConfig.pluginConfig.v2rayIntegration = arg1 == Qt::Checked;
pluginKernelPortAllocateCB->setEnabled(arg1 == Qt::Checked);
}
void PreferencesWindow::on_pluginKernelPortAllocateCB_valueChanged(int arg1)
{
LOADINGCHECK
if (KernelInstance->ActivePluginKernelsCount() > 0)
NEEDRESTART;
CurrentConfig.pluginConfig.portAllocationStart = arg1;
}
@ -901,14 +907,14 @@ void PreferencesWindow::on_setTestLatenctCB_stateChanged(int arg1)
CurrentConfig.advancedConfig.testLatencyPeriodcally = arg1 == Qt::Checked;
}
void PreferencesWindow::on_setAllowInsecureCiphersCB_stateChanged(int arg1)
void PreferencesWindow::on_setSessionResumptionCB_stateChanged(int arg1)
{
LOADINGCHECK
if (arg1 == Qt::Checked)
{
QvMessageBoxWarn(this, tr("Dangerous Operation"), tr("You will lose the advantage of TLS and make your connection under MITM attack."));
QvMessageBoxWarn(this, tr("Dangerous Operation"), tr("This will make your TLS fingerpring different from common golang programs."));
}
CurrentConfig.advancedConfig.setAllowInsecureCiphers = arg1 == Qt::Checked;
CurrentConfig.advancedConfig.setSessionResumption = arg1 == Qt::Checked;
}
void PreferencesWindow::on_quietModeCB_stateChanged(int arg1)

View File

@ -97,7 +97,7 @@ class PreferencesWindow
void on_qvProxyPortCB_valueChanged(int arg1);
void on_setAllowInsecureCB_stateChanged(int arg1);
void on_setTestLatenctCB_stateChanged(int arg1);
void on_setAllowInsecureCiphersCB_stateChanged(int arg1);
void on_setSessionResumptionCB_stateChanged(int arg1);
void on_quietModeCB_stateChanged(int arg1);
void on_tproxGroupBox_toggled(bool arg1);
void on_tProxyPort_valueChanged(int arg1);

View File

@ -608,7 +608,7 @@ But could damage your server if improperly used.</string>
<item row="2" column="0">
<widget class="QLabel" name="label_85">
<property name="text">
<string>Set AllowInsecureCiphers By Default</string>
<string>Enable SessionResumption By Default</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
@ -616,7 +616,7 @@ But could damage your server if improperly used.</string>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="setAllowInsecureCiphersCB">
<widget class="QCheckBox" name="setSessionResumptionCB">
<property name="text">
<string>Enabled</string>
</property>

View File

@ -1341,7 +1341,7 @@ But could dramatically damage your server if improperly used.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Set AllowInsecureCiphers By Default</source>
<source>Enable SessionResumption By Default</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -1765,6 +1765,10 @@ Custom DNS Settings</source>
<source>You will lose the advantage of TLS and make your connection under MITM attack.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This will make your TLS fingerpring different from common golang programs.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This will (probably) make it easy to fingerprint your connection.</source>
<translation type="unfinished"></translation>

View File

@ -1462,6 +1462,10 @@
<source>You will lose the advantage of TLS and make your connection under MITM attack.</source>
<translation>TLSの保護を失いMITMの攻撃を受ける可能性が高くなります</translation>
</message>
<message>
<source>This will make your TLS fingerpring different from common golang programs.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This will (probably) make it easy to fingerprint your connection.</source>
<translation>()</translation>
@ -1789,8 +1793,8 @@ But could dramatically damage your server if improperly used.</source>
使</translation>
</message>
<message>
<source>Set AllowInsecureCiphers By Default</source>
<translation> AllowInsecureCiphers </translation>
<source>Enable SessionResumption By Default</source>
<translation> SessionResumption </translation>
</message>
<message>
<source>IPv4 address, e.g. &apos;127.0.0.1&apos;</source>

View File

@ -1458,6 +1458,10 @@
<source>You will lose the advantage of TLS and make your connection under MITM attack.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This will make your TLS fingerpring different from common golang programs.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This will (probably) make it easy to fingerprint your connection.</source>
<translation type="unfinished"></translation>
@ -1780,7 +1784,7 @@ But could dramatically damage your server if improperly used.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Set AllowInsecureCiphers By Default</source>
<source>Enable SessionResumption By Default</source>
<translation type="unfinished"></translation>
</message>
<message>

View File

@ -1442,6 +1442,10 @@
<source>You will lose the advantage of TLS and make your connection under MITM attack.</source>
<translation> TLS 使MitM</translation>
</message>
<message>
<source>使 TLS golang </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>This will (probably) make it easy to fingerprint your connection.</source>
<translation> GFW </translation>
@ -1789,8 +1793,8 @@ But could dramatically damage your server if improperly used.</source>
使</translation>
</message>
<message>
<source>Set AllowInsecureCiphers By Default</source>
<translation> AllowInsecureCiphers</translation>
<source>Enable SessionResumption By Default</source>
<translation> SessionResumption</translation>
</message>
<message>
<source>IPv4 address, e.g. &apos;127.0.0.1&apos;</source>