mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 12:34:37 +03:00
wip: hysteria2
仅通过编译不代表能用 Co-authored-by: xchacha20-poly1305 <139959885+xchacha20-poly1305@users.noreply.github.com>
This commit is contained in:
committed by
arm64v8a
parent
ff3696772c
commit
aad4063ef7
@@ -48,6 +48,7 @@ https://matsuridayo.github.io
|
|||||||
* TUIC ( sing-box )
|
* TUIC ( sing-box )
|
||||||
* NaïveProxy ( Custom Core )
|
* NaïveProxy ( Custom Core )
|
||||||
* Hysteria ( Custom Core or sing-box )
|
* Hysteria ( Custom Core or sing-box )
|
||||||
|
* Hysteria2 ( Custom Core or sing-box )
|
||||||
* Custom Outbound
|
* Custom Outbound
|
||||||
* Custom Config
|
* Custom Config
|
||||||
* Custom Core
|
* Custom Core
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ https://matsuridayo.github.io
|
|||||||
* Trojan
|
* Trojan
|
||||||
* NaïveProxy ( Custom Core )
|
* NaïveProxy ( Custom Core )
|
||||||
* Hysteria ( Custom Core or sing-box )
|
* Hysteria ( Custom Core or sing-box )
|
||||||
|
* Hysteria2 ( Custom Core or sing-box )
|
||||||
* Custom Outbound
|
* Custom Outbound
|
||||||
* Custom Core
|
* Custom Core
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ namespace NekoGui {
|
|||||||
bean = new NekoGui_fmt::NaiveBean();
|
bean = new NekoGui_fmt::NaiveBean();
|
||||||
} else if (type == "hysteria") {
|
} else if (type == "hysteria") {
|
||||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria);
|
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria);
|
||||||
|
} else if (type == "hysteria2" ) {
|
||||||
|
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_Hysteria2);
|
||||||
} else if (type == "tuic") {
|
} else if (type == "tuic") {
|
||||||
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_TUIC);
|
bean = new NekoGui_fmt::QUICBean(NekoGui_fmt::QUICBean::proxy_TUIC);
|
||||||
} else if (type == "custom") {
|
} else if (type == "custom") {
|
||||||
|
|||||||
@@ -199,6 +199,18 @@ namespace NekoGui_fmt {
|
|||||||
if (!hopPort.trimmed().isEmpty()) outbound["hop_ports"] = hopPort;
|
if (!hopPort.trimmed().isEmpty()) outbound["hop_ports"] = hopPort;
|
||||||
if (authPayloadType == hysteria_auth_base64) outbound["auth"] = authPayload;
|
if (authPayloadType == hysteria_auth_base64) outbound["auth"] = authPayload;
|
||||||
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
|
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
|
||||||
|
} else if (proxy_type == proxy_Hysteria2) {
|
||||||
|
outbound["type"] = "hysteria2";
|
||||||
|
outbound["password"] = authPayload;
|
||||||
|
|
||||||
|
if (uploadMbps > 0) outbound["up_mbps"] = uploadMbps;
|
||||||
|
if (downloadMbps > 0) outbound["down_mbps"] = downloadMbps;
|
||||||
|
if (!obfsPassword.isEmpty()) {
|
||||||
|
outbound["obfs"] = QJsonObject{
|
||||||
|
{"type", "salamander"},
|
||||||
|
{"password", obfsPassword},
|
||||||
|
};
|
||||||
|
}
|
||||||
} else if (proxy_type == proxy_TUIC) {
|
} else if (proxy_type == proxy_TUIC) {
|
||||||
outbound["type"] = "tuic";
|
outbound["type"] = "tuic";
|
||||||
outbound["uuid"] = uuid;
|
outbound["uuid"] = uuid;
|
||||||
|
|||||||
@@ -50,6 +50,16 @@ namespace NekoGui_fmt {
|
|||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto hysteria2Core = [=] {
|
||||||
|
if (isFirstProfile) {
|
||||||
|
if (NekoGui::dataStore->spmode_vpn || !hopPort.trimmed().isEmpty()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
auto tuicCore = [=] {
|
auto tuicCore = [=] {
|
||||||
if (isFirstProfile) {
|
if (isFirstProfile) {
|
||||||
if (NekoGui::dataStore->spmode_vpn) {
|
if (NekoGui::dataStore->spmode_vpn) {
|
||||||
@@ -70,6 +80,8 @@ namespace NekoGui_fmt {
|
|||||||
}
|
}
|
||||||
} else if (proxy_type == proxy_TUIC) {
|
} else if (proxy_type == proxy_TUIC) {
|
||||||
return tuicCore();
|
return tuicCore();
|
||||||
|
} else if (proxy_type == proxy_Hysteria2) {
|
||||||
|
return hysteria2Core();
|
||||||
} else {
|
} else {
|
||||||
return hysteriaCore();
|
return hysteriaCore();
|
||||||
}
|
}
|
||||||
@@ -162,6 +174,78 @@ namespace NekoGui_fmt {
|
|||||||
result.arguments = QStringList{"-c", TempFile};
|
result.arguments = QStringList{"-c", TempFile};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
} else if (proxy_type == proxy_Hysteria2) {
|
||||||
|
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria2")};
|
||||||
|
|
||||||
|
QJsonObject config;
|
||||||
|
|
||||||
|
auto server = serverAddress;
|
||||||
|
if (!hopPort.trimmed().isEmpty()) {
|
||||||
|
server = WrapIPV6Host(server) + ":" + hopPort;
|
||||||
|
} else {
|
||||||
|
server = WrapIPV6Host(server) + ":" + Int2String(serverPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject transport;
|
||||||
|
transport["type"] = "udp";
|
||||||
|
transport["udp"] = QJsonObject{
|
||||||
|
{"hopInterval", hopInterval},
|
||||||
|
};
|
||||||
|
config["transport"] = transport;
|
||||||
|
|
||||||
|
config["server"] = server;
|
||||||
|
config["socks5"] = QJsonObject{
|
||||||
|
{"listen", "127.0.0.1:" + Int2String(socks_port)},
|
||||||
|
{"disableUDP", false},
|
||||||
|
};
|
||||||
|
if (username.isEmpty()) {
|
||||||
|
config["auth"] = authPayload;
|
||||||
|
} else {
|
||||||
|
config["auth"] = username + ":" + authPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject bandwidth;
|
||||||
|
if (uploadMbps > 0) bandwidth["up"] = Int2String(uploadMbps) + " mbps";
|
||||||
|
if (downloadMbps > 0) bandwidth["down"] = Int2String(downloadMbps) + " mbps";
|
||||||
|
config["bandwidth"] = bandwidth;
|
||||||
|
|
||||||
|
QJsonObject quic;
|
||||||
|
if (streamReceiveWindow > 0) quic["initStreamReceiveWindow"] = streamReceiveWindow;
|
||||||
|
if (connectionReceiveWindow > 0) quic["initConnReceiveWindow"] = connectionReceiveWindow;
|
||||||
|
if (disableMtuDiscovery) quic["disablePathMTUDiscovery"] = true;
|
||||||
|
|
||||||
|
config["fastopen"] = true;
|
||||||
|
config["lazy"] = true;
|
||||||
|
|
||||||
|
if (!obfsPassword.isEmpty()) {
|
||||||
|
QJsonObject obfs;
|
||||||
|
obfs["type"] = "salamander";
|
||||||
|
obfs["salamander"] = QJsonObject{
|
||||||
|
{"password", obfsPassword},
|
||||||
|
};
|
||||||
|
|
||||||
|
config["obfs"] = obfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject tls;
|
||||||
|
auto sniGen = sni;
|
||||||
|
if (sni.isEmpty() && !IsIpAddress(serverAddress)) sniGen = serverAddress;
|
||||||
|
tls["sni"] = sniGen;
|
||||||
|
if (allowInsecure) tls["insecure"] = true;
|
||||||
|
if (!caText.trimmed().isEmpty()) {
|
||||||
|
WriteTempFile("hysteria2_" + GetRandomString(10) + ".crt", caText.toUtf8());
|
||||||
|
QJsonArray certificate;
|
||||||
|
certificate.append(TempFile);
|
||||||
|
tls["certificates"] = certificate;
|
||||||
|
}
|
||||||
|
config["tls"] = tls;
|
||||||
|
|
||||||
|
result.config_export = QJsonObject2QString(config, false);
|
||||||
|
WriteTempFile("hysteria2_" + GetRandomString(10) + ".json", result.config_export.toUtf8());
|
||||||
|
result.arguments = QStringList{"-c", TempFile};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
} else { // Hysteria
|
} else { // Hysteria
|
||||||
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria")};
|
ExternalBuildResult result{NekoGui::dataStore->extraCore->Get("hysteria")};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace NekoGui_fmt {
|
|||||||
public:
|
public:
|
||||||
static constexpr int proxy_Hysteria = 0;
|
static constexpr int proxy_Hysteria = 0;
|
||||||
static constexpr int proxy_TUIC = 1;
|
static constexpr int proxy_TUIC = 1;
|
||||||
|
static constexpr int proxy_Hysteria2 = 3;
|
||||||
int proxy_type = proxy_Hysteria;
|
int proxy_type = proxy_Hysteria;
|
||||||
|
|
||||||
// Hysteria
|
// Hysteria
|
||||||
@@ -34,6 +35,9 @@ namespace NekoGui_fmt {
|
|||||||
int hopInterval = 10;
|
int hopInterval = 10;
|
||||||
QString hopPort = "";
|
QString hopPort = "";
|
||||||
|
|
||||||
|
// Hysteria 2 (Something same as hy1)
|
||||||
|
QString username = "";
|
||||||
|
|
||||||
// TUIC
|
// TUIC
|
||||||
|
|
||||||
QString uuid = "";
|
QString uuid = "";
|
||||||
@@ -54,9 +58,7 @@ namespace NekoGui_fmt {
|
|||||||
|
|
||||||
explicit QUICBean(int _proxy_type) : AbstractBean(0) {
|
explicit QUICBean(int _proxy_type) : AbstractBean(0) {
|
||||||
proxy_type = _proxy_type;
|
proxy_type = _proxy_type;
|
||||||
if (proxy_type == proxy_Hysteria) {
|
if (proxy_type == proxy_Hysteria || proxy_type == proxy_Hysteria2) {
|
||||||
_add(new configItem("protocol", &hyProtocol, itemType::integer));
|
|
||||||
_add(new configItem("authPayloadType", &authPayloadType, itemType::integer));
|
|
||||||
_add(new configItem("authPayload", &authPayload, itemType::string));
|
_add(new configItem("authPayload", &authPayload, itemType::string));
|
||||||
_add(new configItem("obfsPassword", &obfsPassword, itemType::string));
|
_add(new configItem("obfsPassword", &obfsPassword, itemType::string));
|
||||||
_add(new configItem("uploadMbps", &uploadMbps, itemType::integer));
|
_add(new configItem("uploadMbps", &uploadMbps, itemType::integer));
|
||||||
@@ -66,6 +68,13 @@ namespace NekoGui_fmt {
|
|||||||
_add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean));
|
_add(new configItem("disableMtuDiscovery", &disableMtuDiscovery, itemType::boolean));
|
||||||
_add(new configItem("hopInterval", &hopInterval, itemType::integer));
|
_add(new configItem("hopInterval", &hopInterval, itemType::integer));
|
||||||
_add(new configItem("hopPort", &hopPort, itemType::string));
|
_add(new configItem("hopPort", &hopPort, itemType::string));
|
||||||
|
if (proxy_type == proxy_Hysteria2) {
|
||||||
|
_add(new configItem("authPayloadType", &authPayloadType, itemType::integer));
|
||||||
|
_add(new configItem("protocol", &hyProtocol, itemType::integer));
|
||||||
|
} else {
|
||||||
|
_add(new configItem("username", &username, itemType::string));
|
||||||
|
}
|
||||||
|
|
||||||
} else if (proxy_type == proxy_TUIC) {
|
} else if (proxy_type == proxy_TUIC) {
|
||||||
_add(new configItem("uuid", &uuid, itemType::string));
|
_add(new configItem("uuid", &uuid, itemType::string));
|
||||||
_add(new configItem("password", &password, itemType::string));
|
_add(new configItem("password", &password, itemType::string));
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
|
|||||||
CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map);
|
CACHE.extraCore = QString2QJsonObject(NekoGui::dataStore->extraCore->core_map);
|
||||||
if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", "");
|
if (!CACHE.extraCore.contains("naive")) CACHE.extraCore.insert("naive", "");
|
||||||
if (!CACHE.extraCore.contains("hysteria")) CACHE.extraCore.insert("hysteria", "");
|
if (!CACHE.extraCore.contains("hysteria")) CACHE.extraCore.insert("hysteria", "");
|
||||||
|
if (!CACHE.extraCore.contains("hysteria2")) CACHE.extraCore.insert("hysteria2", "");
|
||||||
if (!CACHE.extraCore.contains("tuic")) CACHE.extraCore.insert("tuic", "");
|
if (!CACHE.extraCore.contains("tuic")) CACHE.extraCore.insert("tuic", "");
|
||||||
//
|
//
|
||||||
auto extra_core_layout = ui->extra_core_box_scrollAreaWidgetContents->layout();
|
auto extra_core_layout = ui->extra_core_box_scrollAreaWidgetContents->layout();
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
|
|||||||
LOAD_TYPE("vless")
|
LOAD_TYPE("vless")
|
||||||
LOAD_TYPE("naive")
|
LOAD_TYPE("naive")
|
||||||
LOAD_TYPE("hysteria")
|
LOAD_TYPE("hysteria")
|
||||||
|
LOAD_TYPE("hysteria2")
|
||||||
LOAD_TYPE("tuic")
|
LOAD_TYPE("tuic")
|
||||||
ui->type->addItem(tr("Custom (%1 outbound)").arg(software_core_name), "internal");
|
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 (%1 config)").arg(software_core_name), "internal-full");
|
||||||
@@ -177,7 +178,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
|
|||||||
auto _innerWidget = new EditNaive(this);
|
auto _innerWidget = new EditNaive(this);
|
||||||
innerWidget = _innerWidget;
|
innerWidget = _innerWidget;
|
||||||
innerEditor = _innerWidget;
|
innerEditor = _innerWidget;
|
||||||
} else if (type == "hysteria" || type == "tuic") {
|
} else if (type == "hysteria" || type == "hysteria2" || type == "tuic") {
|
||||||
auto _innerWidget = new EditQUIC(this);
|
auto _innerWidget = new EditQUIC(this);
|
||||||
innerWidget = _innerWidget;
|
innerWidget = _innerWidget;
|
||||||
innerEditor = _innerWidget;
|
innerEditor = _innerWidget;
|
||||||
|
|||||||
@@ -19,15 +19,13 @@ void EditQUIC::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
|||||||
this->ent = _ent;
|
this->ent = _ent;
|
||||||
auto bean = this->ent->QUICBean();
|
auto bean = this->ent->QUICBean();
|
||||||
|
|
||||||
if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria) {
|
if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria || bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria2) {
|
||||||
P_LOAD_STRING(hopPort);
|
P_LOAD_STRING(hopPort);
|
||||||
P_LOAD_INT(hopInterval);
|
P_LOAD_INT(hopInterval);
|
||||||
P_LOAD_INT(uploadMbps);
|
P_LOAD_INT(uploadMbps);
|
||||||
P_LOAD_INT(downloadMbps);
|
P_LOAD_INT(downloadMbps);
|
||||||
P_LOAD_COMBO_INT(hyProtocol);
|
|
||||||
P_LOAD_BOOL(disableMtuDiscovery)
|
P_LOAD_BOOL(disableMtuDiscovery)
|
||||||
P_LOAD_STRING(obfsPassword);
|
P_LOAD_STRING(obfsPassword);
|
||||||
P_LOAD_COMBO_INT(authPayloadType);
|
|
||||||
P_LOAD_STRING(authPayload);
|
P_LOAD_STRING(authPayload);
|
||||||
P_LOAD_INT(streamReceiveWindow);
|
P_LOAD_INT(streamReceiveWindow);
|
||||||
P_LOAD_INT(connectionReceiveWindow);
|
P_LOAD_INT(connectionReceiveWindow);
|
||||||
@@ -45,6 +43,21 @@ void EditQUIC::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
|
|||||||
ui->heartbeat->hide();
|
ui->heartbeat->hide();
|
||||||
ui->heartbeat_l->hide();
|
ui->heartbeat_l->hide();
|
||||||
ui->uos->hide();
|
ui->uos->hide();
|
||||||
|
|
||||||
|
if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria) {
|
||||||
|
P_LOAD_COMBO_INT(hyProtocol);
|
||||||
|
P_LOAD_COMBO_INT(authPayloadType);
|
||||||
|
|
||||||
|
ui->username_l->hide();
|
||||||
|
ui->username->hide();
|
||||||
|
} else {
|
||||||
|
P_LOAD_STRING(username);
|
||||||
|
|
||||||
|
ui->hyProtocol->hide();
|
||||||
|
ui->hyProtocol_l->hide();
|
||||||
|
ui->hyProtocol->hide();
|
||||||
|
ui->hyProtocol_l->hide();
|
||||||
|
}
|
||||||
} else if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_TUIC) {
|
} else if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_TUIC) {
|
||||||
P_LOAD_STRING(uuid);
|
P_LOAD_STRING(uuid);
|
||||||
P_LOAD_STRING(password);
|
P_LOAD_STRING(password);
|
||||||
@@ -104,6 +117,9 @@ bool EditQUIC::onEnd() {
|
|||||||
P_SAVE_INT(streamReceiveWindow);
|
P_SAVE_INT(streamReceiveWindow);
|
||||||
P_SAVE_INT(connectionReceiveWindow);
|
P_SAVE_INT(connectionReceiveWindow);
|
||||||
|
|
||||||
|
// Hysteria2
|
||||||
|
P_SAVE_STRING(username);
|
||||||
|
|
||||||
// TUIC
|
// TUIC
|
||||||
P_SAVE_STRING(uuid);
|
P_SAVE_STRING(uuid);
|
||||||
P_SAVE_STRING(password);
|
P_SAVE_STRING(password);
|
||||||
|
|||||||
@@ -166,23 +166,16 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="obfuscation">
|
<layout class="QGridLayout" name="obfuscation">
|
||||||
<item row="1" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="MyLineEdit" name="obfsPassword"/>
|
<widget class="MyLineEdit" name="obfsPassword"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="obfsPassword_l">
|
<widget class="QLabel" name="obfsPassword_l">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Obfs Password</string>
|
<string>Obfs Password</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="hyProtocol_l">
|
|
||||||
<property name="text">
|
|
||||||
<string>Protocol</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
@@ -219,6 +212,23 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="hyProtocol_l">
|
||||||
|
<property name="text">
|
||||||
|
<string>Protocol</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="username_l">
|
||||||
|
<property name="text">
|
||||||
|
<string>Username</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="MyLineEdit" name="username"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
Reference in New Issue
Block a user