diff --git a/README.md b/README.md index d6d88474b..554ef6a69 100644 --- a/README.md +++ b/README.md @@ -250,6 +250,7 @@ Our platform offers compatibility with a diverse range of architectures and devi - Spanish - Indonesian - Ukrainian +- Turkish ## Features @@ -258,7 +259,7 @@ Our platform offers compatibility with a diverse range of architectures and devi - Search within all inbounds and clients - Dark/Light theme - 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 - Traffic statistics, traffic limit, expiration time limit - Customizable Xray configuration templates diff --git a/database/model/model.go b/database/model/model.go index 921ab2115..402565b65 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -10,7 +10,7 @@ import ( type Protocol string const ( - VMess Protocol = "vmess" + VMESS Protocol = "vmess" VLESS Protocol = "vless" DOKODEMO Protocol = "dokodemo-door" HTTP Protocol = "http" @@ -86,6 +86,7 @@ type Setting struct { type Client struct { ID string `json:"id"` + Security string `json:"security"` Password string `json:"password"` Flow string `json:"flow"` Email string `json:"email"` diff --git a/go.mod b/go.mod index c6923faaa..b2462720a 100644 --- a/go.mod +++ b/go.mod @@ -85,16 +85,16 @@ require ( go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect golang.org/x/arch v0.9.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/net v0.28.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/tools v0.24.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // 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 gopkg.in/yaml.v3 v3.0.1 // indirect gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect diff --git a/go.sum b/go.sum index 98001f22a..969a15c49 100644 --- a/go.sum +++ b/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/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-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 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.5.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.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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-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/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 h1:OsSGQeIIsyOEOimVxLEIL4rwGcnrjOydQaiA2bOnZUM= -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 h1:EKiZZXueP9/T68B8Nl0GAx9cjbQnCId0yP3qPMgaaHs= +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.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= diff --git a/sub/subJsonService.go b/sub/subJsonService.go index 742c403cd..8d90876fd 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -282,6 +282,9 @@ func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_ut usersData[0].ID = client.ID usersData[0].Level = 8 + if inbound.Protocol == model.VMESS { + usersData[0].Security = client.Security + } if inbound.Protocol == model.VLESS { usersData[0].Flow = client.Flow usersData[0].Encryption = "none" @@ -371,6 +374,7 @@ type UserVnext struct { Encryption string `json:"encryption,omitempty"` Flow string `json:"flow,omitempty"` ID string `json:"id"` + Security string `json:"security,omitempty"` Level int `json:"level"` } diff --git a/sub/subService.go b/sub/subService.go index 0ee181292..2f5b2f98b 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -168,7 +168,7 @@ func (s *SubService) getLink(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 "" } obj := map[string]interface{}{ @@ -281,6 +281,7 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } } obj["id"] = clients[clientIndex].ID + obj["scy"] = clients[clientIndex].Security externalProxies, _ := stream["externalProxy"].([]interface{}) diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 1ca6cee48..f1909552b 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -69,6 +69,14 @@ const WireguardDomainStrategy = [ "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(SSMethods); Object.freeze(TLS_FLOW_CONTROL); @@ -76,6 +84,7 @@ Object.freeze(UTLS_FINGERPRINT); Object.freeze(ALPN_OPTION); Object.freeze(OutboundDomainStrategies); Object.freeze(WireguardDomainStrategy); +Object.freeze(USERS_SECURITY); class CommonClass { @@ -721,7 +730,7 @@ class Outbound extends CommonClass { 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) { @@ -923,11 +932,12 @@ Outbound.DNSSettings = class extends CommonClass { } }; Outbound.VmessSettings = class extends CommonClass { - constructor(address, port, id) { + constructor(address, port, id, security) { super(); this.address = address; this.port = port; this.id = id; + this.security = security; } static fromJson(json = {}) { @@ -936,6 +946,7 @@ Outbound.VmessSettings = class extends CommonClass { json.vnext[0].address, json.vnext[0].port, json.vnext[0].users[0].id, + json.vnext[0].users[0].security, ); } @@ -944,7 +955,7 @@ Outbound.VmessSettings = class extends CommonClass { vnext: [{ address: this.address, port: this.port, - users: [{ id: this.id }], + users: [{ id: this.id, security: this.security }], }], }; } diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index d239160b9..0e4e2e725 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -110,6 +110,14 @@ const TCP_CONGESTION_OPTION = { 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(SSMethods); Object.freeze(XTLS_FLOW_CONTROL); @@ -122,6 +130,7 @@ Object.freeze(SNIFFING_OPTION); Object.freeze(USAGE_OPTION); Object.freeze(DOMAIN_STRATEGY_OPTION); Object.freeze(TCP_CONGESTION_OPTION); +Object.freeze(USERS_SECURITY); class XrayCommonClass { @@ -1446,20 +1455,21 @@ class Inbound extends XrayCommonClass { 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) { return ''; } - const security = forceTls == 'same' ? this.stream.security : forceTls; + const tls = forceTls == 'same' ? this.stream.security : forceTls; let obj = { v: '2', ps: remark, add: address, port: port, id: clientId, + scy: security, net: this.stream.network, type: 'none', - tls: security, + tls: tls, }; const network = this.stream.network; if (network === 'tcp') { @@ -1870,7 +1880,7 @@ class Inbound extends XrayCommonClass { genLink(address = '', port = this.port, forceTls = 'same', remark = '', client) { switch (this.protocol) { 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: return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow); case Protocols.SHADOWSOCKS: @@ -2007,24 +2017,24 @@ Inbound.Settings = class extends XrayCommonClass { Inbound.VmessSettings = class extends Inbound.Settings { constructor(protocol, - vmesses = [new Inbound.VmessSettings.Vmess()]) { + vmesses = [new Inbound.VmessSettings.VMESS()]) { super(protocol); this.vmesses = vmesses; } indexOfVmessById(id) { - return this.vmesses.findIndex(vmess => vmess.id === id); + return this.vmesses.findIndex(VMESS => VMESS.id === id); } - addVmess(vmess) { - if (this.indexOfVmessById(vmess.id) >= 0) { + addVmess(VMESS) { + if (this.indexOfVmessById(VMESS.id) >= 0) { return false; } - this.vmesses.push(vmess); + this.vmesses.push(VMESS); } - delVmess(vmess) { - const i = this.indexOfVmessById(vmess.id); + delVmess(VMESS) { + const i = this.indexOfVmessById(VMESS.id); if (i >= 0) { this.vmesses.splice(i, 1); } @@ -2033,7 +2043,7 @@ Inbound.VmessSettings = class extends Inbound.Settings { static fromJson(json = {}) { return new Inbound.VmessSettings( 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(); this.id = id; + this.security = security; this.email = email; this.limitIp = limitIp; this.totalGB = totalGB; @@ -2058,8 +2081,9 @@ Inbound.VmessSettings.Vmess = class extends XrayCommonClass { } static fromJson(json = {}) { - return new Inbound.VmessSettings.Vmess( + return new Inbound.VmessSettings.VMESS( json.id, + json.security, json.email, json.limitIp, json.totalGB, @@ -2098,10 +2122,12 @@ Inbound.VmessSettings.Vmess = class extends XrayCommonClass { }; Inbound.VLESSSettings = class extends Inbound.Settings { - constructor(protocol, + constructor( + protocol, vlesses = [new Inbound.VLESSSettings.VLESS()], decryption = 'none', - fallbacks = []) { + fallbacks = [] + ) { super(protocol); this.vlesses = vlesses; this.decryption = decryption; @@ -2135,7 +2161,18 @@ Inbound.VLESSSettings = class extends Inbound.Settings { }; 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(); this.id = id; this.flow = flow; diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html index 5e6d1a1f4..3cdc5ff68 100644 --- a/web/html/xui/client_bulk_modal.html +++ b/web/html/xui/client_bulk_modal.html @@ -28,6 +28,11 @@ + + + [[ key ]] + + {{ i18n "none" }} @@ -146,6 +151,7 @@ emailPostfix: "", subId: "", tgId: '', + security: "auto", flow: "", delayedStart: false, reset: 0, @@ -168,6 +174,7 @@ newClient.email += useNum ? prefix + i.toString() + postfix : prefix + postfix; if (clientsBulkModal.subId.length > 0) newClient.subId = clientsBulkModal.subId; newClient.tgId = clientsBulkModal.tgId; + newClient.security = clientsBulkModal.security; newClient.limitIp = clientsBulkModal.limitIp; newClient._totalGB = clientsBulkModal.totalGB; newClient._expiryTime = clientsBulkModal.expiryTime; @@ -203,6 +210,7 @@ this.emailPostfix = ""; this.subId = ""; this.tgId = ''; + this.security = "auto"; this.flow = ""; this.dbInbound = new DBInbound(dbInbound); this.inbound = dbInbound.toInbound(); @@ -211,7 +219,7 @@ }, newClient(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.TROJAN: return new Inbound.TrojanSettings.Trojan(); case Protocols.SHADOWSOCKS: return new Inbound.ShadowsocksSettings.Shadowsocks(clientsBulkModal.inbound.settings.shadowsockses[0].method); diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index 83fa71a37..aa62e02a7 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -61,7 +61,7 @@ }, addClient(protocol, clients) { 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.TROJAN: return clients.push(new Inbound.TrojanSettings.Trojan()); case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks(clients[0].method)); diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html index 845f9408d..aa5588244 100644 --- a/web/html/xui/form/client.html +++ b/web/html/xui/form/client.html @@ -39,6 +39,11 @@ + + + [[ key ]] + +