fix: Restore header type for compatiblity with Xray

This commit is contained in:
Nova 2024-08-26 17:22:02 +03:30
parent ff15bc53a6
commit 26eefee4b9
No known key found for this signature in database
GPG Key ID: 389787EC83F5D73A
7 changed files with 143 additions and 48 deletions

View File

@ -52,6 +52,15 @@ namespace NekoGui_fmt {
transport["headers"] = QMapString2QJsonObject(headerMap);
}
outbound->insert("transport", transport);
} else if (header_type == "http") {
// TCP + headerType
QJsonObject transport{
{"type", "http"},
{"method", "GET"},
{"path", path},
{"headers", QJsonObject{{"Host", QListStr2QJsonArray(host.split(","))}}},
};
outbound->insert("transport", transport);
}
// 对应字段 tls

View File

@ -60,6 +60,12 @@ namespace NekoGui_fmt {
if (!stream->method.isEmpty()) query.addQueryItem("method", stream->method);
} else if (stream->network == "grpc") {
if (!stream->path.isEmpty()) query.addQueryItem("serviceName", stream->path);
} else if (stream->network == "tcp") {
if (stream->header_type == "http") {
if (!stream->path.isEmpty()) query.addQueryItem("path", stream->path);
query.addQueryItem("headerType", "http");
query.addQueryItem("host", stream->host);
}
}
// mux
@ -156,6 +162,11 @@ namespace NekoGui_fmt {
if (!stream->host.isEmpty()) query.addQueryItem("host", stream->host);
} else if (stream->network == "grpc") {
if (!stream->path.isEmpty()) query.addQueryItem("serviceName", stream->path);
} else if (stream->network == "tcp") {
if (stream->header_type == "http") {
query.addQueryItem("headerType", "http");
query.addQueryItem("host", stream->host);
}
}
// mux

View File

