Support hysteria2

This commit is contained in:
arm64v8a
2023-09-06 18:45:20 +09:00
parent 9efde1a59e
commit 29c618581e
12 changed files with 109 additions and 98 deletions

View File

@@ -202,7 +202,7 @@ namespace NekoGui_fmt {
if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload; if (authPayloadType == hysteria_auth_string) outbound["auth_str"] = authPayload;
} else if (proxy_type == proxy_Hysteria2) { } else if (proxy_type == proxy_Hysteria2) {
outbound["type"] = "hysteria2"; outbound["type"] = "hysteria2";
outbound["password"] = authPayload; outbound["password"] = password;
outbound["up_mbps"] = uploadMbps; outbound["up_mbps"] = uploadMbps;
outbound["down_mbps"] = downloadMbps; outbound["down_mbps"] = downloadMbps;
if (!obfsPassword.isEmpty()) { if (!obfsPassword.isEmpty()) {

View File

@@ -198,11 +198,7 @@ namespace NekoGui_fmt {
{"listen", "127.0.0.1:" + Int2String(socks_port)}, {"listen", "127.0.0.1:" + Int2String(socks_port)},
{"disableUDP", false}, {"disableUDP", false},
}; };
if (username.isEmpty()) { config["auth"] = password;
config["auth"] = authPayload;
} else {
config["auth"] = username + ":" + authPayload;
}
QJsonObject bandwidth; QJsonObject bandwidth;
if (uploadMbps > 0) bandwidth["up"] = Int2String(uploadMbps) + " mbps"; if (uploadMbps > 0) bandwidth["up"] = Int2String(uploadMbps) + " mbps";

View File

@@ -214,6 +214,26 @@ namespace NekoGui_fmt {
if (disableSni) q.addQueryItem("disable_sni", "1"); if (disableSni) q.addQueryItem("disable_sni", "1");
if (!q.isEmpty()) url.setQuery(q); if (!q.isEmpty()) url.setQuery(q);
if (!name.isEmpty()) url.setFragment(name); 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); return url.toString(QUrl::FullyEncoded);
} }

View File

