[feature] add grpc multiMode

This commit is contained in:
Alireza Ahmadi
2023-04-27 22:35:26 +02:00
parent 7ecb73af8c
commit dd11585074
5 changed files with 122 additions and 116 deletions

View File

@@ -29,20 +29,6 @@ const SSMethods = {
BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305',
};
const RULE_IP = {
PRIVATE: 'geoip:private',
CN: 'geoip:cn',
};
const RULE_DOMAIN = {
ADS: 'geosite:category-ads',
ADS_ALL: 'geosite:category-ads-all',
CN: 'geosite:cn',
GOOGLE: 'geosite:google',
FACEBOOK: 'geosite:facebook',
SPEEDTEST: 'geosite:speedtest',
};
const TLS_FLOW_CONTROL = {
VISION: "xtls-rprx-vision",
VISION_UDP443: "xtls-rprx-vision-udp443",
@@ -97,8 +83,6 @@ const ALPN_OPTION = {
Object.freeze(Protocols);
Object.freeze(VmessMethods);
Object.freeze(SSMethods);
Object.freeze(RULE_IP);
Object.freeze(RULE_DOMAIN);
Object.freeze(TLS_FLOW_CONTROL);
Object.freeze(TLS_VERSION_OPTION);
Object.freeze(TLS_CIPHER_OPTION);
@@ -451,18 +435,20 @@ 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,
}
}
}
@@ -1106,50 +1092,6 @@ class Inbound extends XrayCommonClass {
if (this.protocol !== Protocols.VMESS) {
return '';
}
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') {
let request = tcp.request;
path = request.path.join(',');
let index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
host = request.headers[index].value;
}
}
} else if (network === 'kcp') {
let kcp = this.stream.kcp;
type = kcp.type;
path = kcp.seed;
} else if (network === 'ws') {
let ws = this.stream.ws;
path = ws.path;
let index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
host = ws.headers[index].value;
}
} else if (network === 'http') {
network = 'h2';
path = this.stream.http.path;
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;
} else if (network === 'grpc') {
path = this.stream.grpc.serviceName;
}
if (this.stream.security === 'tls') {
if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
address = this.stream.tls.server;
}
}
let obj = {
v: '2',
ps: remark,
@@ -1157,16 +1099,66 @@ class Inbound extends XrayCommonClass {
port: this.port,
id: this.settings.vmesses[clientIndex].id,
aid: this.settings.vmesses[clientIndex].alterId,
net: network,
type: type,
host: host,
path: path,
net: this.stream.network,
type: 'none',
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,
};
let network = this.stream.network;
if (network === 'tcp') {
let tcp = this.stream.tcp;
obj.type = tcp.type;
if (tcp.type === 'http') {
let request = tcp.request;
obj.path = request.path.join(',');
let index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
obj.host = request.headers[index].value;
}
}
} else if (network === 'kcp') {
let kcp = this.stream.kcp;
obj.type = kcp.type;
obj.path = kcp.seed;
} else if (network === 'ws') {
let ws = this.stream.ws;
obj.path = ws.path;
let index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
if (index >= 0) {
obj.host = ws.headers[index].value;
}
} else if (network === 'http') {
obj.net = 'h2';
obj.path = this.stream.http.path;
obj.host = this.stream.http.host.join(',');
} else if (network === 'quic') {
obj.type = this.stream.quic.type;
obj.host = this.stream.quic.security;
obj.path = this.stream.quic.key;
} else if (network === 'grpc') {
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)) {
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;
}
}
return 'vmess://' + base64(JSON.stringify(obj, null, 2));
}
@@ -1219,6 +1211,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;
}
@@ -1332,6 +1327,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;
}

View File

@@ -9,6 +9,14 @@
</a-form-item>
</td>
</tr>
<tr>
<td>MultiMode</td>
<td>
<a-form-item>
<a-switch v-model="inbound.stream.grpc.multiMode"></a-switch>
</a-form-item>
</td>
</tr>
</table>
</a-form>
{{end}}

View File

@@ -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>

View File

@@ -820,7 +820,6 @@
}
},
});
</script>
{{template "inboundModal"}}

View File

@@ -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)
@@ -415,6 +412,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)