@ -93,6 +93,12 @@ namespace NekoGui_fmt {
stream->host = GetQueryValue(query, "host", "");
} else if (stream->network == "grpc") {
stream->path = GetQueryValue(query, "serviceName", "");
} else if (stream->network == "tcp") {
if (GetQueryValue(query, "headerType") == "http") {
stream->header_type = "http";
stream->host = GetQueryValue(query, "host", "");
stream->path = GetQueryValue(query, "path", "");
}
}
// mux
@ -171,6 +177,7 @@ namespace NekoGui_fmt {
stream->host = objN["host"].toString();
stream->path = objN["path"].toString();
stream->sni = objN["sni"].toString();
stream->header_type = objN["type"].toString();
auto net = objN["net"].toString();
if (!net.isEmpty()) {
if (net == "h2") {
@ -239,6 +246,12 @@ namespace NekoGui_fmt {
stream->host = GetQueryValue(query, "host", "");
} else if (stream->network == "grpc") {
stream->path = GetQueryValue(query, "serviceName", "");
} else if (stream->network == "tcp") {
if (GetQueryValue(query, "headerType") == "http") {
stream->header_type = "http";
stream->path = GetQueryValue(query, "path", "");
stream->host = GetQueryValue(query, "host", "");
}
}
return !(uuid.isEmpty() || serverAddress.isEmpty());
}

View File

@ -13,6 +13,7 @@ namespace NekoGui_fmt {
QString host = "";
QString method = "";
QString headers = "";
QString header_type = "";
QString sni = "";
QString alpn = "";
@ -38,6 +39,7 @@ namespace NekoGui_fmt {
_add(new configItem("cert", &certificate, itemType::string));
_add(new configItem("insecure", &allow_insecure, itemType::boolean));
_add(new configItem("headers", &headers, itemType::string));
_add(new configItem("h_type", &header_type, itemType::string));
_add(new configItem("method", &method, itemType::string));
_add(new configItem("ed_name", &ws_early_data_name, itemType::string));
_add(new configItem("ed_len", &ws_early_data_length, itemType::integer));

View File

@ -459,6 +459,23 @@ namespace NekoGui_sub {
}
bean->stream->path = Node2QString(h2["path"]);
}
auto tcp_http = NodeChild(proxy, {"http-opts", "http-opt"});
if (tcp_http.IsMap()) {
bean->stream->network = "tcp";
bean->stream->header_type = "http";
auto headers = tcp_http["headers"];
for (auto header: headers) {
if (Node2QString(header.first).toLower() == "host") {
bean->stream->host = Node2QString(header.second[0]);
}
break;
}
auto paths = tcp_http["path"];
for (auto path: paths) {
bean->stream->path = Node2QString(path);
break;
}
}
} else if (type == "hysteria") {
auto bean = ent->QUICBean();

View File

@ -32,7 +32,20 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
network_title_base = ui->network_box->title();
connect(ui->network, &QComboBox::currentTextChanged, this, [=](const QString &txt) {
ui->network_box->setTitle(network_title_base.arg(txt));
if (txt == "grpc") {
if (txt == "tcp") {
ui->header_type->setVisible(true);
ui->header_type_l->setVisible(true);
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
ui->method_l->setVisible(false);
ui->path->setVisible(true);
ui->path_l->setVisible(true);
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else if (txt == "grpc") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
@ -42,6 +55,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(false);
ui->host_l->setVisible(false);
} else if (txt == "ws" || txt == "httpupgrade") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(true);
ui->headers_l->setVisible(true);
ui->method->setVisible(false);
@ -51,6 +66,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else if (txt == "http") {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(true);
ui->headers_l->setVisible(true);
ui->method->setVisible(true);
@ -60,6 +77,8 @@ DialogEditProfile::DialogEditProfile(const QString &_type, int profileOrGroupId,
ui->host->setVisible(true);
ui->host_l->setVisible(true);
} else {
ui->header_type->setVisible(false);
ui->header_type_l->setVisible(false);
ui->headers->setVisible(false);
ui->headers_l->setVisible(false);
ui->method->setVisible(false);
@ -236,7 +255,6 @@ void DialogEditProfile::typeSelected(const QString &newType) {
// 右边 stream
auto stream = GetStreamSettings(ent->bean.get());
if (stream != nullptr) {
ui->network_box->setVisible(stream->network != "tcp");
ui->right_all_w->setVisible(true);
ui->network->setCurrentText(stream->network);
ui->security->setCurrentText(stream->security);
@ -252,6 +270,7 @@ void DialogEditProfile::typeSelected(const QString &newType) {
ui->utlsFingerprint->setCurrentText(stream->utlsFingerprint);
}
ui->insecure->setChecked(stream->allow_insecure);
ui->header_type->setCurrentText(stream->header_type);
ui->headers->setText(stream->headers);
ui->ws_early_data_name->setText(stream->ws_early_data_name);
ui->ws_early_data_length->setText(Int2String(stream->ws_early_data_length));
@ -318,9 +337,11 @@ void DialogEditProfile::typeSelected(const QString &newType) {
if (type == "vmess" || type == "vless" || type == "trojan") {
ui->network_l->setVisible(true);
ui->network->setVisible(true);
ui->network_box->setVisible(true);
} else {
ui->network_l->setVisible(false);
ui->network->setVisible(false);
ui->network_box->setVisible(false);
}
if (type == "vmess" || type == "vless" || type == "trojan" || type == "http") {
ui->security->setVisible(true);
@ -382,6 +403,7 @@ bool DialogEditProfile::onEnd() {
stream->utlsFingerprint = ui->utlsFingerprint->currentText();
stream->allow_insecure = ui->insecure->isChecked();
stream->headers = ui->headers->text();
stream->header_type = ui->header_type->currentText();
stream->method = ui->method->text();
stream->ws_early_data_name = ui->ws_early_data_name->text();
stream->ws_early_data_length = ui->ws_early_data_length->text().toInt();

View File

@ -525,56 +525,14 @@
<string>Network Settings (%1)</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="MyLineEdit" name="host"/>
</item>
<item row="4" column="1">
<widget class="MyLineEdit" name="ws_early_data_length"/>
</item>
<item row="5" column="1">
<widget class="MyLineEdit" name="ws_early_data_name"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="host_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http host (ws/http/httpUpgrade)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">Host</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="headers"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="ws_early_data_length_l">
<property name="text">
<string notr="true">EarlyData Length</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="path_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http path (ws/http/httpUpgrade)&lt;/p&gt;&lt;p&gt;serviceName (gRPC)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">Path</string>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="ws_early_data_name_l">
<property name="text">
<string notr="true">EarlyData Name</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="MyLineEdit" name="path"/>
</item>
<item row="0" column="0">
<item row="1" column="0">
<widget class="QLabel" name="headers_l">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
@ -593,7 +551,39 @@
</property>
</widget>
</item>
<item row="1" column="0">
<item row="5" column="0">
<widget class="QLabel" name="ws_early_data_length_l">
<property name="text">
<string notr="true">EarlyData Length</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="method"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="path_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http path (ws/http/httpUpgrade)&lt;/p&gt;&lt;p&gt;serviceName (gRPC)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">Path</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="MyLineEdit" name="path"/>
</item>
<item row="6" column="1">
<widget class="MyLineEdit" name="ws_early_data_name"/>
</item>
<item row="5" column="1">
<widget class="MyLineEdit" name="ws_early_data_length"/>
</item>
<item row="4" column="1">
<widget class="MyLineEdit" name="host"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="method_l">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Method of http request, will be converted to uppercase&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -603,8 +593,39 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="host_l">
<property name="toolTip">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;http host (ws/http/httpUpgrade)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true">Host</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="method"/>
<widget class="QLineEdit" name="headers"/>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="header_type">
<item>
<property name="text">
<string/>
</property>
</item>
<item>
<property name="text">
<string>http</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="header_type_l">
<property name="text">
<string>header type</string>
</property>
</widget>
</item>
</layout>
</widget>