mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-19 13:42:51 +08:00
feat: Add wireguard support
This commit is contained in:
parent
4c203ef443
commit
c3f184eb9d
@ -159,6 +159,10 @@ set(PROJECT_SOURCES
|
||||
ui/edit/edit_custom.cpp
|
||||
ui/edit/edit_custom.ui
|
||||
|
||||
ui/edit/edit_wireguard.h
|
||||
ui/edit/edit_wireguard.cpp
|
||||
ui/edit/edit_wireguard.ui
|
||||
|
||||
ui/dialog_basic_settings.cpp
|
||||
ui/dialog_basic_settings.h
|
||||
ui/dialog_basic_settings.ui
|
||||
|
||||
@ -223,6 +223,8 @@ namespace NekoGui {
|
||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria2);
|
||||
} else if (type == "tuic") {
|
||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_TUIC);
|
||||
} else if (type == "wireguard") {
|
||||
bean = new NekoGui_fmt::WireguardBean(NekoGui_fmt::WireguardBean());
|
||||
} else if (type == "custom") {
|
||||
bean = new NekoGui_fmt::CustomBean();
|
||||
} else {
|
||||
|
||||
@ -17,6 +17,8 @@ namespace NekoGui_fmt {
|
||||
|
||||
class QUICBean;
|
||||
|
||||
class WireguardBean;
|
||||
|
||||
class CustomBean;
|
||||
|
||||
class ChainBean;
|
||||
@ -69,6 +71,10 @@ namespace NekoGui {
|
||||
return (NekoGui_fmt::QUICBean *) bean.get();
|
||||
};
|
||||
|
||||
[[nodiscard]] NekoGui_fmt::WireguardBean *WireguardBean() const {
|
||||
return (NekoGui_fmt::WireguardBean *) bean.get();
|
||||
};
|
||||
|
||||
[[nodiscard]] NekoGui_fmt::CustomBean *CustomBean() const {
|
||||
return (NekoGui_fmt::CustomBean *) bean.get();
|
||||
};
|
||||
|
||||
@ -242,6 +242,31 @@ namespace NekoGui_fmt {
|
||||
return result;
|
||||
}
|
||||
|
||||
CoreObjOutboundBuildResult WireguardBean::BuildCoreObjSingBox() {
|
||||
CoreObjOutboundBuildResult result;
|
||||
|
||||
auto tun_name = "nekoray-tunwg";
|
||||
#ifdef Q_OS_MACOS
|
||||
tun_name = "utunwg9";
|
||||
#endif
|
||||
|
||||
QJsonObject outbound{
|
||||
{"type", "wireguard"},
|
||||
{"server", serverAddress},
|
||||
{"server_port", serverPort},
|
||||
{"interface_name", tun_name},
|
||||
{"local_address", QJsonArray{"172.20.0.1/24", "fdfe:dcba:9876::1/96"}},
|
||||
{"private_key", privateKey},
|
||||
{"peer_public_key", publicKey},
|
||||
{"pre_shared_key", preSharedKey},
|
||||
{"reserved", QListInt2QJsonArray(reserved)},
|
||||
{"mtu", MTU},
|
||||
};
|
||||
|
||||
result.outbound = outbound;
|
||||
return result;
|
||||
}
|
||||
|
||||
CoreObjOutboundBuildResult CustomBean::BuildCoreObjSingBox() {
|
||||
CoreObjOutboundBuildResult result;
|
||||
|
||||
|
||||
@ -242,4 +242,21 @@ namespace NekoGui_fmt {
|
||||
return url.toString(QUrl::FullyEncoded);
|
||||
}
|
||||
|
||||
QString WireguardBean::ToShareLink() {
|
||||
QUrl url;
|
||||
url.setScheme("wg");
|
||||
url.setHost(serverAddress);
|
||||
url.setPort(serverPort);
|
||||
if (!name.isEmpty()) url.setFragment(name);
|
||||
QUrlQuery q;
|
||||
q.addQueryItem("private_key", privateKey);
|
||||
q.addQueryItem("peer_public_key", publicKey);
|
||||
q.addQueryItem("pre_shared_key", preSharedKey);
|
||||
q.addQueryItem("reserved", FormatReserved());
|
||||
q.addQueryItem("mtu", Int2String(MTU));
|
||||
q.addQueryItem("use_system_interface", useSystemInterface ? "true":"false");
|
||||
url.setQuery(q);
|
||||
return url.toString(QUrl::FullyEncoded);
|
||||
}
|
||||
|
||||
} // namespace NekoGui_fmt
|
||||
@ -333,4 +333,25 @@ namespace NekoGui_fmt {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WireguardBean::TryParseLink(const QString &link) {
|
||||
auto url = QUrl(link);
|
||||
if (!url.isValid()) return false;
|
||||
auto query = GetQuery(url);
|
||||
|
||||
name = url.fragment(QUrl::FullyDecoded);
|
||||
serverAddress = url.host();
|
||||
serverPort = url.port();
|
||||
privateKey = query.queryItemValue("private_key");
|
||||
publicKey = query.queryItemValue("peer_public_key");
|
||||
preSharedKey = query.queryItemValue("pre_shared_key");
|
||||
auto rawReserved = query.queryItemValue("reserved");
|
||||
if (!rawReserved.isEmpty()) {
|
||||
for (const auto &item: rawReserved.split("-")) reserved += item.toInt();
|
||||
}
|
||||
MTU = query.queryItemValue("mtu").toInt();
|
||||
useSystemInterface = query.queryItemValue("use_system_interface") == "true";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace NekoGui_fmt
|
||||
45
fmt/WireguardBean.h
Normal file
45
fmt/WireguardBean.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "fmt/AbstractBean.hpp"
|
||||
|
||||
namespace NekoGui_fmt {
|
||||
class WireguardBean : public AbstractBean {
|
||||
public:
|
||||
QString privateKey;
|
||||
QString publicKey;
|
||||
QString preSharedKey;
|
||||
QList<int> reserved;
|
||||
int MTU = 1420;
|
||||
bool useSystemInterface = false;
|
||||
bool enableGSO = false;
|
||||
|
||||
WireguardBean() : AbstractBean(0) {
|
||||
_add(new configItem("private_key", &privateKey, itemType::string));
|
||||
_add(new configItem("public_key", &publicKey, itemType::string));
|
||||
_add(new configItem("pre_shared_key", &preSharedKey, itemType::string));
|
||||
_add(new configItem("reserved", &reserved, itemType::integerList));
|
||||
_add(new configItem("mtu", &MTU, itemType::integer));
|
||||
_add(new configItem("use_system_proxy", &useSystemInterface, itemType::boolean));
|
||||
_add(new configItem("enable_gso", &enableGSO, itemType::boolean));
|
||||
};
|
||||
|
||||
QString FormatReserved() {
|
||||
QString res = "";
|
||||
for (int i=0;i<reserved.size();i++) {
|
||||
res += Int2String(reserved[i]);
|
||||
if (i != reserved.size() - 1) {
|
||||
res += "-";
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QString DisplayType() override { return "Wireguard"; };
|
||||
|
||||
CoreObjOutboundBuildResult BuildCoreObjSingBox() override;
|
||||
|
||||
bool TryParseLink(const QString &link);
|
||||
|
||||
QString ToShareLink() override;
|
||||
};
|
||||
} // namespace NekoGui_fmt
|
||||
@ -7,4 +7,5 @@
|
||||
#include "TrojanVLESSBean.hpp"
|
||||
#include "NaiveBean.hpp"
|
||||
#include "QUICBean.hpp"
|
||||
#include "WireguardBean.h"
|
||||
#include "CustomBean.hpp"
|
||||
|
||||
@ -202,6 +202,14 @@ namespace NekoGui_sub {
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
// Wireguard
|
||||
if (str.startsWith("wg://")) {
|
||||
needFix = false;
|
||||
ent = NekoGui::ProfileManager::NewProxyEntity("wireguard");
|
||||
auto ok = ent->WireguardBean()->TryParseLink(str);
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
if (ent == nullptr) return;
|
||||
|
||||
// Fix
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "ui/edit/edit_trojan_vless.h"
|
||||
#include "ui/edit/edit_naive.h"
|
||||
#include "ui/edit/edit_quic.h"
|
||||
#include "ui/edit/edit_wireguard.h"
|
||||
#include "ui/edit/edit_custom.h"
|
||||
|
||||
#include "fmt/includes.h"
|
||||
@ -140,6 +141,7 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
|
||||
LOAD_TYPE("hysteria")
|
||||
LOAD_TYPE("hysteria2")
|
||||
LOAD_TYPE("tuic")
|
||||
LOAD_TYPE("wireguard")
|
||||
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal");
|
||||
ui->type->addItem(tr("Custom (%1 config)").arg(software_core_name), "internal-full");
|
||||
ui->type->addItem(tr("Custom (Extra Core)"), "custom");
|
||||
@ -199,6 +201,10 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
||||
auto _innerWidget = new EditQUIC(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "wireguard") {
|
||||
auto _innerWidget = new EditWireguard(this);
|
||||
innerWidget = _innerWidget;
|
||||
innerEditor = _innerWidget;
|
||||
} else if (type == "custom" || type == "internal" || type == "internal-full") {
|
||||
auto _innerWidget = new EditCustom(this);
|
||||
innerWidget = _innerWidget;
|
||||
|
||||
49
ui/edit/edit_wireguard.cpp
Normal file
49
ui/edit/edit_wireguard.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "edit_wireguard.h"
|
||||
#include "ui_edit_wireguard.h"
|
||||
|
||||
#include "fmt/WireguardBean.h"
|
||||
|
||||
EditWireguard::EditWireguard(QWidget *parent) : QWidget(parent), ui(new Ui::EditWireguard) {
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
EditWireguard::~EditWireguard() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditWireguard::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
||||
this->ent = _ent;
|
||||
auto bean = this->ent->WireguardBean();
|
||||
|
||||
#ifndef Q_OS_LINUX
|
||||
ui->enable_gso->hide();
|
||||
adjustSize();
|
||||
#endif
|
||||
|
||||
ui->private_key->setText(bean->privateKey);
|
||||
ui->public_key->setText(bean->publicKey);
|
||||
ui->preshared_key->setText(bean->preSharedKey);
|
||||
auto reservedStr = bean->FormatReserved().replace("-", ",");
|
||||
ui->reserved->setText(reservedStr);
|
||||
ui->mtu->setText(Int2String(bean->MTU));
|
||||
ui->sys_ifc->setChecked(bean->useSystemInterface);
|
||||
ui->enable_gso->setChecked(bean->enableGSO);
|
||||
}
|
||||
|
||||
bool EditWireguard::onEnd() {
|
||||
auto bean = this->ent->WireguardBean();
|
||||
|
||||
bean->privateKey = ui->private_key->text();
|
||||
bean->publicKey = ui->public_key->text();
|
||||
bean->preSharedKey = ui->preshared_key->text();
|
||||
auto rawReserved = ui->reserved->text();
|
||||
bean->reserved = {};
|
||||
for (const auto& item: rawReserved.split(",")) {
|
||||
bean->reserved += item.trimmed().toInt();
|
||||
}
|
||||
bean->MTU = ui->mtu->text().toInt();
|
||||
bean->useSystemInterface = ui->sys_ifc->isChecked();
|
||||
bean->enableGSO = ui->enable_gso->isChecked();
|
||||
|
||||
return true;
|
||||
}
|
||||
27
ui/edit/edit_wireguard.h
Normal file
27
ui/edit/edit_wireguard.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include "profile_editor.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class EditWireguard;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class EditWireguard : public QWidget, public ProfileEditor {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditWireguard(QWidget *parent = nullptr);
|
||||
|
||||
~EditWireguard() override;
|
||||
|
||||
void onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) override;
|
||||
|
||||
bool onEnd() override;
|
||||
|
||||
private:
|
||||
Ui::EditWireguard *ui;
|
||||
std::shared_ptr<NekoGui::ProxyEntity> ent;
|
||||
};
|
||||
89
ui/edit/edit_wireguard.ui
Normal file
89
ui/edit/edit_wireguard.ui
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditWireguard</class>
|
||||
<widget class="QWidget" name="EditWireguard">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>EditWireguard</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="reserved"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="public_key"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="private_key"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="public_key_l">
|
||||
<property name="text">
|
||||
<string>Public Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="preshared_key"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="enable_gso">
|
||||
<property name="text">
|
||||
<string>Enable GSO</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="preshared_key_l">
|
||||
<property name="text">
|
||||
<string>Pre Shared Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="private_key_l">
|
||||
<property name="text">
|
||||
<string>Private Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="sys_ifc">
|
||||
<property name="text">
|
||||
<string>Use System Interface</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="reserved_l">
|
||||
<property name="text">
|
||||
<string>Reserved</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="mtu">
|
||||
<property name="text">
|
||||
<string>1420</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="mtu_l">
|
||||
<property name="text">
|
||||
<string>MTU</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Loading…
Reference in New Issue
Block a user