mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-19 21:42:24 +00:00
new - vmess security (inbound client side - outbound)
This commit is contained in:
parent
bda5c2c915
commit
93d52bc86c
15 changed files with 116 additions and 36 deletions
|
@ -250,6 +250,7 @@ Our platform offers compatibility with a diverse range of architectures and devi
|
||||||
- Spanish
|
- Spanish
|
||||||
- Indonesian
|
- Indonesian
|
||||||
- Ukrainian
|
- Ukrainian
|
||||||
|
- Turkish
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
@ -258,7 +259,7 @@ Our platform offers compatibility with a diverse range of architectures and devi
|
||||||
- Search within all inbounds and clients
|
- Search within all inbounds and clients
|
||||||
- Dark/Light theme
|
- Dark/Light theme
|
||||||
- Supports multi-user and multi-protocol
|
- Supports multi-user and multi-protocol
|
||||||
- Supports protocols, including VMess, VLESS, Trojan, Shadowsocks, Dokodemo-door, Socks, HTTP, wireguard
|
- Supports protocols, including VMESS, VLESS, Trojan, Shadowsocks, Dokodemo-door, Socks, HTTP, wireguard
|
||||||
- Supports XTLS native Protocols, including RPRX-Direct, Vision, REALITY
|
- Supports XTLS native Protocols, including RPRX-Direct, Vision, REALITY
|
||||||
- Traffic statistics, traffic limit, expiration time limit
|
- Traffic statistics, traffic limit, expiration time limit
|
||||||
- Customizable Xray configuration templates
|
- Customizable Xray configuration templates
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
type Protocol string
|
type Protocol string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VMess Protocol = "vmess"
|
VMESS Protocol = "vmess"
|
||||||
VLESS Protocol = "vless"
|
VLESS Protocol = "vless"
|
||||||
DOKODEMO Protocol = "dokodemo-door"
|
DOKODEMO Protocol = "dokodemo-door"
|
||||||
HTTP Protocol = "http"
|
HTTP Protocol = "http"
|
||||||
|
@ -86,6 +86,7 @@ type Setting struct {
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
Security string `json:"security"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Flow string `json:"flow"`
|
Flow string `json:"flow"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -85,16 +85,16 @@ require (
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||||
golang.org/x/arch v0.9.0 // indirect
|
golang.org/x/arch v0.9.0 // indirect
|
||||||
golang.org/x/crypto v0.26.0 // indirect
|
golang.org/x/crypto v0.26.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||||
golang.org/x/mod v0.20.0 // indirect
|
golang.org/x/mod v0.20.0 // indirect
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.23.0 // indirect
|
golang.org/x/sys v0.24.0 // indirect
|
||||||
golang.org/x/time v0.6.0 // indirect
|
golang.org/x/time v0.6.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240808171019-573a1156607a // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
|
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
|
||||||
|
|
12
go.sum
12
go.sum
|
@ -299,8 +299,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
@ -339,8 +339,8 @@ golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
|
@ -371,8 +371,8 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
|
||||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 h1:OsSGQeIIsyOEOimVxLEIL4rwGcnrjOydQaiA2bOnZUM=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240808171019-573a1156607a h1:EKiZZXueP9/T68B8Nl0GAx9cjbQnCId0yP3qPMgaaHs=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240808171019-573a1156607a/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
|
|
|
@ -282,6 +282,9 @@ func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_ut
|
||||||
|
|
||||||
usersData[0].ID = client.ID
|
usersData[0].ID = client.ID
|
||||||
usersData[0].Level = 8
|
usersData[0].Level = 8
|
||||||
|
if inbound.Protocol == model.VMESS {
|
||||||
|
usersData[0].Security = client.Security
|
||||||
|
}
|
||||||
if inbound.Protocol == model.VLESS {
|
if inbound.Protocol == model.VLESS {
|
||||||
usersData[0].Flow = client.Flow
|
usersData[0].Flow = client.Flow
|
||||||
usersData[0].Encryption = "none"
|
usersData[0].Encryption = "none"
|
||||||
|
@ -371,6 +374,7 @@ type UserVnext struct {
|
||||||
Encryption string `json:"encryption,omitempty"`
|
Encryption string `json:"encryption,omitempty"`
|
||||||
Flow string `json:"flow,omitempty"`
|
Flow string `json:"flow,omitempty"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
Security string `json:"security,omitempty"`
|
||||||
Level int `json:"level"`
|
Level int `json:"level"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ func (s *SubService) getLink(inbound *model.Inbound, email string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
|
func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
|
||||||
if inbound.Protocol != model.VMess {
|
if inbound.Protocol != model.VMESS {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
obj := map[string]interface{}{
|
obj := map[string]interface{}{
|
||||||
|
@ -281,6 +281,7 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj["id"] = clients[clientIndex].ID
|
obj["id"] = clients[clientIndex].ID
|
||||||
|
obj["scy"] = clients[clientIndex].Security
|
||||||
|
|
||||||
externalProxies, _ := stream["externalProxy"].([]interface{})
|
externalProxies, _ := stream["externalProxy"].([]interface{})
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,14 @@ const WireguardDomainStrategy = [
|
||||||
"ForceIPv6v4"
|
"ForceIPv6v4"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const USERS_SECURITY = {
|
||||||
|
AES_128_GCM: "aes-128-gcm",
|
||||||
|
CHACHA20_POLY1305: "chacha20-poly1305",
|
||||||
|
AUTO: "auto",
|
||||||
|
NONE: "none",
|
||||||
|
ZERO: "zero",
|
||||||
|
};
|
||||||
|
|
||||||
Object.freeze(Protocols);
|
Object.freeze(Protocols);
|
||||||
Object.freeze(SSMethods);
|
Object.freeze(SSMethods);
|
||||||
Object.freeze(TLS_FLOW_CONTROL);
|
Object.freeze(TLS_FLOW_CONTROL);
|
||||||
|
@ -76,6 +84,7 @@ Object.freeze(UTLS_FINGERPRINT);
|
||||||
Object.freeze(ALPN_OPTION);
|
Object.freeze(ALPN_OPTION);
|
||||||
Object.freeze(OutboundDomainStrategies);
|
Object.freeze(OutboundDomainStrategies);
|
||||||
Object.freeze(WireguardDomainStrategy);
|
Object.freeze(WireguardDomainStrategy);
|
||||||
|
Object.freeze(USERS_SECURITY);
|
||||||
|
|
||||||
|
|
||||||
class CommonClass {
|
class CommonClass {
|
||||||
|
@ -721,7 +730,7 @@ class Outbound extends CommonClass {
|
||||||
|
|
||||||
const port = json.port * 1;
|
const port = json.port * 1;
|
||||||
|
|
||||||
return new Outbound(json.ps, Protocols.VMess, new Outbound.VmessSettings(json.add, port, json.id), stream);
|
return new Outbound(json.ps, Protocols.VMess, new Outbound.VmessSettings(json.add, port, json.id, json.scy), stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromParamLink(link) {
|
static fromParamLink(link) {
|
||||||
|
@ -923,11 +932,12 @@ Outbound.DNSSettings = class extends CommonClass {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Outbound.VmessSettings = class extends CommonClass {
|
Outbound.VmessSettings = class extends CommonClass {
|
||||||
constructor(address, port, id) {
|
constructor(address, port, id, security) {
|
||||||
super();
|
super();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.security = security;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
|
@ -936,6 +946,7 @@ Outbound.VmessSettings = class extends CommonClass {
|
||||||
json.vnext[0].address,
|
json.vnext[0].address,
|
||||||
json.vnext[0].port,
|
json.vnext[0].port,
|
||||||
json.vnext[0].users[0].id,
|
json.vnext[0].users[0].id,
|
||||||
|
json.vnext[0].users[0].security,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +955,7 @@ Outbound.VmessSettings = class extends CommonClass {
|
||||||
vnext: [{
|
vnext: [{
|
||||||
address: this.address,
|
address: this.address,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
users: [{ id: this.id }],
|
users: [{ id: this.id, security: this.security }],
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,14 @@ const TCP_CONGESTION_OPTION = {
|
||||||
RENO: "reno",
|
RENO: "reno",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const USERS_SECURITY = {
|
||||||
|
AES_128_GCM: "aes-128-gcm",
|
||||||
|
CHACHA20_POLY1305: "chacha20-poly1305",
|
||||||
|
AUTO: "auto",
|
||||||
|
NONE: "none",
|
||||||
|
ZERO: "zero",
|
||||||
|
};
|
||||||
|
|
||||||
Object.freeze(Protocols);
|
Object.freeze(Protocols);
|
||||||
Object.freeze(SSMethods);
|
Object.freeze(SSMethods);
|
||||||
Object.freeze(XTLS_FLOW_CONTROL);
|
Object.freeze(XTLS_FLOW_CONTROL);
|
||||||
|
@ -122,6 +130,7 @@ Object.freeze(SNIFFING_OPTION);
|
||||||
Object.freeze(USAGE_OPTION);
|
Object.freeze(USAGE_OPTION);
|
||||||
Object.freeze(DOMAIN_STRATEGY_OPTION);
|
Object.freeze(DOMAIN_STRATEGY_OPTION);
|
||||||
Object.freeze(TCP_CONGESTION_OPTION);
|
Object.freeze(TCP_CONGESTION_OPTION);
|
||||||
|
Object.freeze(USERS_SECURITY);
|
||||||
|
|
||||||
class XrayCommonClass {
|
class XrayCommonClass {
|
||||||
|
|
||||||
|
@ -1446,20 +1455,21 @@ class Inbound extends XrayCommonClass {
|
||||||
this.sniffing = new Sniffing();
|
this.sniffing = new Sniffing();
|
||||||
}
|
}
|
||||||
|
|
||||||
genVmessLink(address = '', port = this.port, forceTls, remark = '', clientId) {
|
genVmessLink(address = '', port = this.port, forceTls, remark = '', clientId, security) {
|
||||||
if (this.protocol !== Protocols.VMESS) {
|
if (this.protocol !== Protocols.VMESS) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const security = forceTls == 'same' ? this.stream.security : forceTls;
|
const tls = forceTls == 'same' ? this.stream.security : forceTls;
|
||||||
let obj = {
|
let obj = {
|
||||||
v: '2',
|
v: '2',
|
||||||
ps: remark,
|
ps: remark,
|
||||||
add: address,
|
add: address,
|
||||||
port: port,
|
port: port,
|
||||||
id: clientId,
|
id: clientId,
|
||||||
|
scy: security,
|
||||||
net: this.stream.network,
|
net: this.stream.network,
|
||||||
type: 'none',
|
type: 'none',
|
||||||
tls: security,
|
tls: tls,
|
||||||
};
|
};
|
||||||
const network = this.stream.network;
|
const network = this.stream.network;
|
||||||
if (network === 'tcp') {
|
if (network === 'tcp') {
|
||||||
|
@ -1870,7 +1880,7 @@ class Inbound extends XrayCommonClass {
|
||||||
genLink(address = '', port = this.port, forceTls = 'same', remark = '', client) {
|
genLink(address = '', port = this.port, forceTls = 'same', remark = '', client) {
|
||||||
switch (this.protocol) {
|
switch (this.protocol) {
|
||||||
case Protocols.VMESS:
|
case Protocols.VMESS:
|
||||||
return this.genVmessLink(address, port, forceTls, remark, client.id);
|
return this.genVmessLink(address, port, forceTls, remark, client.id, client.security);
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow);
|
return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow);
|
||||||
case Protocols.SHADOWSOCKS:
|
case Protocols.SHADOWSOCKS:
|
||||||
|
@ -2007,24 +2017,24 @@ Inbound.Settings = class extends XrayCommonClass {
|
||||||
|
|
||||||
Inbound.VmessSettings = class extends Inbound.Settings {
|
Inbound.VmessSettings = class extends Inbound.Settings {
|
||||||
constructor(protocol,
|
constructor(protocol,
|
||||||
vmesses = [new Inbound.VmessSettings.Vmess()]) {
|
vmesses = [new Inbound.VmessSettings.VMESS()]) {
|
||||||
super(protocol);
|
super(protocol);
|
||||||
this.vmesses = vmesses;
|
this.vmesses = vmesses;
|
||||||
}
|
}
|
||||||
|
|
||||||
indexOfVmessById(id) {
|
indexOfVmessById(id) {
|
||||||
return this.vmesses.findIndex(vmess => vmess.id === id);
|
return this.vmesses.findIndex(VMESS => VMESS.id === id);
|
||||||
}
|
}
|
||||||
|
|
||||||
addVmess(vmess) {
|
addVmess(VMESS) {
|
||||||
if (this.indexOfVmessById(vmess.id) >= 0) {
|
if (this.indexOfVmessById(VMESS.id) >= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.vmesses.push(vmess);
|
this.vmesses.push(VMESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
delVmess(vmess) {
|
delVmess(VMESS) {
|
||||||
const i = this.indexOfVmessById(vmess.id);
|
const i = this.indexOfVmessById(VMESS.id);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
this.vmesses.splice(i, 1);
|
this.vmesses.splice(i, 1);
|
||||||
}
|
}
|
||||||
|
@ -2033,7 +2043,7 @@ Inbound.VmessSettings = class extends Inbound.Settings {
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
return new Inbound.VmessSettings(
|
return new Inbound.VmessSettings(
|
||||||
Protocols.VMESS,
|
Protocols.VMESS,
|
||||||
json.clients.map(client => Inbound.VmessSettings.Vmess.fromJson(client)),
|
json.clients.map(client => Inbound.VmessSettings.VMESS.fromJson(client)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2043,10 +2053,23 @@ Inbound.VmessSettings = class extends Inbound.Settings {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
|
|
||||||
constructor(id = RandomUtil.randomUUID(), email = RandomUtil.randomLowerAndNum(8), limitIp = 0, totalGB = 0, expiryTime = 0, enable = true, tgId = '', subId = RandomUtil.randomLowerAndNum(16), reset = 0) {
|
Inbound.VmessSettings.VMESS = class extends XrayCommonClass {
|
||||||
|
constructor(
|
||||||
|
id = RandomUtil.randomUUID(),
|
||||||
|
security = USERS_SECURITY.AUTO,
|
||||||
|
email = RandomUtil.randomLowerAndNum(8),
|
||||||
|
limitIp = 0,
|
||||||
|
totalGB = 0,
|
||||||
|
expiryTime = 0,
|
||||||
|
enable = true,
|
||||||
|
tgId = '',
|
||||||
|
subId = RandomUtil.randomLowerAndNum(16),
|
||||||
|
reset = 0
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.security = security;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.limitIp = limitIp;
|
this.limitIp = limitIp;
|
||||||
this.totalGB = totalGB;
|
this.totalGB = totalGB;
|
||||||
|
@ -2058,8 +2081,9 @@ Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json = {}) {
|
static fromJson(json = {}) {
|
||||||
return new Inbound.VmessSettings.Vmess(
|
return new Inbound.VmessSettings.VMESS(
|
||||||
json.id,
|
json.id,
|
||||||
|
json.security,
|
||||||
json.email,
|
json.email,
|
||||||
json.limitIp,
|
json.limitIp,
|
||||||
json.totalGB,
|
json.totalGB,
|
||||||
|
@ -2098,10 +2122,12 @@ Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
|
||||||
};
|
};
|
||||||
|
|
||||||
Inbound.VLESSSettings = class extends Inbound.Settings {
|
Inbound.VLESSSettings = class extends Inbound.Settings {
|
||||||
constructor(protocol,
|
constructor(
|
||||||
|
protocol,
|
||||||
vlesses = [new Inbound.VLESSSettings.VLESS()],
|
vlesses = [new Inbound.VLESSSettings.VLESS()],
|
||||||
decryption = 'none',
|
decryption = 'none',
|
||||||
fallbacks = []) {
|
fallbacks = []
|
||||||
|
) {
|
||||||
super(protocol);
|
super(protocol);
|
||||||
this.vlesses = vlesses;
|
this.vlesses = vlesses;
|
||||||
this.decryption = decryption;
|
this.decryption = decryption;
|
||||||
|
@ -2135,7 +2161,18 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
|
||||||
};
|
};
|
||||||
|
|
||||||
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
||||||
constructor(id = RandomUtil.randomUUID(), flow = '', email = RandomUtil.randomLowerAndNum(8), limitIp = 0, totalGB = 0, expiryTime = 0, enable = true, tgId = '', subId = RandomUtil.randomLowerAndNum(16), reset = 0) {
|
constructor(
|
||||||
|
id = RandomUtil.randomUUID(),
|
||||||
|
flow = '',
|
||||||
|
email = RandomUtil.randomLowerAndNum(8),
|
||||||
|
limitIp = 0,
|
||||||
|
totalGB = 0,
|
||||||
|
expiryTime = 0,
|
||||||
|
enable = true,
|
||||||
|
tgId = '',
|
||||||
|
subId = RandomUtil.randomLowerAndNum(16),
|
||||||
|
reset = 0
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
<a-form-item label='{{ i18n "pages.client.clientCount" }}' v-if="clientsBulkModal.emailMethod < 2">
|
<a-form-item label='{{ i18n "pages.client.clientCount" }}' v-if="clientsBulkModal.emailMethod < 2">
|
||||||
<a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number>
|
<a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item v-if="inbound.protocol === Protocols.VMESS" label='Security'>
|
||||||
|
<a-select v-model="clientsBulkModal.security" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label='Flow' v-if="clientsBulkModal.inbound.canEnableTlsFlow()">
|
<a-form-item label='Flow' v-if="clientsBulkModal.inbound.canEnableTlsFlow()">
|
||||||
<a-select v-model="clientsBulkModal.flow" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select v-model="clientsBulkModal.flow" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
|
||||||
|
@ -146,6 +151,7 @@
|
||||||
emailPostfix: "",
|
emailPostfix: "",
|
||||||
subId: "",
|
subId: "",
|
||||||
tgId: '',
|
tgId: '',
|
||||||
|
security: "auto",
|
||||||
flow: "",
|
flow: "",
|
||||||
delayedStart: false,
|
delayedStart: false,
|
||||||
reset: 0,
|
reset: 0,
|
||||||
|
@ -168,6 +174,7 @@
|
||||||
newClient.email += useNum ? prefix + i.toString() + postfix : prefix + postfix;
|
newClient.email += useNum ? prefix + i.toString() + postfix : prefix + postfix;
|
||||||
if (clientsBulkModal.subId.length > 0) newClient.subId = clientsBulkModal.subId;
|
if (clientsBulkModal.subId.length > 0) newClient.subId = clientsBulkModal.subId;
|
||||||
newClient.tgId = clientsBulkModal.tgId;
|
newClient.tgId = clientsBulkModal.tgId;
|
||||||
|
newClient.security = clientsBulkModal.security;
|
||||||
newClient.limitIp = clientsBulkModal.limitIp;
|
newClient.limitIp = clientsBulkModal.limitIp;
|
||||||
newClient._totalGB = clientsBulkModal.totalGB;
|
newClient._totalGB = clientsBulkModal.totalGB;
|
||||||
newClient._expiryTime = clientsBulkModal.expiryTime;
|
newClient._expiryTime = clientsBulkModal.expiryTime;
|
||||||
|
@ -203,6 +210,7 @@
|
||||||
this.emailPostfix = "";
|
this.emailPostfix = "";
|
||||||
this.subId = "";
|
this.subId = "";
|
||||||
this.tgId = '';
|
this.tgId = '';
|
||||||
|
this.security = "auto";
|
||||||
this.flow = "";
|
this.flow = "";
|
||||||
this.dbInbound = new DBInbound(dbInbound);
|
this.dbInbound = new DBInbound(dbInbound);
|
||||||
this.inbound = dbInbound.toInbound();
|
this.inbound = dbInbound.toInbound();
|
||||||
|
@ -211,7 +219,7 @@
|
||||||
},
|
},
|
||||||
newClient(protocol) {
|
newClient(protocol) {
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case Protocols.VMESS: return new Inbound.VmessSettings.Vmess();
|
case Protocols.VMESS: return new Inbound.VmessSettings.VMESS();
|
||||||
case Protocols.VLESS: return new Inbound.VLESSSettings.VLESS();
|
case Protocols.VLESS: return new Inbound.VLESSSettings.VLESS();
|
||||||
case Protocols.TROJAN: return new Inbound.TrojanSettings.Trojan();
|
case Protocols.TROJAN: return new Inbound.TrojanSettings.Trojan();
|
||||||
case Protocols.SHADOWSOCKS: return new Inbound.ShadowsocksSettings.Shadowsocks(clientsBulkModal.inbound.settings.shadowsockses[0].method);
|
case Protocols.SHADOWSOCKS: return new Inbound.ShadowsocksSettings.Shadowsocks(clientsBulkModal.inbound.settings.shadowsockses[0].method);
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
},
|
},
|
||||||
addClient(protocol, clients) {
|
addClient(protocol, clients) {
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case Protocols.VMESS: return clients.push(new Inbound.VmessSettings.Vmess());
|
case Protocols.VMESS: return clients.push(new Inbound.VmessSettings.VMESS());
|
||||||
case Protocols.VLESS: return clients.push(new Inbound.VLESSSettings.VLESS());
|
case Protocols.VLESS: return clients.push(new Inbound.VLESSSettings.VLESS());
|
||||||
case Protocols.TROJAN: return clients.push(new Inbound.TrojanSettings.Trojan());
|
case Protocols.TROJAN: return clients.push(new Inbound.TrojanSettings.Trojan());
|
||||||
case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks(clients[0].method));
|
case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks(clients[0].method));
|
||||||
|
|
|
@ -39,6 +39,11 @@
|
||||||
</template>
|
</template>
|
||||||
<a-input v-model.trim="client.id"></a-input>
|
<a-input v-model.trim="client.id"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item v-if="inbound.protocol === Protocols.VMESS" label='Security'>
|
||||||
|
<a-select v-model="client.security" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item v-if="client.email && app.subSettings.enable">
|
<a-form-item v-if="client.email && app.subSettings.enable">
|
||||||
<template slot="label">
|
<template slot="label">
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
|
|
|
@ -160,6 +160,11 @@
|
||||||
<a-form-item label='ID'>
|
<a-form-item label='ID'>
|
||||||
<a-input v-model.trim="outbound.settings.id"></a-input>
|
<a-input v-model.trim="outbound.settings.id"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label='Security'>
|
||||||
|
<a-select v-model="outbound.settings.security" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<!-- vless settings -->
|
<!-- vless settings -->
|
||||||
<template v-if="outbound.canEnableTlsFlow()">
|
<template v-if="outbound.canEnableTlsFlow()">
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
<tr class="client-table-header">
|
<tr class="client-table-header">
|
||||||
<th>{{ i18n "pages.inbounds.email" }}</th>
|
<th>{{ i18n "pages.inbounds.email" }}</th>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
<th>Security</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="(client, index) in inbound.settings.vmesses" :class="index % 2 == 1 ? 'client-table-odd-row' : ''">
|
<tr v-for="(client, index) in inbound.settings.vmesses" :class="index % 2 == 1 ? 'client-table-odd-row' : ''">
|
||||||
<td>[[ client.email ]]</td>
|
<td>[[ client.email ]]</td>
|
||||||
<td>[[ client.id ]]</td>
|
<td>[[ client.id ]]</td>
|
||||||
|
<td>[[ client.security ]]</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
|
|
@ -523,7 +523,9 @@
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
await PromiseUtil.sleep(5000);
|
await PromiseUtil.sleep(5000);
|
||||||
let { webCertFile, webKeyFile, webDomain: host, webPort: port, webBasePath: base } = this.allSetting;
|
var { webCertFile, webKeyFile, webDomain: host, webPort: port, webBasePath: base } = this.allSetting;
|
||||||
|
if (host == this.oldAllSetting.webDomain) host = null;
|
||||||
|
if (port == this.oldAllSetting.webPort) port = null;
|
||||||
const isTLS = webCertFile !== "" || webKeyFile !== "";
|
const isTLS = webCertFile !== "" || webKeyFile !== "";
|
||||||
const url = buildURL({ host, port, isTLS, base, path: "panel/settings" });
|
const url = buildURL({ host, port, isTLS, base, path: "panel/settings" });
|
||||||
window.location.replace(url);
|
window.location.replace(url);
|
||||||
|
|
|
@ -490,6 +490,7 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
|
||||||
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
|
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
|
||||||
"email": client.Email,
|
"email": client.Email,
|
||||||
"id": client.ID,
|
"id": client.ID,
|
||||||
|
"security": client.Security,
|
||||||
"flow": client.Flow,
|
"flow": client.Flow,
|
||||||
"password": client.Password,
|
"password": client.Password,
|
||||||
"cipher": cipher,
|
"cipher": cipher,
|
||||||
|
@ -711,6 +712,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
|
||||||
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
|
err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
|
||||||
"email": clients[0].Email,
|
"email": clients[0].Email,
|
||||||
"id": clients[0].ID,
|
"id": clients[0].ID,
|
||||||
|
"security": clients[0].Security,
|
||||||
"flow": clients[0].Flow,
|
"flow": clients[0].Flow,
|
||||||
"password": clients[0].Password,
|
"password": clients[0].Password,
|
||||||
"cipher": cipher,
|
"cipher": cipher,
|
||||||
|
@ -1559,6 +1561,7 @@ func (s *InboundService) ResetClientTraffic(id int, clientEmail string) (bool, e
|
||||||
err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]interface{}{
|
err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]interface{}{
|
||||||
"email": client.Email,
|
"email": client.Email,
|
||||||
"id": client.ID,
|
"id": client.ID,
|
||||||
|
"security": client.Security,
|
||||||
"flow": client.Flow,
|
"flow": client.Flow,
|
||||||
"password": client.Password,
|
"password": client.Password,
|
||||||
"cipher": cipher,
|
"cipher": cipher,
|
||||||
|
|
Loading…
Reference in a new issue