Compare commits

...

10 Commits

Author SHA1 Message Date
MHSanaei
31339d6bf8 v1.6.1 2023-05-25 19:16:09 +03:30
MHSanaei
8865443438 update dependencies 2023-05-25 19:15:22 +03:30
Tara Rostami
835deb77f4 Minor correction In UI (#537)
* Update antd.min.css

* Update settings.html

* Update custom.css
2023-05-25 16:21:29 +03:30
MHSanaei
6a7c3716ac fix MHz view 2023-05-25 16:13:54 +03:30
MHSanaei
15211f81b1 New - CPU Speed
logical Processors  removed
2023-05-25 15:48:23 +03:30
Tara Rostami
b3f7a6572e Minor changes in the UI (#535)
* Update antd.min.css

* Update settings.html
2023-05-25 13:15:24 +03:30
MHSanaei
6f28a3a2fe change blockedips to AllowedIps
now only those IPs that are allowed are able to establish a connection; other connections are dropped it will happen every 10 sec
after user offline that IPs will be removed from AllowedIps
2023-05-25 03:21:31 +03:30
MHSanaei
896cc5386c new - show cores, public ipv4 and ipv6
logical Processors
you can see them on first page
2023-05-25 03:11:09 +03:30
dependabot[bot]
76f70ce1e9 Bump github.com/pelletier/go-toml/v2 from 2.0.7 to 2.0.8 (#523)
Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.0.7 to 2.0.8.
- [Release notes](https://github.com/pelletier/go-toml/releases)
- [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml)
- [Commits](https://github.com/pelletier/go-toml/compare/v2.0.7...v2.0.8)

---
updated-dependencies:
- dependency-name: github.com/pelletier/go-toml/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-24 13:35:36 +03:30
dependabot[bot]
6aa3c8d4a2 Bump svenstaro/upload-release-action from 2.5.0 to 2.6.0 (#514)
Bumps [svenstaro/upload-release-action](https://github.com/svenstaro/upload-release-action) from 2.5.0 to 2.6.0.
- [Release notes](https://github.com/svenstaro/upload-release-action/releases)
- [Changelog](https://github.com/svenstaro/upload-release-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/svenstaro/upload-release-action/compare/2.5.0...2.6.0)

---
updated-dependencies:
- dependency-name: svenstaro/upload-release-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-24 01:37:30 +03:30
16 changed files with 266 additions and 106 deletions

View File

@@ -38,7 +38,7 @@ jobs:
- name: package
run: tar -zcvf x-ui-linux-amd64.tar.gz x-ui
- name: upload
uses: svenstaro/upload-release-action@2.5.0
uses: svenstaro/upload-release-action@2.6.0
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref }}
@@ -80,7 +80,7 @@ jobs:
- name: package
run: tar -zcvf x-ui-linux-arm64.tar.gz x-ui
- name: upload
uses: svenstaro/upload-release-action@2.5.0
uses: svenstaro/upload-release-action@2.6.0
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref }}

View File

@@ -1 +1 @@
1.6.0
1.6.1

6
go.mod
View File

@@ -11,7 +11,7 @@ require (
github.com/mymmrac/telego v0.24.0
github.com/nicksnyder/go-i18n/v2 v2.2.1
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml/v2 v2.0.7
github.com/pelletier/go-toml/v2 v2.0.8
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.23.4
github.com/xtls/xray-core v1.8.1
@@ -25,7 +25,7 @@ require (
require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/bytedance/sonic v1.8.9 // indirect
github.com/bytedance/sonic v1.8.10 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/fasthttp/router v1.4.19 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
@@ -64,7 +64,7 @@ require (
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/genproto v0.0.0-20230524185152-1884fd1fac28 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

15
go.sum
View File

@@ -10,8 +10,8 @@ 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.9 h1:mXB6OoHaI9OrWugkvNxWiuHTy5RCrVfxg2Nn40sf0oc=
github.com/bytedance/sonic v1.8.9/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/bytedance/sonic v1.8.10 h1:XFSQg4/rwpQnNWSybNDr8oz6QtQY9uRGfRKDVWVsvP8=
github.com/bytedance/sonic v1.8.10/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
@@ -116,8 +116,8 @@ github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
@@ -157,8 +157,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
@@ -246,8 +247,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/genproto v0.0.0-20230524185152-1884fd1fac28 h1:+55/MuGJORMxCrkAgo2595fMAnN/4rweCuwibbqrvpc=
google.golang.org/genproto v0.0.0-20230524185152-1884fd1fac28/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=

View File

@@ -996,7 +996,8 @@ to{transform:scale(0) translate(50%,-50%);opacity:0}
.ant-menu-horizontal .ant-menu-item,.ant-menu-horizontal .ant-menu-submenu{margin-top:-1px}
.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-submenu .ant-menu-submenu-title:hover{background-color:transparent}
.ant-menu-item-selected,.ant-menu-item-selected>a,.ant-menu-item-selected>a:hover{color:#1890ff}
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{background: linear-gradient(90deg,#009670 0,#026247 100%);color: #fff;border-radius: 0.5rem}
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{background-color: #0a7557;background-image: linear-gradient( 270deg, rgba(123, 199, 77, 0) 30%, #00ab80, rgba(123, 199, 77, 0) 100% );background-repeat: no-repeat;animation: ma-bg-move linear 6.6s infinite;/*background: linear-gradient(90deg,#009670 0,#026247 100%);*/color: #fff;border-radius: 0.5rem}
@-webkit-keyframes ma-bg-move {0% {background-position: -500px 0;}100% {background-position: 1000px 0;}}@keyframes ma-bg-move {0% {background-position: -500px 0;}50% {background-position: 1000px 0;}100% {background-position: 1000px 0;}}
.ant-menu-vertical-right{border-left:1px solid #e8e8e8}
.ant-menu-vertical-left.ant-menu-sub,.ant-menu-vertical-right.ant-menu-sub,.ant-menu-vertical.ant-menu-sub{min-width:160px;padding:0;border-right:0;transform-origin:0 0}
.ant-menu-vertical-left.ant-menu-sub .ant-menu-item,.ant-menu-vertical-right.ant-menu-sub .ant-menu-item,.ant-menu-vertical.ant-menu-sub .ant-menu-item{left:0;margin-left:0;border-right:0}
@@ -1081,8 +1082,8 @@ to{transform:scale(0) translate(50%,-50%);opacity:0}
.ant-menu-dark .ant-menu-item-selected{color:#fff;border-right:0}
.ant-menu-dark .ant-menu-item-selected:after{border-right:0}
.ant-menu-dark .ant-menu-item-selected .anticon,.ant-menu-dark .ant-menu-item-selected .anticon+span,.ant-menu-dark .ant-menu-item-selected>a,.ant-menu-dark .ant-menu-item-selected>a:hover{color:#ffffff}
.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected,.ant-menu.ant-menu-dark .ant-menu-item-selected{background-color:#15223a}
.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-active,.ant-menu.ant-menu-dark .ant-menu-item-active{background-color:#38383800}
.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected,.ant-menu.ant-menu-dark .ant-menu-item-selected{background-color:#0a7557}
/*.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-active,.ant-menu.ant-menu-dark .ant-menu-item-active{background-color:#0a7557}*/
.ant-menu-dark .ant-menu-item-disabled,.ant-menu-dark .ant-menu-item-disabled>a,.ant-menu-dark .ant-menu-submenu-disabled,.ant-menu-dark .ant-menu-submenu-disabled>a{color:hsla(0,0%,100%,.35)!important;opacity:.8}
.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title{color:hsla(0,0%,100%,.35)!important}
.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-item-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:after,.ant-menu-dark .ant-menu-submenu-disabled>.ant-menu-submenu-title>.ant-menu-submenu-arrow:before{background:hsla(0,0%,100%,.35)!important}
@@ -3231,7 +3232,7 @@ textarea.ant-input-number{max-width:100%;height:auto;min-height:32px;line-height
.ant-input-number-handler-down-inner:before,.ant-input-number-handler-up-inner:before{display:none}
.ant-input-number-handler-down-inner .ant-input-number-handler-down-inner-icon,.ant-input-number-handler-down-inner .ant-input-number-handler-up-inner-icon,.ant-input-number-handler-up-inner .ant-input-number-handler-down-inner-icon,.ant-input-number-handler-up-inner .ant-input-number-handler-up-inner-icon{display:block}
.ant-input-number-focused,.ant-input-number:hover{border-color:rgb(0, 150, 112) !important;border-right-width:1px!important}
.ant-input-number-focused{outline:0;box-shadow:0 0 0 2px rgba(24,144,255,.2)}
.ant-input-number-focused{outline:0;box-shadow:rgba(0, 150, 112, 0.2) 0px 0px 0px 2px}
.ant-input-number-disabled{color:rgba(0,0,0,.25);background-color:#f5f5f5;cursor:not-allowed;opacity:1}
.ant-input-number-disabled:hover{border-color:#d9d9d9;border-right-width:1px!important}
.ant-input-number-disabled .ant-input-number-input{cursor:not-allowed}

View File

@@ -213,6 +213,7 @@ body {
}
.ant-card-dark-box-nohover{
margin-top: .5rem;
padding: 0 20px 20px !important;
box-shadow: 0 1px 10px -1px rgb(154 175 238 / 0%) !important;
}

View File

@@ -5,7 +5,9 @@ const ONE_TB = ONE_GB * 1024;
const ONE_PB = ONE_TB * 1024;
function sizeFormat(size) {
if (size < ONE_KB) {
if (size < 0) {
return "0 B";
} else if (size < ONE_KB) {
return size.toFixed(0) + " B";
} else if (size < ONE_MB) {
return (size / ONE_KB).toFixed(2) + " KB";
@@ -20,6 +22,23 @@ function sizeFormat(size) {
}
}
function cpuSpeedFormat(speed) {
if (speed > 1000) {
const GHz = speed / 1000;
return GHz.toFixed(2) + " GHz";
} else {
return speed.toFixed(2) + " MHz";
}
}
function cpuCoreFormat(cores) {
if (cores === 1) {
return "1 Core";
} else {
return cores + " Cores";
}
}
function base64(str) {
return Base64.encode(str);
}

View File

@@ -34,7 +34,8 @@
:stroke-color="status.cpu.color"
:class="themeSwitcher.darkCardClass"
:percent="status.cpu.percent"></a-progress>
<div>CPU</div>
<div>CPU: [[ cpuCoreFormat(status.cpuCores) ]]</div>
<div>Speed: [[ cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
</a-col>
<a-col :span="12" style="text-align: center">
<a-progress type="dashboard" status="normal"
@@ -84,14 +85,10 @@
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "pages.index.operationHours" }}:
<a-tag color="green">[[ formatSecond(status.uptime) ]]</a-tag>
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.operationHoursDesc" }}
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
{{ i18n "menu.link" }}:
<a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">{{ i18n "pages.index.logs" }}</a-tag>
<a-tag color="blue" style="cursor: pointer;" @click="openConfig">{{ i18n "pages.index.config" }}</a-tag>
<a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag>
</a-card>
</a-col>
<a-col :sm="24" :md="12">
@@ -111,26 +108,69 @@
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "menu.link" }}:
<a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">{{ i18n "pages.index.logs" }}</a-tag>
<a-tag color="blue" style="cursor: pointer;" @click="openConfig">{{ i18n "pages.index.config" }}</a-tag>
<a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag>
<a-row>
<a-col :span="12">
{{ i18n "pages.index.systemLoad" }}: [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.systemLoadDesc" }}
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</a-col>
<a-col :span="12">
{{ i18n "pages.index.operationHours" }}:
<a-tag color="green">[[ formatSecond(status.uptime) ]]</a-tag>
</a-col>
</a-row>
</a-card>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "pages.index.systemLoad" }}: [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
<a-row>
<a-col :span="12">
IPv4:
<a-tooltip>
<template slot="title">
[[ status.publicIP.ipv4 ]]
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</a-col>
<a-col :span="12">
IPv6:
<a-tooltip>
<template slot="title">
[[ status.publicIP.ipv6 ]]
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</a-col>
</a-row>
</a-card>
</a-col>
</a-col>
<a-col :sm="24" :md="12">
<a-card hoverable :class="themeSwitcher.darkCardClass">
TCP / UDP {{ i18n "pages.index.connectionCount" }}: [[ status.tcpCount ]] / [[ status.udpCount ]]
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.connectionCountDesc" }}
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
<a-row>
<a-col :span="12">
TCP: [[ status.tcpCount ]]
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.connectionTcpCountDesc" }}
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</a-col>
<a-col :span="12">
UDP: [[ status.udpCount ]]
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.connectionUdpCountDesc" }}
</template>
<a-icon type="question-circle" theme="filled"></a-icon>
</a-tooltip>
</a-col>
</a-row>
</a-card>
</a-col>
<a-col :sm="24" :md="12">
@@ -138,7 +178,7 @@
<a-row>
<a-col :span="12">
<a-icon type="arrow-up"></a-icon>
[[ sizeFormat(status.netIO.up) ]] / S
[[ sizeFormat(status.netIO.up) ]]/S
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.upSpeed" }}
@@ -148,7 +188,7 @@
</a-col>
<a-col :span="12">
<a-icon type="arrow-down"></a-icon>
[[ sizeFormat(status.netIO.down) ]] / S
[[ sizeFormat(status.netIO.down) ]]/S
<a-tooltip>
<template slot="title">
{{ i18n "pages.index.downSpeed" }}
@@ -294,11 +334,14 @@
class Status {
constructor(data) {
this.cpu = new CurTotal(0, 0);
this.cpuCores = 0;
this.cpuSpeedMhz = 0;
this.disk = new CurTotal(0, 0);
this.loads = [0, 0, 0];
this.mem = new CurTotal(0, 0);
this.netIO = { up: 0, down: 0 };
this.netTraffic = { sent: 0, recv: 0 };
this.publicIP = { ipv4: 0, ipv6: 0 };
this.swap = new CurTotal(0, 0);
this.tcpCount = 0;
this.udpCount = 0;
@@ -309,11 +352,14 @@
return;
}
this.cpu = new CurTotal(data.cpu, 100);
this.cpuCores = data.cpuCores;
this.cpuSpeedMhz = data.cpuSpeedMhz;
this.disk = new CurTotal(data.disk.current, data.disk.total);
this.loads = data.loads.map(load => toFixed(load, 2));
this.mem = new CurTotal(data.mem.current, data.mem.total);
this.netIO = data.netIO;
this.netTraffic = data.netTraffic;
this.publicIP = data.publicIP;
this.swap = new CurTotal(data.swap.current, data.swap.total);
this.tcpCount = data.tcpCount;
this.udpCount = data.udpCount;

View File

@@ -26,14 +26,32 @@
.alert-msg {
color: rgb(194, 117, 18);
font-weight: bold;
font-size: 20px;
margin-top: 5px;
padding: 16px 6px;
font-weight: normal;
font-size: 16px;
padding: .5rem 1rem;
text-align: center;
border-bottom: 1px solid;
background: rgb(255 145 0 / 15%);
margin: 1.5rem 2.5rem 0rem 2.5rem;
border-radius: .5rem;
transition: all 0.5s;
animation: signal 3s cubic-bezier(0.18, 0.89, 0.32, 1.28) infinite;
}
.alert-msg:hover {
cursor: default;
transition-duration: .3s;
animation: signal 0.9s ease infinite;
}
@keyframes signal{
0%{
box-shadow: 0 0 0 0 rgba(194, 118, 18, 0.5);
}
50%{
box-shadow: 0 0 0 6px rgba(0 ,0,0,0);
}
100%{
box-shadow: 0 0 0 6px rgba(0 ,0,0,0);
}
}
.alert-msg > i {
color: inherit;
font-size: 24px;

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"os"
"regexp"
"sync"
"x-ui/database"
"x-ui/database/model"
"x-ui/logger"
@@ -20,34 +21,38 @@ import (
type CheckClientIpJob struct {
xrayService service.XrayService
AllowedIps []string
mutex sync.Mutex
}
var job *CheckClientIpJob
var disAllowedIps []string
var AllowedIps []string
var ipRegx *regexp.Regexp = regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
var emailRegx *regexp.Regexp = regexp.MustCompile(`email:.+`)
func NewCheckClientIpJob() *CheckClientIpJob {
job = new(CheckClientIpJob)
job := &CheckClientIpJob{}
return job
}
func (j *CheckClientIpJob) Run() {
logger.Debug("Check Client IP Job...")
processLogFile()
j.processLogFile()
// disAllowedIps = []string{"192.168.1.183","192.168.1.197"}
blockedIps := []byte(strings.Join(disAllowedIps, ","))
// AllowedIps = []string{"192.168.1.183","192.168.1.197"}
allowedIps := []byte(strings.Join(j.getAllowedIps(), ","))
// check if file exists, if not create one
_, err := os.Stat(xray.GetBlockedIPsPath())
_, err := os.Stat(xray.GetAllowedIPsPath())
if os.IsNotExist(err) {
_, err = os.OpenFile(xray.GetBlockedIPsPath(), os.O_RDWR|os.O_CREATE, 0755)
_, err = os.OpenFile(xray.GetAllowedIPsPath(), os.O_RDWR|os.O_CREATE, 0755)
checkError(err)
}
err = os.WriteFile(xray.GetBlockedIPsPath(), blockedIps, 0755)
err = os.WriteFile(xray.GetAllowedIPsPath(), allowedIps, 0755)
checkError(err)
}
func processLogFile() {
func (j *CheckClientIpJob) processLogFile() {
accessLogPath := GetAccessLogPath()
if accessLogPath == "" {
logger.Warning("access.log doesn't exist in your config.json")
@@ -65,8 +70,6 @@ func processLogFile() {
lines := strings.Split(string(data), "\n")
for _, line := range lines {
ipRegx, _ := regexp.Compile(`[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+`)
emailRegx, _ := regexp.Compile(`email:.+`)
matchesIp := ipRegx.FindString(line)
if len(matchesIp) > 0 {
@@ -81,19 +84,13 @@ func processLogFile() {
}
matchesEmail = strings.TrimSpace(strings.Split(matchesEmail, "email: ")[1])
if InboundClientIps[matchesEmail] != nil {
if contains(InboundClientIps[matchesEmail], ip) {
continue
}
InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
} else {
if !contains(InboundClientIps[matchesEmail], ip) {
InboundClientIps[matchesEmail] = append(InboundClientIps[matchesEmail], ip)
}
}
}
disAllowedIps = []string{}
j.setAllowedIps([]string{})
for clientEmail, ips := range InboundClientIps {
inboundClientIps, err := GetInboundClientIps(clientEmail)
@@ -102,7 +99,7 @@ func processLogFile() {
addInboundClientIps(clientEmail, ips)
} else {
updateInboundClientIps(inboundClientIps, clientEmail, ips)
j.updateInboundClientIps(inboundClientIps, clientEmail, ips)
}
}
@@ -115,6 +112,7 @@ func processLogFile() {
stop <- true
}
func GetAccessLogPath() string {
config, err := os.ReadFile(xray.GetConfigPath())
@@ -135,20 +133,22 @@ func GetAccessLogPath() string {
return ""
}
func checkError(e error) {
if e != nil {
logger.Warning("client ip job err:", e)
}
}
func contains(s []string, str string) bool {
for _, v := range s {
if v == str {
return true
}
}
return false
}
func GetInboundClientIps(clientEmail string) (*model.InboundClientIps, error) {
db := database.GetDB()
InboundClientIps := &model.InboundClientIps{}
@@ -158,6 +158,7 @@ func GetInboundClientIps(clientEmail string) (*model.InboundClientIps, error) {
}
return InboundClientIps, nil
}
func addInboundClientIps(clientEmail string, ips []string) error {
inboundClientIps := &model.InboundClientIps{}
jsonIps, err := json.Marshal(ips)
@@ -170,10 +171,10 @@ func addInboundClientIps(clientEmail string, ips []string) error {
tx := db.Begin()
defer func() {
if err == nil {
tx.Commit()
} else {
if r := recover(); r != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
@@ -183,13 +184,7 @@ func addInboundClientIps(clientEmail string, ips []string) error {
}
return nil
}
func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) error {
jsonIps, err := json.Marshal(ips)
checkError(err)
inboundClientIps.ClientEmail = clientEmail
inboundClientIps.Ips = string(jsonIps)
func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmail string, ips []string) error {
// check inbound limitation
inbound, err := GetInboundByEmail(clientEmail)
@@ -206,17 +201,22 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmai
for _, client := range clients {
if client.Email == clientEmail {
limitIp := client.LimitIP
if limitIp < len(ips) && limitIp != 0 && inbound.Enable {
disAllowedIps = append(disAllowedIps, ips[limitIp:]...)
for _, ip := range ips[:limitIp] {
j.addAllowedIp(ip)
}
}
}
}
logger.Debug("disAllowedIps ", disAllowedIps)
sort.Strings(disAllowedIps)
jsonIps, err := json.Marshal(ips) // marshal the possibly truncated list of IPs
checkError(err)
inboundClientIps.ClientEmail = clientEmail
inboundClientIps.Ips = string(jsonIps)
logger.Debug("Allowed IPs: ", ips)
db := database.GetDB()
err = db.Save(inboundClientIps).Error
@@ -225,6 +225,25 @@ func updateInboundClientIps(inboundClientIps *model.InboundClientIps, clientEmai
}
return nil
}
func (j *CheckClientIpJob) setAllowedIps(ips []string) {
j.mutex.Lock()
defer j.mutex.Unlock()
j.AllowedIps = ips
}
func (j *CheckClientIpJob) addAllowedIp(ip string) {
j.mutex.Lock()
defer j.mutex.Unlock()
j.AllowedIps = append(j.AllowedIps, ip)
}
func (j *CheckClientIpJob) getAllowedIps() []string {
j.mutex.Lock()
defer j.mutex.Unlock()
return j.AllowedIps
}
func DisableInbound(id int) error {
db := database.GetDB()
result := db.Model(model.Inbound{}).
@@ -278,7 +297,7 @@ func LimitDevice() {
srcPort = portRegx.FindString(data[1])
srcPort = strings.Replace(srcPort, ":", "", -1)
if contains(disAllowedIps, srcIp) {
if contains(AllowedIps, srcIp) {
dropCmd := cmd.NewCmd("bash", "-c", "ss -K dport = "+srcPort)
dropCmd.Start()

View File

@@ -38,9 +38,11 @@ const (
)
type Status struct {
T time.Time `json:"-"`
Cpu float64 `json:"cpu"`
Mem struct {
T time.Time `json:"-"`
Cpu float64 `json:"cpu"`
CpuCores int `json:"cpuCores"`
CpuSpeedMhz float64 `json:"cpuSpeedMhz"`
Mem struct {
Current uint64 `json:"current"`
Total uint64 `json:"total"`
} `json:"mem"`
@@ -69,6 +71,10 @@ type Status struct {
Sent uint64 `json:"sent"`
Recv uint64 `json:"recv"`
} `json:"netTraffic"`
PublicIP struct {
IPv4 string `json:"ipv4"`
IPv6 string `json:"ipv6"`
} `json:"publicIP"`
}
type Release struct {
@@ -80,6 +86,33 @@ type ServerService struct {
inboundService InboundService
}
const DebugMode = false // Set to true during development
func getPublicIP(url string) string {
resp, err := http.Get(url)
if err != nil {
if DebugMode {
logger.Warning("get public IP failed:", err)
}
return "N/A"
}
defer resp.Body.Close()
ip, err := io.ReadAll(resp.Body)
if err != nil {
if DebugMode {
logger.Warning("read public IP failed:", err)
}
return "N/A"
}
if string(ip) == "" {
return "N/A" // default value
}
return string(ip)
}
func (s *ServerService) GetStatus(lastStatus *Status) *Status {
now := time.Now()
status := &Status{
@@ -93,6 +126,21 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
status.Cpu = percents[0]
}
status.CpuCores, err = cpu.Counts(false)
if err != nil {
logger.Warning("get cpu cores count failed:", err)
}
cpuInfos, err := cpu.Info()
if err != nil {
logger.Warning("get cpu info failed:", err)
} else if len(cpuInfos) > 0 {
cpuInfo := cpuInfos[0]
status.CpuSpeedMhz = cpuInfo.Mhz // setting CPU speed in MHz
} else {
logger.Warning("could not find cpu info")
}
upTime, err := host.Uptime()
if err != nil {
logger.Warning("get uptime failed:", err)
@@ -161,6 +209,9 @@ func (s *ServerService) GetStatus(lastStatus *Status) *Status {
logger.Warning("get udp connections failed:", err)
}
status.PublicIP.IPv4 = getPublicIP("https://api.ipify.org")
status.PublicIP.IPv6 = getPublicIP("https://api6.ipify.org")
if s.xrayService.IsXrayRunning() {
status.Xray.State = Running
status.Xray.ErrorMsg = ""

View File

@@ -75,14 +75,15 @@
"xrayStatus" = "Xray Status"
"stopXray" = "Stop"
"restartXray" = "Restart"
"xraySwitch" = "Switch Version"
"xraySwitch" = "SwitchV"
"xraySwitchClick" = "Choose the version you want to switch to."
"xraySwitchClickDesk" = "Choose wisely, as older versions may not be compatible with current configurations."
"operationHours" = "Operation Hours"
"operationHoursDesc" = "System uptime: time since startup."
"operationHours" = "Uptime"
"systemLoad" = "System Load"
"systemLoadDesc" = "system load average for the past 1, 5, and 15 minutes"
"connectionTcpCountDesc" = "Total TCP connections across all network cards."
"connectionUdpCountDesc" = "Total UDP connections across all network cards."
"connectionCount" = "Number of Connections"
"connectionCountDesc" = "Total connections across all network cards."
"upSpeed" = "Total upload speed for all network cards."
"downSpeed" = "Total download speed for all network cards."
"totalSent" = "Total upload traffic of all network cards since system startup."

View File

@@ -78,11 +78,12 @@
"xraySwitch" = "تغییر ورژن"
"xraySwitchClick" = "ورژن مورد نظر را انتخاب کنید"
"xraySwitchClickDesk" = "لطفا با دقت انتخاب کنید ، در صورت انتخاب اشتباه امکان قطعی سیستم وجود دارد "
"operationHours" = "مدت فعالیت"
"operationHoursDesc" = "مدت فعالیت سیستم بعد از روشن شدن"
"systemLoad" = "بار روی سیستم"
"operationHours" = "آپ تایم سیستم"
"systemLoad" = "بار سیستم"
"systemLoadDesc" = "میانگین بار سیستم برای 1، 5 و 15 دقیقه گذشته"
"connectionTcpCountDesc" = "مجموع اتصالات TCP در تمام کارت های شبکه"
"connectionUdpCountDesc" = "مجموع اتصالات UDP در تمام کارت های شبکه"
"connectionCount" = "تعداد کانکشن ها"
"connectionCountDesc" = "تعداد کانکشن ها برای کل شبکه"
"upSpeed" = "سرعت آپلود در حال حاضر سیستم"
"downSpeed" = "سرعت دانلود در حال حاضر سیستم"
"totalSent" = "جمع کل ترافیک آپلود مصرفی"

View File

@@ -78,11 +78,12 @@
"xraySwitch" = "Переключить версию"
"xraySwitchClick" = "Выберите желаемую версию"
"xraySwitchClickDesk" = "Выбирайте внимательно, так как старые версии могут быть несовместимы с текущими конфигурациями"
"operationHours" = "Часы работы"
"operationHoursDesc" = "Аптайм системы: время системы в сети"
"operationHours" = "Время работы системы"
"systemLoad" = "Системная нагрузка"
"systemLoadDesc" = "средняя загрузка системы за последние 1, 5 и 15 минут"
"connectionTcpCountDesc" = "Всего подключений TCP по всем сетевым картам."
"connectionUdpCountDesc" = "Общее количество подключений UDP по всем сетевым картам."
"connectionCount" = "Количество соединений"
"connectionCountDesc" = "Всего подключений по всем сетям"
"upSpeed" = "Общая скорость upload для всех сетей"
"downSpeed" = "Общая скорость download для всех сетей"
"totalSent" = "Общий объем загруженных данных для всех сетей с момента запуска системы"

View File

@@ -78,11 +78,12 @@
"xraySwitch" = "切换版本"
"xraySwitchClick" = "点击你想切换的版本"
"xraySwitchClickDesk" = "请谨慎选择,旧版本可能配置不兼容"
"operationHours" = "运行时间"
"operationHoursDesc" = "系统自启动以来的运行时间"
"operationHours" = "系统正常运行时间"
"systemLoad" = "系统负载"
"systemLoadDesc" = "过去 1、5 和 15 分钟的系统平均负载"
"connectionTcpCountDesc" = "所有网卡的总 TCP 连接数。"
"connectionUdpCountDesc" = "所有网卡的总 UDP 连接数。"
"connectionCount" = "连接数"
"connectionCountDesc" = "所有网卡的总连接数"
"upSpeed" = "所有网卡的总上传速度"
"downSpeed" = "所有网卡的总下载速度"
"totalSent" = "系统启动以来所有网卡的总上传流量"

View File

@@ -51,8 +51,8 @@ func GetIranPath() string {
return config.GetBinFolderPath() + "/iran.dat"
}
func GetBlockedIPsPath() string {
return config.GetBinFolderPath() + "/blockedIPs"
func GetAllowedIPsPath() string {
return config.GetBinFolderPath() + "/AllowedIPs"
}
func stopProcess(p *Process) {
@@ -173,7 +173,7 @@ func (p *process) Start() (err error) {
return common.NewErrorf("Failed to write configuration file: %v", err)
}
cmd := exec.Command(GetBinaryPath(), "-c", configPath, "-restrictedIPsPath", GetBlockedIPsPath())
cmd := exec.Command(GetBinaryPath(), "-c", configPath, "-restrictedIPsPath", GetAllowedIPsPath())
p.cmd = cmd
stdReader, err := cmd.StdoutPipe()