From 29d348bd67981b57bdf8a7fa41ea915b7b183956 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Tue, 12 Mar 2024 15:40:41 +0100 Subject: [PATCH] [feature] add httpUpgrade transport Co-Authored-By: MHSanaei --- sub/subJsonService.go | 2 + sub/subService.go | 16 +++++ web/assets/js/model/outbound.js | 32 +++++++++- web/assets/js/model/xray.js | 58 ++++++++++++++++++- web/html/xui/form/outbound.html | 29 +++++++--- .../xui/form/stream/stream_httpupgrade.html | 13 +++++ web/html/xui/form/stream/stream_settings.html | 7 +++ web/html/xui/inbound_info_modal.html | 2 +- 8 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 web/html/xui/form/stream/stream_httpupgrade.html diff --git a/sub/subJsonService.go b/sub/subJsonService.go index 0467e311..9ff3fa2c 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -217,6 +217,8 @@ func (s *SubJsonService) streamData(stream string) map[string]interface{} { streamSettings["tcpSettings"] = s.removeAcceptProxy(streamSettings["tcpSettings"]) case "ws": streamSettings["wsSettings"] = s.removeAcceptProxy(streamSettings["wsSettings"]) + case "httpupgrade": + streamSettings["httpupgradeSettings"] = s.removeAcceptProxy(streamSettings["httpupgradeSettings"]) } return streamSettings diff --git a/sub/subService.go b/sub/subService.go index e873c15f..0ae46e02 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -213,6 +213,10 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { if grpc["multiMode"].(bool) { obj["type"] = "multi" } + case "httpupgrade": + httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) + obj["path"] = httpupgrade["path"].(string) + obj["host"] = httpupgrade["host"].(string) } security, _ := stream["security"].(string) @@ -347,6 +351,10 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { if grpc["multiMode"].(bool) { params["mode"] = "multi" } + case "httpupgrade": + httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) + params["path"] = httpupgrade["path"].(string) + params["host"] = httpupgrade["host"].(string) } security, _ := stream["security"].(string) @@ -528,6 +536,10 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string if grpc["multiMode"].(bool) { params["mode"] = "multi" } + case "httpupgrade": + httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) + params["path"] = httpupgrade["path"].(string) + params["host"] = httpupgrade["host"].(string) } security, _ := stream["security"].(string) @@ -705,6 +717,10 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st if grpc["multiMode"].(bool) { params["mode"] = "multi" } + case "httpupgrade": + httpupgrade, _ := stream["httpupgradeSettings"].(map[string]interface{}) + params["path"] = httpupgrade["path"].(string) + params["host"] = httpupgrade["host"].(string) } security, _ := stream["security"].(string) diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index cbfcfd3c..517272f7 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -275,6 +275,28 @@ class GrpcStreamSettings extends CommonClass { } } +class HttpUpgradeStreamSettings extends CommonClass { + constructor(path='/', host='') { + super(); + this.path = path; + this.host = host; + } + + static fromJson(json={}) { + return new HttpUpgradeStreamSettings( + json.path, + json.Host, + ); + } + + toJson() { + return { + path: this.path, + host: this.host, + }; + } +} + class TlsStreamSettings extends CommonClass { constructor(serverName='', alpn=[], @@ -375,6 +397,7 @@ class StreamSettings extends CommonClass { httpSettings=new HttpStreamSettings(), quicSettings=new QuicStreamSettings(), grpcSettings=new GrpcStreamSettings(), + httpupgradeSettings=new HttpUpgradeStreamSettings(), sockopt = undefined, ) { super(); @@ -388,6 +411,7 @@ class StreamSettings extends CommonClass { this.http = httpSettings; this.quic = quicSettings; this.grpc = grpcSettings; + this.httpupgrade = httpupgradeSettings; this.sockopt = sockopt; } @@ -419,6 +443,7 @@ class StreamSettings extends CommonClass { HttpStreamSettings.fromJson(json.httpSettings), QuicStreamSettings.fromJson(json.quicSettings), GrpcStreamSettings.fromJson(json.grpcSettings), + HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings), SockoptStreamSettings.fromJson(json.sockopt), ); } @@ -436,6 +461,7 @@ class StreamSettings extends CommonClass { httpSettings: network === 'http' ? this.http.toJson() : undefined, quicSettings: network === 'quic' ? this.quic.toJson() : undefined, grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, + httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, }; } @@ -500,7 +526,7 @@ class Outbound extends CommonClass { canEnableTls() { if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false; - return ["tcp", "ws", "http", "quic", "grpc"].includes(this.stream.network); + return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade"].includes(this.stream.network); } //this is used for xtls-rprx-vision @@ -615,6 +641,8 @@ class Outbound extends CommonClass { json.type ? json.type : 'none'); } else if (network === 'grpc') { stream.grpc = new GrpcStreamSettings(json.path, json.type == 'multi'); + } else if (network === 'httpupgrade') { + stream.httpupgrade = new HttpUpgradeStreamSettings(json.path,json.host); } if(json.tls && json.tls == 'tls'){ @@ -655,6 +683,8 @@ class Outbound extends CommonClass { headerType ?? 'none'); } else if (type === 'grpc') { stream.grpc = new GrpcStreamSettings(url.searchParams.get('serviceName') ?? '', url.searchParams.get('mode') == 'multi'); + } else if (type === 'httpupgrade') { + stream.httpupgrade = new HttpUpgradeStreamSettings(path,host); } if(security == 'tls'){ diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index 79fe0b1c..1ec620b2 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -453,6 +453,31 @@ class GrpcStreamSettings extends XrayCommonClass { } } +class HttpUpgradeStreamSettings extends XrayCommonClass { + constructor(acceptProxyProtocol=false, path='/', host='') { + super(); + this.acceptProxyProtocol = acceptProxyProtocol; + this.path = path; + this.host = host; + } + + static fromJson(json={}) { + return new HttpUpgradeStreamSettings( + json.acceptProxyProtocol, + json.path, + json.host, + ); + } + + toJson() { + return { + acceptProxyProtocol: this.acceptProxyProtocol, + path: this.path, + host: this.host, + }; + } +} + class TlsStreamSettings extends XrayCommonClass { constructor(serverName='', minVersion = TLS_VERSION_OPTION.TLS12, @@ -705,6 +730,7 @@ class StreamSettings extends XrayCommonClass { httpSettings=new HttpStreamSettings(), quicSettings=new QuicStreamSettings(), grpcSettings=new GrpcStreamSettings(), + httpupgradeSettings=new HttpUpgradeStreamSettings(), sockopt = undefined, ) { super(); @@ -719,6 +745,7 @@ class StreamSettings extends XrayCommonClass { this.http = httpSettings; this.quic = quicSettings; this.grpc = grpcSettings; + this.httpupgrade = httpupgradeSettings; this.sockopt = sockopt; } @@ -767,6 +794,7 @@ class StreamSettings extends XrayCommonClass { HttpStreamSettings.fromJson(json.httpSettings), QuicStreamSettings.fromJson(json.quicSettings), GrpcStreamSettings.fromJson(json.grpcSettings), + HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings), SockoptStreamSettings.fromJson(json.sockopt), ); } @@ -785,6 +813,7 @@ class StreamSettings extends XrayCommonClass { httpSettings: network === 'http' ? this.http.toJson() : undefined, quicSettings: network === 'quic' ? this.quic.toJson() : undefined, grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, + httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, }; } @@ -889,6 +918,10 @@ class Inbound extends XrayCommonClass { return this.network === "http"; } + get isHttpupgrade() { + return this.network === "httpupgrade"; + } + // Shadowsocks get method() { switch (this.protocol) { @@ -918,6 +951,8 @@ class Inbound extends XrayCommonClass { return this.stream.ws.getHeader("Host"); } else if (this.isH2) { return this.stream.http.host[0]; + } else if (this.isHttpupgrade) { + return this.stream.httpupgrade.host; } return null; } @@ -929,6 +964,8 @@ class Inbound extends XrayCommonClass { return this.stream.ws.path; } else if (this.isH2) { return this.stream.http.path; + } else if (this.isHttpupgrade) { + return this.stream.httpupgrade.path; } return null; } @@ -964,7 +1001,7 @@ class Inbound extends XrayCommonClass { canEnableTls() { if(![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false; - return ["tcp", "ws", "http", "quic", "grpc"].includes(this.network); + return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade"].includes(this.network); } //this is used for xtls-rprx-vision @@ -1045,6 +1082,10 @@ class Inbound extends XrayCommonClass { if (this.stream.grpc.multiMode){ obj.type = 'multi' } + } else if (network === 'httpupgrade') { + let httpupgrade = this.stream.httpupgrade; + obj.path = httpupgrade.path; + obj.host = httpupgrade.host; } if (security === 'tls') { @@ -1117,6 +1158,11 @@ class Inbound extends XrayCommonClass { params.set("mode", "multi"); } break; + case "httpupgrade": + const httpupgrade = this.stream.httpupgrade; + params.set("path", httpupgrade.path); + params.set("host", httpupgrade.host); + break; } if (security === 'tls') { @@ -1219,6 +1265,11 @@ class Inbound extends XrayCommonClass { params.set("mode", "multi"); } break; + case "httpupgrade": + const httpupgrade = this.stream.httpupgrade; + params.set("path", httpupgrade.path); + params.set("host", httpupgrade.host); + break; } if (security === 'tls') { @@ -1300,6 +1351,11 @@ class Inbound extends XrayCommonClass { params.set("mode", "multi"); } break; + case "httpupgrade": + const httpupgrade = this.stream.httpupgrade; + params.set("path", httpupgrade.path); + params.set("host", httpupgrade.host); + break; } if (security === 'tls') { diff --git a/web/html/xui/form/outbound.html b/web/html/xui/form/outbound.html index 47348db4..d2513262 100644 --- a/web/html/xui/form/outbound.html +++ b/web/html/xui/form/outbound.html @@ -226,22 +226,23 @@ HTTP/2 QUIC gRPC + HttpUpgrade + @@ -268,7 +269,7 @@ - + @@ -336,6 +337,16 @@ + + + diff --git a/web/html/xui/form/stream/stream_httpupgrade.html b/web/html/xui/form/stream/stream_httpupgrade.html new file mode 100644 index 00000000..397a2830 --- /dev/null +++ b/web/html/xui/form/stream/stream_httpupgrade.html @@ -0,0 +1,13 @@ +{{define "form/streamHTTPUPGRADE"}} + + + + + + + + + + + +{{end}} \ No newline at end of file diff --git a/web/html/xui/form/stream/stream_settings.html b/web/html/xui/form/stream/stream_settings.html index ae8a05f2..0ce62066 100644 --- a/web/html/xui/form/stream/stream_settings.html +++ b/web/html/xui/form/stream/stream_settings.html @@ -10,6 +10,7 @@ HTTP/2 QUIC gRPC + HttpUpgrade @@ -43,6 +44,12 @@ + + + +