@@ -233,10 +233,9 @@ namespace NekoGui_fmt {
name = url.fragment(); name = url.fragment();
serverAddress = url.host(); serverAddress = url.host();
serverPort = url.port(); serverPort = url.port();
serverAddress = url.host(); // default sni
hopPort = query.queryItemValue("mport"); hopPort = query.queryItemValue("mport");
obfsPassword = query.queryItemValue("obfsParam"); obfsPassword = query.queryItemValue("obfsParam");
allowInsecure = query.queryItemValue("insecure") == "1"; allowInsecure = QStringList{"1", "true"}.contains(query.queryItemValue("insecure"));
uploadMbps = query.queryItemValue("upmbps").toInt(); uploadMbps = query.queryItemValue("upmbps").toInt();
downloadMbps = query.queryItemValue("downmbps").toInt(); downloadMbps = query.queryItemValue("downmbps").toInt();
@@ -275,6 +274,21 @@ namespace NekoGui_fmt {
udpRelayMode = query.queryItemValue("udp_relay_mode"); udpRelayMode = query.queryItemValue("udp_relay_mode");
allowInsecure = query.queryItemValue("allow_insecure") == "1"; allowInsecure = query.queryItemValue("allow_insecure") == "1";
disableSni = query.queryItemValue("disable_sni") == "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; return true;

View File

@@ -12,7 +12,7 @@ namespace NekoGui_fmt {
bool forceExternal = false; bool forceExternal = false;
// Hysteria // Hysteria 1
static constexpr int hysteria_protocol_udp = 0; static constexpr int hysteria_protocol_udp = 0;
static constexpr int hysteria_protocol_facktcp = 1; 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_string = 1;
static constexpr int hysteria_auth_base64 = 2; static constexpr int hysteria_auth_base64 = 2;
int authPayloadType = 0; int authPayloadType = 0;
QString authPayload = ""; QString authPayload = "";
// Hysteria 1&2
QString obfsPassword = ""; QString obfsPassword = "";
int uploadMbps = 100; int uploadMbps = 100;
@@ -37,19 +39,19 @@ 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 = "";
QString password = "";
QString congestionControl = "bbr"; QString congestionControl = "bbr";
QString udpRelayMode = "native"; QString udpRelayMode = "native";
bool zeroRttHandshake = false; bool zeroRttHandshake = false;
QString heartbeat = "10s"; QString heartbeat = "10s";
bool uos = false; bool uos = false;
// HY2&TUIC
QString password = "";
// TLS // TLS
bool allowInsecure = false; bool allowInsecure = false;
@@ -76,9 +78,8 @@ namespace NekoGui_fmt {
} else { // hy2 } else { // hy2
uploadMbps = 0; uploadMbps = 0;
downloadMbps = 0; downloadMbps = 0;
_add(new configItem("username", &username, itemType::string)); _add(new configItem("password", &password, 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));
@@ -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; int NeedExternal(bool isFirstProfile) override;

View File

@@ -124,7 +124,7 @@ namespace NekoGui_sub {
if (!ok) return; if (!ok) return;
} }
// Hysteria // Hysteria1
if (str.startsWith("hysteria://")) { if (str.startsWith("hysteria://")) {
needFix = false; needFix = false;
ent = NekoGui::ProfileManager::NewProxyEntity("hysteria"); ent = NekoGui::ProfileManager::NewProxyEntity("hysteria");
@@ -132,6 +132,14 @@ namespace NekoGui_sub {
if (!ok) return; 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 // TUIC
if (str.startsWith("tuic://")) { if (str.startsWith("tuic://")) {
needFix = false; needFix = false;

View File

@@ -972,10 +972,6 @@ This needs to be run NekoBox with administrator privileges.</source>
<source>UDP Relay Mode</source> <source>UDP Relay Mode</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Username</source>
<translation type="unfinished">نام کاربری</translation>
</message>
<message> <message>
<source>Force use external core</source> <source>Force use external core</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>

View File

@@ -979,10 +979,6 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun</translation>
<source>UDP Relay Mode</source> <source>UDP Relay Mode</source>
<translation>Режим UDP Relay</translation> <translation>Режим UDP Relay</translation>
</message> </message>
<message>
<source>Username</source>
<translation type="unfinished">Имя пользователя</translation>
</message>
<message> <message>
<source>Force use external core</source> <source>Force use external core</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>

View File

@@ -980,10 +980,6 @@ This needs to be run NekoBox with administrator privileges.</source>
<source>Disable SNI</source> <source>Disable SNI</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Username</source>
<translation></translation>
</message>
<message> <message>
<source>Force use external core</source> <source>Force use external core</source>
<translation>使</translation> <translation>使</translation>

View File

@@ -120,8 +120,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
LOAD_TYPE("vmess") LOAD_TYPE("vmess")
LOAD_TYPE("vless") LOAD_TYPE("vless")
LOAD_TYPE("naive") LOAD_TYPE("naive")
ui->type->addItem("Hysteria1", "hysteria"); LOAD_TYPE("hysteria")
ui->type->addItem("Hysteria2", "hysteria2"); 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");

View File

@@ -19,23 +19,39 @@ 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 || 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_BOOL(disableMtuDiscovery)
P_LOAD_BOOL(disableMtuDiscovery) P_LOAD_STRING(obfsPassword);
P_LOAD_STRING(obfsPassword); P_LOAD_STRING(authPayload);
P_LOAD_STRING(authPayload); P_LOAD_INT(streamReceiveWindow);
P_LOAD_INT(streamReceiveWindow); P_LOAD_INT(connectionReceiveWindow);
P_LOAD_INT(connectionReceiveWindow);
P_LOAD_BOOL(forceExternal);
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->hide();
ui->uuid_l->hide(); ui->uuid_l->hide();
ui->uuidgen->hide(); ui->uuidgen->hide();
ui->password->hide();
ui->password_l->hide();
ui->congestionControl->hide(); ui->congestionControl->hide();
ui->congestionControl_l->hide(); ui->congestionControl_l->hide();
ui->udpRelayMode->hide(); ui->udpRelayMode->hide();
@@ -47,14 +63,9 @@ void EditQUIC::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
if (!IS_NEKO_BOX) ui->forceExternal->hide(); if (!IS_NEKO_BOX) ui->forceExternal->hide();
if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria) { // hy1 if (bean->proxy_type == NekoGui_fmt::QUICBean::proxy_Hysteria) { // hy1
P_LOAD_COMBO_INT(hyProtocol); ui->password->hide();
P_LOAD_COMBO_INT(authPayloadType); ui->password_l->hide();
ui->username_l->hide();
ui->username->hide();
} else { // hy2 } else { // hy2
P_LOAD_STRING(username);
ui->hyProtocol->hide(); ui->hyProtocol->hide();
ui->hyProtocol_l->hide(); ui->hyProtocol_l->hide();
ui->hyProtocol->hide(); ui->hyProtocol->hide();
@@ -79,14 +90,6 @@ void EditQUIC::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
} }
} }
} 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(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->hide();
ui->hopPort_l->hide(); ui->hopPort_l->hide();
ui->hopInterval->hide(); ui->hopInterval->hide();
@@ -112,13 +115,6 @@ void EditQUIC::onStart(std::shared_ptr<NekoGui::ProxyEntity> _ent) {
ui->uos->hide(); 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() { bool EditQUIC::onEnd() {
@@ -139,9 +135,6 @@ 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);

View File

@@ -176,16 +176,20 @@
</item> </item>
<item> <item>
<layout class="QGridLayout" name="obfuscation"> <layout class="QGridLayout" name="obfuscation">
<item row="2" column="1"> <item row="1" column="0">
<widget class="MyLineEdit" name="obfsPassword"/>
</item>
<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>
@@ -222,22 +226,8 @@
</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"> <item row="1" column="1">
<widget class="MyLineEdit" name="username"/> <widget class="MyLineEdit" name="obfsPassword"/>
</item> </item>
</layout> </layout>
</item> </item>
@@ -262,7 +252,7 @@
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="authPayload_l"> <widget class="QLabel" name="authPayload_l">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@@ -275,7 +265,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="password_l"> <widget class="QLabel" name="password_l">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
@@ -287,12 +277,6 @@
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="uuid_l"> <widget class="QLabel" name="uuid_l">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string notr="true">UUID</string> <string notr="true">UUID</string>
</property> </property>
@@ -446,7 +430,6 @@
<tabstop>uos</tabstop> <tabstop>uos</tabstop>
<tabstop>hyProtocol</tabstop> <tabstop>hyProtocol</tabstop>
<tabstop>disableMtuDiscovery</tabstop> <tabstop>disableMtuDiscovery</tabstop>
<tabstop>username</tabstop>
<tabstop>obfsPassword</tabstop> <tabstop>obfsPassword</tabstop>
<tabstop>authPayloadType</tabstop> <tabstop>authPayloadType</tabstop>
<tabstop>authPayload</tabstop> <tabstop>authPayload</tabstop>