diff --git a/fmt/Bean2CoreObj_box.cpp b/fmt/Bean2CoreObj_box.cpp
index 4c631a8..13f3215 100644
--- a/fmt/Bean2CoreObj_box.cpp
+++ b/fmt/Bean2CoreObj_box.cpp
@@ -202,7 +202,7 @@ namespace NekoGui_fmt {
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
} else if (proxy_type == proxy_Hysteria2) {
outbound["type"] = "hysteria2";
- outbound["password"] = authPayload;
+ outbound["password"] = password;
outbound["up_mbps"] = uploadMbps;
outbound["down_mbps"] = downloadMbps;
if (!obfsPassword.isEmpty()) {
diff --git a/fmt/Bean2External.cpp b/fmt/Bean2External.cpp
index 411f7c7..14daea6 100644
--- a/fmt/Bean2External.cpp
+++ b/fmt/Bean2External.cpp
@@ -198,11 +198,7 @@ namespace NekoGui_fmt {
{"listen", "127.0.0.1:" + Int2String(socks_port)},
{"disableUDP", false},
};
- if (username.isEmpty()) {
- config["auth"] = authPayload;
- } else {
- config["auth"] = username + ":" + authPayload;
- }
+ config["auth"] = password;
QJsonObject bandwidth;
if (uploadMbps > 0) bandwidth["up"] = Int2String(uploadMbps) + " mbps";
diff --git a/fmt/Bean2Link.cpp b/fmt/Bean2Link.cpp
index 5426767..f8a73d0 100644
--- a/fmt/Bean2Link.cpp
+++ b/fmt/Bean2Link.cpp
@@ -214,6 +214,26 @@ namespace NekoGui_fmt {
if (disableSni) q.addQueryItem("disable_sni", "1");
if (!q.isEmpty()) url.setQuery(q);
if (!name.isEmpty()) url.setFragment(name);
+ } else if (proxy_type == proxy_Hysteria2) {
+ url.setScheme("hy2");
+ url.setHost(serverAddress);
+ url.setPort(serverPort);
+ if (password.contains(":")) {
+ url.setUserName(SubStrBefore(password, ":"));
+ url.setPassword(SubStrAfter(password, ":"));
+ } else {
+ url.setUserName(password);
+ }
+ QUrlQuery q;
+ if (!obfsPassword.isEmpty()) {
+ q.addQueryItem("obfs", "salamander");
+ q.addQueryItem("obfs-password", obfsPassword);
+ }
+ // if (!hopPort.trimmed().isEmpty()) q.addQueryItem("mport", hopPort);
+ if (allowInsecure) q.addQueryItem("insecure", "1");
+ if (!sni.isEmpty()) q.addQueryItem("sni", sni);
+ if (!q.isEmpty()) url.setQuery(q);
+ if (!name.isEmpty()) url.setFragment(name);
}
return url.toString(QUrl::FullyEncoded);
}
diff --git a/fmt/Link2Bean.cpp b/fmt/Link2Bean.cpp
index 2141c85..bdff875 100644
--- a/fmt/Link2Bean.cpp
+++ b/fmt/Link2Bean.cpp
@@ -233,10 +233,9 @@ namespace NekoGui_fmt {
name = url.fragment();
serverAddress = url.host();
serverPort = url.port();
- serverAddress = url.host(); // default sni
hopPort = query.queryItemValue("mport");
obfsPassword = query.queryItemValue("obfsParam");
- allowInsecure = query.queryItemValue("insecure") == "1";
+ allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
uploadMbps = query.queryItemValue("upmbps").toInt();
downloadMbps = query.queryItemValue("downmbps").toInt();
@@ -275,6 +274,21 @@ namespace NekoGui_fmt {
udpRelayMode = query.queryItemValue("udp_relay_mode");
allowInsecure = query.queryItemValue("allow_insecure") == "1";
disableSni = query.queryItemValue("disable_sni") == "1";
+ } else if (QStringList{"hy2", "hysteria2"}.contains(url.scheme())) {
+ name = url.fragment();
+ serverAddress = url.host();
+ serverPort = url.port();
+ // hopPort = query.queryItemValue("mport");
+ obfsPassword = query.queryItemValue("obfs-password");
+ allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
+
+ if (url.password().isEmpty()) {
+ password = url.userName();
+ } else {
+ password = url.userName() + ":" + url.password();
+ }
+
+ sni = query.queryItemValue("sni");
}
return true;
diff --git a/fmt/QUICBean.hpp b/fmt/QUICBean.hpp
index 405ee04..b4650ed 100644
--- a/fmt/QUICBean.hpp
+++ b/fmt/QUICBean.hpp
@@ -12,7 +12,7 @@ namespace NekoGui_fmt {
bool forceExternal = false;
- // Hysteria
+ // Hysteria 1
static constexpr int hysteria_protocol_udp = 0;
static constexpr int hysteria_protocol_facktcp = 1;
@@ -23,8 +23,10 @@ namespace NekoGui_fmt {
static constexpr int hysteria_auth_string = 1;
static constexpr int hysteria_auth_base64 = 2;
int authPayloadType = 0;
-
QString authPayload = "";
+
+ // Hysteria 1&2
+
QString obfsPassword = "";
int uploadMbps = 100;
@@ -37,19 +39,19 @@ namespace NekoGui_fmt {
int hopInterval = 10;
QString hopPort = "";
- // Hysteria 2 (Something same as hy1)
- QString username = "";
-
// TUIC
QString uuid = "";
- QString password = "";
QString congestionControl = "bbr";
QString udpRelayMode = "native";
bool zeroRttHandshake = false;
QString heartbeat = "10s";
bool uos = false;
+ // HY2&TUIC
+
+ QString password = "";
+
// TLS
bool allowInsecure = false;
@@ -76,9 +78,8 @@ namespace NekoGui_fmt {
} else { // hy2
uploadMbps = 0;
downloadMbps = 0;
- _add(new configItem("username", &username, itemType::string));
+ _add(new configItem("password", &password, itemType::string));
}
-
} else if (proxy_type == proxy_TUIC) {
_add(new configItem("uuid", &uuid, itemType::string));
_add(new configItem("password", &password, itemType::string));
@@ -114,7 +115,15 @@ namespace NekoGui_fmt {
}
}
- QString DisplayType() override { return proxy_type == proxy_TUIC ? "TUIC" : "Hysteria"; };
+ QString DisplayType() override {
+ if (proxy_type == proxy_TUIC) {
+ return "TUIC";
+ } else if (proxy_type == proxy_Hysteria) {
+ return "Hysteria1";
+ } else {
+ return "Hysteria2";
+ }
+ };
int NeedExternal(bool isFirstProfile) override;
diff --git a/sub/GroupUpdater.cpp b/sub/GroupUpdater.cpp
index d5853d8..5de4047 100644
--- a/sub/GroupUpdater.cpp
+++ b/sub/GroupUpdater.cpp
@@ -124,7 +124,7 @@ namespace NekoGui_sub {
if (!ok) return;
}
- // Hysteria
+ // Hysteria1
if (str.startsWith("hysteria://")) {
needFix = false;
ent = NekoGui::ProfileManager::NewProxyEntity("hysteria");
@@ -132,6 +132,14 @@ namespace NekoGui_sub {
if (!ok) return;
}
+ // Hysteria2
+ if (str.startsWith("hysteria2://") || str.startsWith("hy2://")) {
+ needFix = false;
+ ent = NekoGui::ProfileManager::NewProxyEntity("hysteria2");
+ auto ok = ent->QUICBean()->TryParseLink(str);
+ if (!ok) return;
+ }
+
// TUIC
if (str.startsWith("tuic://")) {
needFix = false;
diff --git a/translations/fa_IR.ts b/translations/fa_IR.ts
index 3f36bad..f69dc07 100644
--- a/translations/fa_IR.ts
+++ b/translations/fa_IR.ts
@@ -972,10 +972,6 @@ This needs to be run NekoBox with administrator privileges.
UDP Relay Mode
-
- Username
- نام کاربری
-
Force use external core
diff --git a/translations/ru_RU.ts b/translations/ru_RU.ts
index c849559..9703972 100644
--- a/translations/ru_RU.ts
+++ b/translations/ru_RU.ts
@@ -979,10 +979,6 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun
UDP Relay Mode
Режим UDP Relay
-
- Username
- Имя пользователя
-
Force use external core
diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts
index 98404dc..3417563 100644
--- a/translations/zh_CN.ts
+++ b/translations/zh_CN.ts
@@ -980,10 +980,6 @@ This needs to be run NekoBox with administrator privileges.
Disable SNI
不发送服务器名称指示
-
- Username
- 用户名
-
Force use external core
强制使用外部核心
diff --git a/ui/edit/dialog_edit_profile.cpp b/ui/edit/dialog_edit_profile.cpp
index 65d9c71..4eb524f 100644
--- a/ui/edit/dialog_edit_profile.cpp
+++ b/ui/edit/dialog_edit_profile.cpp
@@ -120,8 +120,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
LOAD_TYPE("vmess")
LOAD_TYPE("vless")
LOAD_TYPE("naive")
- ui->type->addItem("Hysteria1", "hysteria");
- ui->type->addItem("Hysteria2", "hysteria2");
+ LOAD_TYPE("hysteria")
+ LOAD_TYPE("hysteria2")
LOAD_TYPE("tuic")
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");
diff --git a/ui/edit/edit_quic.cpp b/ui/edit/edit_quic.cpp
index b5d74d5..879af8f 100644
--- a/ui/edit/edit_quic.cpp
+++ b/ui/edit/edit_quic.cpp
@@ -19,23 +19,39 @@ void EditQUIC::onStart(std::shared_ptr _ent) {
this->ent = _ent;
auto bean = this->ent->QUICBean();
- if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria || bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria2) {
- P_LOAD_STRING(hopPort);
- P_LOAD_INT(hopInterval);
- P_LOAD_INT(uploadMbps);
- P_LOAD_INT(downloadMbps);
- P_LOAD_BOOL(disableMtuDiscovery)
- P_LOAD_STRING(obfsPassword);
- P_LOAD_STRING(authPayload);
- P_LOAD_INT(streamReceiveWindow);
- P_LOAD_INT(connectionReceiveWindow);
- P_LOAD_BOOL(forceExternal);
+ P_LOAD_STRING(hopPort);
+ P_LOAD_INT(hopInterval);
+ P_LOAD_INT(uploadMbps);
+ P_LOAD_INT(downloadMbps);
+ P_LOAD_BOOL(disableMtuDiscovery)
+ P_LOAD_STRING(obfsPassword);
+ P_LOAD_STRING(authPayload);
+ P_LOAD_INT(streamReceiveWindow);
+ P_LOAD_INT(connectionReceiveWindow);
+ P_LOAD_BOOL(forceExternal);
+ P_LOAD_COMBO_INT(hyProtocol);
+ P_LOAD_COMBO_INT(authPayloadType);
+ P_LOAD_STRING(uuid);
+ P_LOAD_STRING(password);
+
+ P_LOAD_COMBO_STRING(congestionControl);
+ P_LOAD_COMBO_STRING(udpRelayMode);
+ P_LOAD_BOOL(zeroRttHandshake);
+ P_LOAD_STRING(heartbeat);
+ P_LOAD_BOOL(uos);
+
+ // TLS
+ P_LOAD_STRING(sni);
+ P_LOAD_STRING(alpn);
+ P_C_LOAD_STRING(caText);
+ P_LOAD_BOOL(allowInsecure);
+ P_LOAD_BOOL(disableSni);
+
+ if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria || bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria2) {
ui->uuid->hide();
ui->uuid_l->hide();
ui->uuidgen->hide();
- ui->password->hide();
- ui->password_l->hide();
ui->congestionControl->hide();
ui->congestionControl_l->hide();
ui->udpRelayMode->hide();
@@ -47,14 +63,9 @@ void EditQUIC::onStart(std::shared_ptr _ent) {
if (!IS_NEKO_BOX) ui->forceExternal->hide();
if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria) { // hy1
- P_LOAD_COMBO_INT(hyProtocol);
- P_LOAD_COMBO_INT(authPayloadType);
-
- ui->username_l->hide();
- ui->username->hide();
+ ui->password->hide();
+ ui->password_l->hide();
} else { // hy2
- P_LOAD_STRING(username);
-
ui->hyProtocol->hide();
ui->hyProtocol_l->hide();
ui->hyProtocol->hide();
@@ -79,14 +90,6 @@ void EditQUIC::onStart(std::shared_ptr _ent) {
}
}
} else if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_TUIC) {
- P_LOAD_STRING(uuid);
- P_LOAD_STRING(password);
- P_LOAD_COMBO_STRING(congestionControl);
- P_LOAD_COMBO_STRING(udpRelayMode);
- P_LOAD_BOOL(zeroRttHandshake);
- P_LOAD_STRING(heartbeat);
- P_LOAD_BOOL(uos);
-
ui->hopPort->hide();
ui->hopPort_l->hide();
ui->hopInterval->hide();
@@ -112,13 +115,6 @@ void EditQUIC::onStart(std::shared_ptr _ent) {
ui->uos->hide();
}
}
-
- // TLS
- P_LOAD_STRING(sni);
- P_LOAD_STRING(alpn);
- P_C_LOAD_STRING(caText);
- P_LOAD_BOOL(allowInsecure);
- P_LOAD_BOOL(disableSni);
}
bool EditQUIC::onEnd() {
@@ -139,9 +135,6 @@ bool EditQUIC::onEnd() {
P_SAVE_INT(streamReceiveWindow);
P_SAVE_INT(connectionReceiveWindow);
- // Hysteria2
- P_SAVE_STRING(username);
-
// TUIC
P_SAVE_STRING(uuid);
P_SAVE_STRING(password);
diff --git a/ui/edit/edit_quic.ui b/ui/edit/edit_quic.ui
index 2e3e913..385beea 100644
--- a/ui/edit/edit_quic.ui
+++ b/ui/edit/edit_quic.ui
@@ -176,16 +176,20 @@
-
-
-
-
-
- -
+
-
Obfs Password
+ -
+
+
+ Protocol
+
+
+
-
-
@@ -222,22 +226,8 @@
- -
-
-
- Protocol
-
-
-
- -
-
-
- Username
-
-
-
-
-
+
@@ -262,7 +252,7 @@
-
-
+
0
0
@@ -275,7 +265,7 @@
-
-
+
0
0
@@ -287,12 +277,6 @@
-
-
-
- 0
- 0
-
-
UUID
@@ -446,7 +430,6 @@
uos
hyProtocol
disableMtuDiscovery
- username
obfsPassword
authPayloadType
authPayload