Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.sum2
-rw-r--r--logger/logger.go3
-rw-r--r--web/assets/js/model/xray.js96
-rw-r--r--web/global/global.go3
-rw-r--r--web/html/xui/form/stream/stream_grpc.html3
-rw-r--r--web/html/xui/inbound_info_modal.html1
-rw-r--r--web/service/sub.go90
7 files changed, 111 insertions, 87 deletions
diff --git a/go.sum b/go.sum
index 0e86b547..8484df35 100644
--- a/go.sum
+++ b/go.sum
@@ -9,8 +9,6 @@ github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
-github.com/bytedance/sonic v1.8.7 h1:d3sry5vGgVq/OpgozRUNP6xBsSo0mtNdwliApw+SAMQ=
-github.com/bytedance/sonic v1.8.7/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/bytedance/sonic v1.8.8 h1:Kj4AYbZSeENfyXicsYppYKO0K2YWab+i2UTSY7Ukz9Q=
github.com/bytedance/sonic v1.8.8/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
diff --git a/logger/logger.go b/logger/logger.go
index cb5e8360..405f2ec7 100644
--- a/logger/logger.go
+++ b/logger/logger.go
@@ -1,8 +1,9 @@
package logger
import (
- "github.com/op/go-logging"
"os"
+
+ "github.com/op/go-logging"
)
var logger *logging.Logger
diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js
index 3370aa07..195155cf 100644
--- a/web/assets/js/model/xray.js
+++ b/web/assets/js/model/xray.js
@@ -440,18 +440,26 @@ class QuicStreamSettings extends XrayCommonClass {
}
class GrpcStreamSettings extends XrayCommonClass {
- constructor(serviceName="") {
+ constructor(
+ serviceName="",
+ multiMode=false
+ ) {
super();
this.serviceName = serviceName;
+ this.multiMode = multiMode;
}
static fromJson(json={}) {
- return new GrpcStreamSettings(json.serviceName);
+ return new GrpcStreamSettings(
+ json.serviceName,
+ json.multiMode
+ );
}
toJson() {
return {
serviceName: this.serviceName,
+ multiMode: this.multiMode
}
}
}
@@ -1246,67 +1254,73 @@ class Inbound extends XrayCommonClass {
if (this.protocol !== Protocols.VMESS) {
return '';
}
+ let obj = {
+ v: '2',
+ ps: remark,
+ add: address,
+ port: this.port,
+ id: this.settings.vmesses[clientIndex].id,
+ aid: this.settings.vmesses[clientIndex].alterId,
+ net: this.stream.network,
+ type: 'none',
+ tls: this.stream.security,
+ };
let network = this.stream.network;
- let type = 'none';
- let host = '';
- let path = '';
if (network === 'tcp') {
let tcp = this.stream.tcp;
- type = tcp.type;
- if (type === 'http') {
+ obj.type = tcp.type;
+ if (tcp.type === 'http') {
let request = tcp.request;
- path = request.path.join(',');
+ obj.path = request.path.join(',');
let index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
- host = request.headers[index].value;
+ obj.host = request.headers[index].value;
}
}
} else if (network === 'kcp') {
let kcp = this.stream.kcp;
- type = kcp.type;
- path = kcp.seed;
+ obj.type = kcp.type;
+ obj.path = kcp.seed;
} else if (network === 'ws') {
let ws = this.stream.ws;
- path = ws.path;
+ obj.path = ws.path;
let index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
- host = ws.headers[index].value;
+ obj.host = ws.headers[index].value;
}
} else if (network === 'http') {
- network = 'h2';
- path = this.stream.http.path;
- host = this.stream.http.host.join(',');
+ obj.net = 'h2';
+ obj.path = this.stream.http.path;
+ obj.host = this.stream.http.host.join(',');
} else if (network === 'quic') {
- type = this.stream.quic.type;
- host = this.stream.quic.security;
- path = this.stream.quic.key;
+ obj.type = this.stream.quic.type;
+ obj.host = this.stream.quic.security;
+ obj.path = this.stream.quic.key;
} else if (network === 'grpc') {
- path = this.stream.grpc.serviceName;
+ obj.path = this.stream.grpc.serviceName;
+ if (this.stream.grpc.multiMode){
+ obj.type = 'multi'
+ }
}
if (this.stream.security === 'tls') {
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
- address = this.stream.tls.server;
+ obj.add = this.stream.tls.server;
+ }
+ if (!ObjectUtil.isEmpty(this.stream.tls.settings.serverName)){
+ obj.sni = this.stream.tls.settings.serverName;
+ }
+ if (!ObjectUtil.isEmpty(this.stream.tls.settings.fingerprint)){
+ obj.fp = this.stream.tls.settings.fingerprint;
+ }
+ if (this.stream.tls.alpn.length>0){
+ obj.alpn = this.stream.tls.alpn.join(',');
+ }
+ if (this.stream.tls.settings.allowInsecure){
+ obj.allowInsecure = this.stream.tls.settings.allowInsecure;
}
}
- let obj = {
- v: '2',
- ps: remark,
- add: address,
- port: this.port,
- id: this.settings.vmesses[clientIndex].id,
- aid: this.settings.vmesses[clientIndex].alterId,
- net: network,
- type: type,
- host: host,
- path: path,
- tls: this.stream.security,
- sni: this.stream.tls.settings.serverName,
- fp: this.stream.tls.settings.fingerprint,
- alpn: this.stream.tls.alpn.join(','),
- allowInsecure: this.stream.tls.settings.allowInsecure,
- };
return 'vmess://' + base64(JSON.stringify(obj, null, 2));
}
@@ -1359,6 +1373,9 @@ class Inbound extends XrayCommonClass {
case "grpc":
const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName);
+ if(grpc.multiMode){
+ params.set("mode", "multi");
+ }
break;
}
@@ -1476,6 +1493,9 @@ class Inbound extends XrayCommonClass {
case "grpc":
const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName);
+ if(grpc.multiMode){
+ params.set("mode", "multi");
+ }
break;
}
diff --git a/web/global/global.go b/web/global/global.go
index 09d0683a..7ded94e7 100644
--- a/web/global/global.go
+++ b/web/global/global.go
@@ -2,8 +2,9 @@ package global
import (
"context"
- "github.com/robfig/cron/v3"
_ "unsafe"
+
+ "github.com/robfig/cron/v3"
)
var webServer WebServer
diff --git a/web/html/xui/form/stream/stream_grpc.html b/web/html/xui/form/stream/stream_grpc.html
index 4e57d225..21c95f99 100644
--- a/web/html/xui/form/stream/stream_grpc.html
+++ b/web/html/xui/form/stream/stream_grpc.html
@@ -3,5 +3,8 @@
<a-form-item label="ServiceName">
<a-input v-model.trim="inbound.stream.grpc.serviceName"></a-input>
</a-form-item>
+ <a-form-item label="Multi Mode">
+ <a-switch v-model="inbound.stream.grpc.multiMode"></a-switch>
+ </a-form-item>
</a-form>
{{end}} \ No newline at end of file
diff --git a/web/html/xui/inbound_info_modal.html b/web/html/xui/inbound_info_modal.html
index 4e8c7dae..489a9a61 100644
--- a/web/html/xui/inbound_info_modal.html
+++ b/web/html/xui/inbound_info_modal.html
@@ -41,6 +41,7 @@
<template v-if="inbound.isGrpc">
<tr><td>grpc serviceName</td><td><a-tag color="green">[[ inbound.serviceName ]]</a-tag></td></tr>
+ <tr><td>grpc multiMode</td><td><a-tag color="green">[[ inbound.stream.grpc.multiMode ]]</a-tag></td></tr>
</template>
</table>
</td></tr>
diff --git a/web/service/sub.go b/web/service/sub.go
index ba70fe43..2aaee06a 100644
--- a/web/service/sub.go
+++ b/web/service/sub.go
@@ -102,80 +102,89 @@ func (s *SubService) getLink(inbound *model.Inbound, email string) string {
}
func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
- address := s.address
if inbound.Protocol != model.VMess {
return ""
}
+ obj := map[string]interface{}{
+ "v": "2",
+ "ps": email,
+ "add": s.address,
+ "port": inbound.Port,
+ "type": "none",
+ }
var stream map[string]interface{}
json.Unmarshal([]byte(inbound.StreamSettings), &stream)
network, _ := stream["network"].(string)
- typeStr := "none"
- host := ""
- path := ""
- sni := ""
- fp := ""
- var alpn []string
- allowInsecure := false
+ obj["net"] = network
switch network {
case "tcp":
tcp, _ := stream["tcpSettings"].(map[string]interface{})
header, _ := tcp["header"].(map[string]interface{})
- typeStr, _ = header["type"].(string)
+ typeStr, _ := header["type"].(string)
+ obj["type"] = typeStr
if typeStr == "http" {
request := header["request"].(map[string]interface{})
requestPath, _ := request["path"].([]interface{})
- path = requestPath[0].(string)
+ obj["path"] = requestPath[0].(string)
headers, _ := request["headers"].(map[string]interface{})
- host = searchHost(headers)
+ obj["host"] = searchHost(headers)
}
case "kcp":
kcp, _ := stream["kcpSettings"].(map[string]interface{})
header, _ := kcp["header"].(map[string]interface{})
- typeStr, _ = header["type"].(string)
- path, _ = kcp["seed"].(string)
+ obj["type"], _ = header["type"].(string)
+ obj["path"], _ = kcp["seed"].(string)
case "ws":
ws, _ := stream["wsSettings"].(map[string]interface{})
- path = ws["path"].(string)
+ obj["path"] = ws["path"].(string)
headers, _ := ws["headers"].(map[string]interface{})
- host = searchHost(headers)
+ obj["host"] = searchHost(headers)
case "http":
- network = "h2"
+ obj["net"] = "h2"
http, _ := stream["httpSettings"].(map[string]interface{})
- path, _ = http["path"].(string)
- host = searchHost(http)
+ obj["path"], _ = http["path"].(string)
+ obj["host"] = searchHost(http)
case "quic":
quic, _ := stream["quicSettings"].(map[string]interface{})
header := quic["header"].(map[string]interface{})
- typeStr, _ = header["type"].(string)
- host, _ = quic["security"].(string)
- path, _ = quic["key"].(string)
+ obj["type"], _ = header["type"].(string)
+ obj["host"], _ = quic["security"].(string)
+ obj["path"], _ = quic["key"].(string)
case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{})
- path = grpc["serviceName"].(string)
+ obj["path"] = grpc["serviceName"].(string)
+ if grpc["multiMode"].(bool) {
+ obj["type"] = "multi"
+ }
}
security, _ := stream["security"].(string)
+ obj["tls"] = security
if security == "tls" {
tlsSetting, _ := stream["tlsSettings"].(map[string]interface{})
alpns, _ := tlsSetting["alpn"].([]interface{})
- for _, a := range alpns {
- alpn = append(alpn, a.(string))
+ if len(alpns) > 0 {
+ var alpn []string
+ for _, a := range alpns {
+ alpn = append(alpn, a.(string))
+ }
+ obj["alpn"] = strings.Join(alpn, ",")
}
tlsSettings, _ := searchKey(tlsSetting, "settings")
if tlsSetting != nil {
if sniValue, ok := searchKey(tlsSettings, "serverName"); ok {
- sni, _ = sniValue.(string)
+ obj["sni"], _ = sniValue.(string)
}
if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok {
- fp, _ = fpValue.(string)
+ obj["fp"], _ = fpValue.(string)
}
if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok {
- allowInsecure, _ = insecure.(bool)
+ obj["allowInsecure"], _ = insecure.(bool)
}
}
serverName, _ := tlsSetting["serverName"].(string)
if serverName != "" {
- address = serverName
+ obj["add"] = serverName
}
}
@@ -187,24 +196,9 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
break
}
}
+ obj["id"] = clients[clientIndex].ID
+ obj["aid"] = clients[clientIndex].AlterIds
- obj := map[string]interface{}{
- "v": "2",
- "ps": email,
- "add": address,
- "port": inbound.Port,
- "id": clients[clientIndex].ID,
- "aid": clients[clientIndex].AlterIds,
- "net": network,
- "type": typeStr,
- "host": host,
- "path": path,
- "tls": security,
- "sni": sni,
- "fp": fp,
- "alpn": strings.Join(alpn, ","),
- "allowInsecure": allowInsecure,
- }
jsonStr, _ := json.MarshalIndent(obj, "", " ")
return "vmess://" + base64.StdEncoding.EncodeToString(jsonStr)
}
@@ -266,6 +260,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string)
+ if grpc["multiMode"].(bool) {
+ params["mode"] = "multi"
+ }
}
security, _ := stream["security"].(string)
@@ -444,6 +441,9 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string)
+ if grpc["multiMode"].(bool) {
+ params["mode"] = "multi"
+ }
}
security, _ := stream["security"].(string)