diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 435391df..96ef2d7b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,8 +7,9 @@ on: push: branches: - main + tags: + - "v*.*.*" paths: - - '.github/workflows/release.yml' - '**.js' - '**.css' - '**.html' @@ -38,7 +39,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -84,7 +85,7 @@ jobs: cd x-ui/bin # Download dependencies - Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.8.29/" + Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.9.5/" if [ "${{ matrix.platform }}" == "amd64" ]; then wget -q ${Xray_URL}Xray-linux-64.zip unzip Xray-linux-64.zip @@ -135,10 +136,13 @@ jobs: - name: Upload files to GH release uses: svenstaro/upload-release-action@v2 - if: github.event_name == 'release' && github.event.action == 'published' + if: | + (github.event_name == 'release' && github.event.action == 'published') || + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) with: repo_token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ github.ref }} file: x-ui-linux-${{ matrix.platform }}.tar.gz asset_name: x-ui-linux-${{ matrix.platform }}.tar.gz + overwrite: true prerelease: true diff --git a/DockerInit.sh b/DockerInit.sh index 10d4c121..d08eaf61 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -27,7 +27,7 @@ case $1 in esac mkdir -p build/bin cd build/bin -wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.8.29/Xray-linux-${ARCH}.zip" +wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.9.5/Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip" rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat mv xray "xray-linux-${FNAME}" diff --git a/config/version b/config/version index ba5c9fca..4484c2b2 100644 --- a/config/version +++ b/config/version @@ -1 +1 @@ -2.6.7 \ No newline at end of file +2.6.8 \ No newline at end of file diff --git a/database/model/model.go b/database/model/model.go index a34dc097..c8712990 100644 --- a/database/model/model.go +++ b/database/model/model.go @@ -107,3 +107,10 @@ type Client struct { CreatedAt int64 `json:"created_at,omitempty"` UpdatedAt int64 `json:"updated_at,omitempty"` } + +type VLESSSettings struct { + Clients []Client `json:"clients"` + Decryption string `json:"decryption"` + Encryption string `json:"encryption"` + Fallbacks []any `json:"fallbacks"` +} diff --git a/go.mod b/go.mod index bd265bf9..9277a466 100644 --- a/go.mod +++ b/go.mod @@ -14,10 +14,10 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pelletier/go-toml/v2 v2.2.4 github.com/robfig/cron/v3 v3.0.1 - github.com/shirou/gopsutil/v4 v4.25.7 + github.com/shirou/gopsutil/v4 v4.25.8 github.com/valyala/fasthttp v1.65.0 github.com/xlzd/gotp v0.1.0 - github.com/xtls/xray-core v1.250803.1-0.20250829143322-81b7cd718ad5 + github.com/xtls/xray-core v1.250905.0 go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.41.0 golang.org/x/text v0.28.0 @@ -28,7 +28,8 @@ require ( require ( github.com/andybalholm/brotli v1.2.0 // indirect - github.com/bytedance/sonic v1.14.0 // indirect + github.com/bytedance/gopkg v0.1.3 // indirect + github.com/bytedance/sonic v1.14.1 // indirect github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -67,8 +68,8 @@ require ( github.com/refraction-networking/utls v1.8.0 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/sagernet/sing v0.7.5 // indirect - github.com/sagernet/sing-shadowsocks v0.2.8 // indirect + github.com/sagernet/sing v0.7.7 // indirect + github.com/sagernet/sing-shadowsocks v0.2.9 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect github.com/tklauser/go-sysconf v0.3.15 // indirect github.com/tklauser/numcpus v0.10.0 // indirect @@ -79,16 +80,16 @@ require ( github.com/valyala/fastjson v1.6.4 // indirect github.com/vishvananda/netlink v1.3.1 // indirect github.com/vishvananda/netns v0.0.5 // indirect - github.com/xtls/reality v0.0.0-20250828044527-046fad5ab64f // indirect + github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/mock v0.6.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/arch v0.20.0 // indirect + golang.org/x/arch v0.21.0 // indirect golang.org/x/mod v0.27.0 // indirect golang.org/x/net v0.43.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/time v0.12.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/time v0.13.0 // indirect golang.org/x/tools v0.36.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb // indirect diff --git a/go.sum b/go.sum index a285204d..d5ece387 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,10 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= -github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= -github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w= +github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc= github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= @@ -132,14 +134,14 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sagernet/sing v0.7.5 h1:gNMwZCLPqR+4e0g6dwi0sSsrvOmoMjpZgqxKsuJZatc= -github.com/sagernet/sing v0.7.5/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE= -github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI= +github.com/sagernet/sing v0.7.7 h1:o46FzVZS+wKbBMEkMEdEHoVZxyM9jvfRpKXc7pEgS/c= +github.com/sagernet/sing v0.7.7/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-shadowsocks v0.2.9 h1:Paep5zCszRKsEn8587O0MnhFWKJwDW1Y4zOYYlIxMkM= +github.com/sagernet/sing-shadowsocks v0.2.9/go.mod h1:TE/Z6401Pi8tgr0nBZcM/xawAI6u3F6TTbz4nH/qw+8= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= -github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM= -github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U= +github.com/shirou/gopsutil/v4 v4.25.8 h1:NnAsw9lN7587WHxjJA9ryDnqhJpFH6A+wagYWTOH970= +github.com/shirou/gopsutil/v4 v4.25.8/go.mod h1:q9QdMmfAOVIw7a+eF86P7ISEU6ka+NLgkUxlopV4RwI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -172,10 +174,10 @@ github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zd github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= -github.com/xtls/reality v0.0.0-20250828044527-046fad5ab64f h1:o1Kryl9qEYYzNep9RId9DM1kBn8tBrcK5UJnti/l0NI= -github.com/xtls/reality v0.0.0-20250828044527-046fad5ab64f/go.mod h1:XxvnCCgBee4WWE0bc4E+a7wbk8gkJ/rS0vNVNtC5qp0= -github.com/xtls/xray-core v1.250803.1-0.20250829143322-81b7cd718ad5 h1:rBqCVgic8yIUVHB4h26K8JNuwJuNj45egsdXxwEvA7E= -github.com/xtls/xray-core v1.250803.1-0.20250829143322-81b7cd718ad5/go.mod h1:WB/73DmN9Vs7lxtx4Xc/D0Ub1VUu06hAh1mMh8JN2uM= +github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c h1:LHLhQY3mKXSpTcQAkjFR4/6ar3rXjQryNeM7khK3AHU= +github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c/go.mod h1:XxvnCCgBee4WWE0bc4E+a7wbk8gkJ/rS0vNVNtC5qp0= +github.com/xtls/xray-core v1.250905.0 h1:VNL3l/6fcwyeYXJTRbf+TYqPfJYkk0Wmmz7qoQNkxY8= +github.com/xtls/xray-core v1.250905.0/go.mod h1:WB/73DmN9Vs7lxtx4Xc/D0Ub1VUu06hAh1mMh8JN2uM= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= @@ -198,28 +200,28 @@ go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= -golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/arch v0.21.0 h1:iTC9o7+wP6cPWpDWkivCvQFGAHDQ59SrSxsLPcnkArw= +golang.org/x/arch v0.21.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= diff --git a/sub/subController.go b/sub/subController.go index 2f22ecab..3f053740 100644 --- a/sub/subController.go +++ b/sub/subController.go @@ -53,7 +53,6 @@ func (a *SUBController) initRouter(g *gin.RouterGroup) { gJson := g.Group(a.subJsonPath) gLink.GET(":subid", a.subs) - gJson.GET(":subid", a.subJsons) } @@ -85,7 +84,7 @@ func (a *SUBController) subs(c *gin.Context) { // Add headers c.Writer.Header().Set("Subscription-Userinfo", header) c.Writer.Header().Set("Profile-Update-Interval", a.updateInterval) - c.Writer.Header().Set("Profile-Title", "base64:" + base64.StdEncoding.EncodeToString([]byte(a.subTitle))) + c.Writer.Header().Set("Profile-Title", "base64:"+base64.StdEncoding.EncodeToString([]byte(a.subTitle))) if a.subEncrypt { c.String(200, base64.StdEncoding.EncodeToString([]byte(result))) @@ -119,7 +118,7 @@ func (a *SUBController) subJsons(c *gin.Context) { // Add headers c.Writer.Header().Set("Subscription-Userinfo", header) c.Writer.Header().Set("Profile-Update-Interval", a.updateInterval) - c.Writer.Header().Set("Profile-Title", "base64:" + base64.StdEncoding.EncodeToString([]byte(a.subTitle))) + c.Writer.Header().Set("Profile-Title", "base64:"+base64.StdEncoding.EncodeToString([]byte(a.subTitle))) c.String(200, jsonSub) } diff --git a/sub/subJsonService.go b/sub/subJsonService.go index 680a01c0..def8b855 100644 --- a/sub/subJsonService.go +++ b/sub/subJsonService.go @@ -184,8 +184,14 @@ func (s *SubJsonService) getConfig(inbound *model.Inbound, client model.Client, var newOutbounds []json_util.RawMessage switch inbound.Protocol { - case "vmess", "vless": - newOutbounds = append(newOutbounds, s.genVnext(inbound, streamSettings, client)) + case "vmess": + newOutbounds = append(newOutbounds, s.genVnext(inbound, streamSettings, client, "")) + case "vless": + var vlessSettings model.VLESSSettings + _ = json.Unmarshal([]byte(inbound.Settings), &vlessSettings) + + newOutbounds = append(newOutbounds, + s.genVnext(inbound, streamSettings, client, vlessSettings.Encryption)) case "trojan", "shadowsocks": newOutbounds = append(newOutbounds, s.genServer(inbound, streamSettings, client)) } @@ -284,7 +290,7 @@ func (s *SubJsonService) realityData(rData map[string]any) map[string]any { return rltyData } -func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client) json_util.RawMessage { +func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client, encryption string) json_util.RawMessage { outbound := Outbound{} usersData := make([]UserVnext, 1) @@ -295,7 +301,7 @@ func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_ut } if inbound.Protocol == model.VLESS { usersData[0].Flow = client.Flow - usersData[0].Encryption = "none" + usersData[0].Encryption = encryption } vnextData := make([]VnextSetting, 1) diff --git a/sub/subService.go b/sub/subService.go index dfb0863e..e6e25e3a 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -313,6 +313,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { if inbound.Protocol != model.VLESS { return "" } + var vlessSettings model.VLESSSettings + _ = json.Unmarshal([]byte(inbound.Settings), &vlessSettings) + var stream map[string]any json.Unmarshal([]byte(inbound.StreamSettings), &stream) clients, _ := s.inboundService.GetClients(inbound) @@ -327,6 +330,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { port := inbound.Port streamNetwork := stream["network"].(string) params := make(map[string]string) + if vlessSettings.Encryption != "" { + params["encryption"] = vlessSettings.Encryption + } params["type"] = streamNetwork switch streamNetwork { diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js index c91dbd11..c2467c36 100644 --- a/web/assets/js/model/inbound.js +++ b/web/assets/js/model/inbound.js @@ -11,10 +11,8 @@ const Protocols = { const SSMethods = { AES_256_GCM: 'aes-256-gcm', - AES_128_GCM: 'aes-128-gcm', CHACHA20_POLY1305: 'chacha20-poly1305', CHACHA20_IETF_POLY1305: 'chacha20-ietf-poly1305', - XCHACHA20_POLY1305: 'xchacha20-poly1305', XCHACHA20_IETF_POLY1305: 'xchacha20-ietf-poly1305', BLAKE3_AES_128_GCM: '2022-blake3-aes-128-gcm', BLAKE3_AES_256_GCM: '2022-blake3-aes-256-gcm', @@ -1301,6 +1299,7 @@ class Inbound extends XrayCommonClass { const security = forceTls == 'same' ? this.stream.security : forceTls; const params = new Map(); params.set("type", this.stream.network); + params.set("encryption", this.settings.encryption); switch (type) { case "tcp": const tcp = this.stream.tcp; @@ -1859,13 +1858,17 @@ Inbound.VLESSSettings = class extends Inbound.Settings { constructor( protocol, vlesses = [new Inbound.VLESSSettings.VLESS()], - decryption = 'none', - fallbacks = [] + decryption = "none", + encryption = "none", + fallbacks = [], + selectedAuth = undefined, ) { super(protocol); this.vlesses = vlesses; this.decryption = decryption; + this.encryption = encryption; this.fallbacks = fallbacks; + this.selectedAuth = selectedAuth; } addFallback() { @@ -1876,22 +1879,43 @@ Inbound.VLESSSettings = class extends Inbound.Settings { this.fallbacks.splice(index, 1); } - // decryption should be set to static value static fromJson(json = {}) { - return new Inbound.VLESSSettings( + const obj = new Inbound.VLESSSettings( Protocols.VLESS, - json.clients.map(client => Inbound.VLESSSettings.VLESS.fromJson(client)), - json.decryption || 'none', - Inbound.VLESSSettings.Fallback.fromJson(json.fallbacks),); + (json.clients || []).map(client => Inbound.VLESSSettings.VLESS.fromJson(client)), + json.decryption, + json.encryption, + Inbound.VLESSSettings.Fallback.fromJson(json.fallbacks || []), + json.selectedAuth + ); + return obj; } + toJson() { - return { + const json = { clients: Inbound.VLESSSettings.toJsonArray(this.vlesses), - decryption: this.decryption, - fallbacks: Inbound.VLESSSettings.toJsonArray(this.fallbacks), }; + + if (this.decryption) { + json.decryption = this.decryption; + } + + if (this.encryption) { + json.encryption = this.encryption; + } + + if (this.fallbacks && this.fallbacks.length > 0) { + json.fallbacks = Inbound.VLESSSettings.toJsonArray(this.fallbacks); + } + if (this.selectedAuth) { + json.selectedAuth = this.selectedAuth; + } + + return json; } + + }; Inbound.VLESSSettings.VLESS = class extends XrayCommonClass { diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index ee78795f..2d5660fb 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -813,7 +813,7 @@ class Outbound extends CommonClass { var settings; switch (protocol) { case Protocols.VLESS: - settings = new Outbound.VLESSSettings(address, port, userData, url.searchParams.get('flow') ?? ''); + settings = new Outbound.VLESSSettings(address, port, userData, url.searchParams.get('flow') ?? '', url.searchParams.get('encryption') ?? 'none'); break; case Protocols.Trojan: settings = new Outbound.TrojanSettings(address, port, userData); @@ -1046,13 +1046,13 @@ Outbound.VmessSettings = class extends CommonClass { } }; Outbound.VLESSSettings = class extends CommonClass { - constructor(address, port, id, flow, encryption = 'none') { + constructor(address, port, id, flow, encryption) { super(); this.address = address; this.port = port; this.id = id; this.flow = flow; - this.encryption = encryption + this.encryption = encryption; } static fromJson(json = {}) { @@ -1071,7 +1071,7 @@ Outbound.VLESSSettings = class extends CommonClass { vnext: [{ address: this.address, port: this.port, - users: [{ id: this.id, flow: this.flow, encryption: 'none', }], + users: [{ id: this.id, flow: this.flow, encryption: this.encryption }], }], }; } diff --git a/web/assets/js/util/date-util.js b/web/assets/js/util/date-util.js index 9b4b0f81..bbca1272 100644 --- a/web/assets/js/util/date-util.js +++ b/web/assets/js/util/date-util.js @@ -134,7 +134,7 @@ class DateUtil { } static formatMillis(millis) { - return moment(millis).format('YYYY-M-D H:m:s'); + return moment(millis).format('YYYY-M-D HH:mm:ss'); } static firstDayOfMonth() { diff --git a/web/controller/api.go b/web/controller/api.go index 636035ba..32af934e 100644 --- a/web/controller/api.go +++ b/web/controller/api.go @@ -47,6 +47,7 @@ func (a *APIController) initRouter(g *gin.RouterGroup) { {"POST", "/resetAllClientTraffics/:id", a.inboundController.resetAllClientTraffics}, {"POST", "/delDepletedClients/:id", a.inboundController.delDepletedClients}, {"POST", "/onlines", a.inboundController.onlines}, + {"POST", "/lastOnline", a.inboundController.lastOnline}, {"POST", "/updateClientTraffic/:email", a.inboundController.updateClientTraffic}, } diff --git a/web/controller/inbound.go b/web/controller/inbound.go index 851b4b6f..9ff2f302 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -340,6 +340,11 @@ func (a *InboundController) onlines(c *gin.Context) { jsonObj(c, a.inboundService.GetOnlineClients(), nil) } +func (a *InboundController) lastOnline(c *gin.Context) { + data, err := a.inboundService.GetClientsLastOnline() + jsonObj(c, data, err) +} + func (a *InboundController) updateClientTraffic(c *gin.Context) { email := c.Param("email") diff --git a/web/controller/server.go b/web/controller/server.go index 2d2f741e..b1174b8f 100644 --- a/web/controller/server.go +++ b/web/controller/server.go @@ -55,6 +55,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) { g.POST("/getNewX25519Cert", a.getNewX25519Cert) g.POST("/getNewmldsa65", a.getNewmldsa65) g.POST("/getNewEchCert", a.getNewEchCert) + g.POST("/getNewVlessEnc", a.getNewVlessEnc) } func (a *ServerController) refreshStatus() { @@ -266,3 +267,12 @@ func (a *ServerController) getNewEchCert(c *gin.Context) { } jsonObj(c, cert, nil) } + +func (a *ServerController) getNewVlessEnc(c *gin.Context) { + out, err := a.serverService.GetNewVlessEnc() + if err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.toasts.getNewVlessEncError"), err) + return + } + jsonObj(c, out, nil) +} diff --git a/web/html/component/aClientTable.html b/web/html/component/aClientTable.html index 53ec27a3..a7279e50 100644 --- a/web/html/component/aClientTable.html +++ b/web/html/component/aClientTable.html @@ -33,12 +33,17 @@ +