Compare commits

...

12 Commits

Author SHA1 Message Date
mhsanaei
8e81008cdc v2.4.10 2024-12-19 10:54:17 +01:00
mhsanaei
e33ad809d6 Xray Core v24.12.18 2024-12-19 10:48:43 +01:00
mhsanaei
d804043a18 fail2ban - bantime 30min 2024-12-18 13:23:32 +01:00
mhsanaei
0fb0df7056 fail2ban - ipv4 & 6 2024-12-18 12:31:05 +01:00
mhsanaei
73e90e0eaa TLS, REALITY : fingerprint set default to chrome 2024-12-17 23:25:54 +01:00
mhsanaei
44ef1ac9a6 remove insecure cipher suites list 2024-12-17 23:18:16 +01:00
mhsanaei
aeac7f2c8b UTLS: unsafe 2024-12-17 23:17:12 +01:00
mhsanaei
39ef172b87 fail2ban - ban and unban an IP Address 2024-12-17 17:59:04 +01:00
mhsanaei
0df85cc3d9 XHTTP: server & client
Remove scMinPostsIntervalMs, xmux, noGRPCHeader from the server side and add them to the client side.

Before you could have them on sub json but I decided to remove them.
2024-12-17 10:39:37 +01:00
MHSanaei
f0f4f082ae improve iplimit 2024-12-16 14:26:47 +01:00
MHSanaei
b29bd993d4 fix session
twice  set-cookie bug fixed
2024-12-16 14:24:59 +01:00
MHSanaei
127eaf69b6 fail2ban - unban all without restart 2024-12-16 13:28:53 +01:00
13 changed files with 147 additions and 116 deletions

View File

@@ -83,7 +83,7 @@ jobs:
cd x-ui/bin
# Download dependencies
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.12.15/"
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.12.18/"
if [ "${{ matrix.platform }}" == "amd64" ]; then
wget ${Xray_URL}Xray-linux-64.zip
unzip Xray-linux-64.zip

View File

@@ -27,7 +27,7 @@ case $1 in
esac
mkdir -p build/bin
cd build/bin
wget "https://github.com/XTLS/Xray-core/releases/download/v24.12.15/Xray-linux-${ARCH}.zip"
wget "https://github.com/XTLS/Xray-core/releases/download/v24.12.18/Xray-linux-${ARCH}.zip"
unzip "Xray-linux-${ARCH}.zip"
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
mv xray "xray-linux-${FNAME}"

View File

@@ -1 +1 @@
2.4.9
2.4.10

12
go.mod
View File

@@ -14,10 +14,10 @@ require (
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.24.11
github.com/valyala/fasthttp v1.58.0
github.com/xtls/xray-core v1.8.25-0.20241215123619-7d0a80b501d4
github.com/xtls/xray-core v1.8.25-0.20241218133935-cab2fdefd321
go.uber.org/atomic v1.11.0
golang.org/x/text v0.21.0
google.golang.org/grpc v1.69.0
google.golang.org/grpc v1.69.2
gorm.io/driver/sqlite v1.5.7
gorm.io/gorm v1.25.12
)
@@ -85,17 +85,17 @@ require (
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/arch v0.12.0 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.28.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-20241209162323-e6fa225c2576 // indirect
google.golang.org/protobuf v1.35.2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 // indirect
google.golang.org/protobuf v1.36.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect
lukechampine.com/blake3 v1.3.0 // indirect

24
go.sum
View File

@@ -189,8 +189,8 @@ github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zd
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 h1:g1Cj7d+my6k/HHxLAyxPwyX8i7FGRr6ulBDMkBzg2BM=
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463/go.mod h1:BjIOLmkEEtAgloAiVUcYj0Mt+YU00JARZw8AEU0IwAg=
github.com/xtls/xray-core v1.8.25-0.20241215123619-7d0a80b501d4 h1:zdd86FEjFZjAaRbWxiZQM2QPOzk/d6cig2DaE7c3MDQ=
github.com/xtls/xray-core v1.8.25-0.20241215123619-7d0a80b501d4/go.mod h1:lduNPDkXku+Avphl8g7W0yJrHhWyxdOnPo0XGYdF0Aw=
github.com/xtls/xray-core v1.8.25-0.20241218133935-cab2fdefd321 h1:vk+n1RmfhFCj5xSi4I6C3USpcUQ48H3lt/QrtARVz1M=
github.com/xtls/xray-core v1.8.25-0.20241218133935-cab2fdefd321/go.mod h1:DCaUwrBk1RIC7hWg/wGoAynE69g3ptua1sEr8i0BWxA=
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=
@@ -215,12 +215,12 @@ golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4=
golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -241,12 +241,12 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.69.0 h1:quSiOM1GJPmPH5XtU+BCoVXcDVJJAzNcoyfC2cCjGkI=
google.golang.org/grpc v1.69.0/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484 h1:Z7FRVJPSMaHQxD0uXU8WdgFh8PseLM8Q8NzhnpMrBhQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241216192217-9240e9c98484/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@@ -34,10 +34,6 @@ const TLS_VERSION_OPTION = {
};
const TLS_CIPHER_OPTION = {
RSA_AES_128_CBC: "TLS_RSA_WITH_AES_128_CBC_SHA",
RSA_AES_256_CBC: "TLS_RSA_WITH_AES_256_CBC_SHA",
RSA_AES_128_GCM: "TLS_RSA_WITH_AES_128_GCM_SHA256",
RSA_AES_256_GCM: "TLS_RSA_WITH_AES_256_GCM_SHA384",
AES_128_GCM: "TLS_AES_128_GCM_SHA256",
AES_256_GCM: "TLS_AES_256_GCM_SHA384",
CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256",
@@ -64,6 +60,7 @@ const UTLS_FINGERPRINT = {
UTLS_QQ: "qq",
UTLS_RANDOM: "random",
UTLS_RANDOMIZED: "randomized",
UTLS_UNSAFE: "unsafe",
};
const ALPN_OPTION = {
@@ -496,19 +493,9 @@ class xHTTPStreamSettings extends XrayCommonClass {
headers = [],
scMaxBufferedPosts = 30,
scMaxEachPostBytes = "1000000",
scMinPostsIntervalMs = "30",
noSSEHeader = false,
xPaddingBytes = "100-1000",
xmux = {
maxConcurrency: "16-32",
maxConnections: 0,
cMaxReuseTimes: "64-128",
cMaxLifetimeMs: 0,
hMaxRequestTimes: "800-900",
hKeepAlivePeriod: 0,
},
mode = MODE_OPTION.AUTO,
noGRPCHeader = false
) {
super();
this.path = path;
@@ -516,12 +503,9 @@ class xHTTPStreamSettings extends XrayCommonClass {
this.headers = headers;
this.scMaxBufferedPosts = scMaxBufferedPosts;
this.scMaxEachPostBytes = scMaxEachPostBytes;
this.scMinPostsIntervalMs = scMinPostsIntervalMs;
this.noSSEHeader = noSSEHeader;
this.xPaddingBytes = xPaddingBytes;
this.xmux = xmux;
this.mode = mode;
this.noGRPCHeader = noGRPCHeader;
}
addHeader(name, value) {
@@ -539,12 +523,9 @@ class xHTTPStreamSettings extends XrayCommonClass {
XrayCommonClass.toHeaders(json.headers),
json.scMaxBufferedPosts,
json.scMaxEachPostBytes,
json.scMinPostsIntervalMs,
json.noSSEHeader,
json.xPaddingBytes,
json.xmux,
json.mode,
json.noGRPCHeader,
);
}
@@ -555,19 +536,9 @@ class xHTTPStreamSettings extends XrayCommonClass {
headers: XrayCommonClass.toV2Headers(this.headers, false),
scMaxBufferedPosts: this.scMaxBufferedPosts,
scMaxEachPostBytes: this.scMaxEachPostBytes,
scMinPostsIntervalMs: this.scMinPostsIntervalMs,
noSSEHeader: this.noSSEHeader,
xPaddingBytes: this.xPaddingBytes,
xmux: {
maxConcurrency: this.xmux.maxConcurrency,
maxConnections: this.xmux.maxConnections,
cMaxReuseTimes: this.xmux.cMaxReuseTimes,
cMaxLifetimeMs: this.xmux.cMaxLifetimeMs,
hMaxRequestTimes: this.xmux.hMaxRequestTimes,
hKeepAlivePeriod: this.xmux.hKeepAlivePeriod,
},
mode: this.mode,
noGRPCHeader: this.noGRPCHeader,
};
}
}
@@ -718,7 +689,10 @@ TlsStreamSettings.Cert = class extends XrayCommonClass {
};
TlsStreamSettings.Settings = class extends XrayCommonClass {
constructor(allowInsecure = false, fingerprint = '') {
constructor(
allowInsecure = false,
fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
) {
super();
this.allowInsecure = allowInsecure;
this.fingerprint = fingerprint;
@@ -807,7 +781,7 @@ class RealityStreamSettings extends XrayCommonClass {
RealityStreamSettings.Settings = class extends XrayCommonClass {
constructor(
publicKey = '',
fingerprint = UTLS_FINGERPRINT.UTLS_RANDOM,
fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
serverName = '',
spiderX = '/'
) {

View File

@@ -39,6 +39,7 @@ const UTLS_FINGERPRINT = {
UTLS_QQ: "qq",
UTLS_RANDOM: "random",
UTLS_RANDOMIZED: "randomized",
UTLS_UNSAFE: "unsafe",
};
const ALPN_OPTION = {
@@ -287,11 +288,24 @@ class xHTTPStreamSettings extends CommonClass {
path = '/',
host = '',
mode = '',
noGRPCHeader = false,
scMinPostsIntervalMs = "30",
xmux = {
maxConcurrency: "16-32",
maxConnections: 0,
cMaxReuseTimes: "64-128",
cMaxLifetimeMs: 0,
hMaxRequestTimes: "800-900",
hKeepAlivePeriod: 0,
},
) {
super();
this.path = path;
this.host = host;
this.mode = mode;
this.noGRPCHeader = noGRPCHeader;
this.scMinPostsIntervalMs = scMinPostsIntervalMs;
this.xmux = xmux;
}
static fromJson(json = {}) {
@@ -299,6 +313,9 @@ class xHTTPStreamSettings extends CommonClass {
json.path,
json.host,
json.mode,
json.noGRPCHeader,
json.scMinPostsIntervalMs,
json.xmux
);
}
@@ -307,6 +324,16 @@ class xHTTPStreamSettings extends CommonClass {
path: this.path,
host: this.host,
mode: this.mode,
noGRPCHeader: this.noGRPCHeader,
scMinPostsIntervalMs: this.scMinPostsIntervalMs,
xmux: {
maxConcurrency: this.xmux.maxConcurrency,
maxConnections: this.xmux.maxConnections,
cMaxReuseTimes: this.xmux.cMaxReuseTimes,
cMaxLifetimeMs: this.xmux.cMaxLifetimeMs,
hMaxRequestTimes: this.xmux.hMaxRequestTimes,
hKeepAlivePeriod: this.xmux.hKeepAlivePeriod,
},
};
}
}

View File

@@ -9,6 +9,7 @@ import (
"x-ui/web/service"
"x-ui/web/session"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)
@@ -49,8 +50,8 @@ func (a *IndexController) index(c *gin.Context) {
func (a *IndexController) login(c *gin.Context) {
var form LoginForm
err := c.ShouldBind(&form)
if err != nil {
if err := c.ShouldBind(&form); err != nil {
pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.invalidFormData"))
return
}
@@ -68,29 +69,31 @@ func (a *IndexController) login(c *gin.Context) {
safeUser := template.HTMLEscapeString(form.Username)
safePass := template.HTMLEscapeString(form.Password)
safeSecret := template.HTMLEscapeString(form.LoginSecret)
if user == nil {
logger.Warningf("wrong username: \"%s\", password: \"%s\", secret: \"%s\", IP: \"%s\"", safeUser, safePass, safeSecret, getRemoteIp(c))
a.tgbot.UserLoginNotify(safeUser, safePass, getRemoteIp(c), timeStr, 0)
pureJsonMsg(c, http.StatusOK, false, I18nWeb(c, "pages.login.toasts.wrongUsernameOrPassword"))
return
} else {
logger.Infof("%s logged in successfully, Ip Address: %s\n", safeUser, getRemoteIp(c))
a.tgbot.UserLoginNotify(safeUser, ``, getRemoteIp(c), timeStr, 1)
}
logger.Infof("%s logged in successfully, Ip Address: %s\n", safeUser, getRemoteIp(c))
a.tgbot.UserLoginNotify(safeUser, ``, getRemoteIp(c), timeStr, 1)
sessionMaxAge, err := a.settingService.GetSessionMaxAge()
if err != nil {
logger.Warning("Unable to get session's max age from DB")
}
err = session.SetMaxAge(c, sessionMaxAge*60)
if err != nil {
logger.Warning("Unable to set session's max age")
session.SetMaxAge(c, sessionMaxAge*60)
session.SetLoginUser(c, user)
if err := sessions.Default(c).Save(); err != nil {
logger.Warning("Unable to save session: ", err)
return
}
err = session.SetLoginUser(c, user)
logger.Infof("%s logged in successfully", user.Username)
jsonMsg(c, I18nWeb(c, "pages.login.toasts.successLogin"), err)
logger.Infof("%s logged in successfully", safeUser)
jsonMsg(c, I18nWeb(c, "pages.login.toasts.successLogin"), nil)
}
func (a *IndexController) logout(c *gin.Context) {
@@ -99,6 +102,9 @@ func (a *IndexController) logout(c *gin.Context) {
logger.Infof("%s logged out successfully", user.Username)
}
session.ClearSession(c)
if err := sessions.Default(c).Save(); err != nil {
logger.Warning("Unable to save session after clearing:", err)
}
c.Redirect(http.StatusTemporaryRedirect, c.GetString("base_path"))
}

View File

@@ -377,6 +377,30 @@
<a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="No gRPC Header" v-if="outbound.stream.xhttp.mode === 'stream-up' || outbound.stream.xhttp.mode === 'stream-one'">
<a-switch v-model="outbound.stream.xhttp.noGRPCHeader"></a-switch>
</a-form-item>
<a-form-item label="Min Upload Interval (Ms)" v-if="outbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="outbound.stream.xhttp.scMinPostsIntervalMs"></a-input>
</a-form-item>
<a-form-item label="Max Concurrency" v-if="!outbound.stream.xhttp.xmux.maxConnections">
<a-input v-model="outbound.stream.xhttp.xmux.maxConcurrency"></a-input>
</a-form-item>
<a-form-item label="Max Connections" v-if="!outbound.stream.xhttp.xmux.maxConcurrency">
<a-input v-model="outbound.stream.xhttp.xmux.maxConnections"></a-input>
</a-form-item>
<a-form-item label="Max Reuse Times">
<a-input v-model="outbound.stream.xhttp.xmux.cMaxReuseTimes"></a-input>
</a-form-item>
<a-form-item label="Max Lifetime (ms)">
<a-input v-model="outbound.stream.xhttp.xmux.cMaxLifetimeMs"></a-input>
</a-form-item>
<a-form-item label="Max Request Times">
<a-input v-model="outbound.stream.xhttp.xmux.hMaxRequestTimes"></a-input>
</a-form-item>
<a-form-item label='Keep Alive Period'>
<a-input v-model.number="outbound.stream.xhttp.xmux.hKeepAlivePeriod"></a-input>
</a-form-item>
</template>
</template>

View File

@@ -27,41 +27,17 @@
<a-select-option v-for="key in MODE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Max Buffered Upload">
<a-form-item label="Max Buffered Upload" v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="inbound.stream.xhttp.scMaxBufferedPosts"></a-input>
</a-form-item>
<a-form-item label="Max Upload Size (Byte)">
<a-form-item label="Max Upload Size (Byte)" v-if="inbound.stream.xhttp.mode === 'packet-up'">
<a-input v-model.trim="inbound.stream.xhttp.scMaxEachPostBytes"></a-input>
</a-form-item>
<a-form-item label="Min Upload Interval (Ms)">
<a-input v-model.trim="inbound.stream.xhttp.scMinPostsIntervalMs"></a-input>
</a-form-item>
<a-form-item label="Padding Bytes">
<a-input v-model.trim="inbound.stream.xhttp.xPaddingBytes"></a-input>
</a-form-item>
<a-form-item label="No SSE Header">
<a-switch v-model="inbound.stream.xhttp.noSSEHeader"></a-switch>
</a-form-item>
<a-form-item label="Max Concurrency" v-if="!inbound.stream.xhttp.xmux.maxConnections">
<a-input v-model="inbound.stream.xhttp.xmux.maxConcurrency"></a-input>
</a-form-item>
<a-form-item label="Max Connections" v-if="!inbound.stream.xhttp.xmux.maxConcurrency">
<a-input v-model="inbound.stream.xhttp.xmux.maxConnections"></a-input>
</a-form-item>
<a-form-item label="Max Reuse Times">
<a-input v-model="inbound.stream.xhttp.xmux.cMaxReuseTimes"></a-input>
</a-form-item>
<a-form-item label="Max Lifetime (ms)">
<a-input v-model="inbound.stream.xhttp.xmux.cMaxLifetimeMs"></a-input>
</a-form-item>
<a-form-item label="Max Request Times">
<a-input v-model="inbound.stream.xhttp.xmux.hMaxRequestTimes"></a-input>
</a-form-item>
<a-form-item label='Keep Alive Period'>
<a-input v-model.number="inbound.stream.xhttp.xmux.hKeepAlivePeriod"></a-input>
</a-form-item>
<a-form-item label="No gRPC Header">
<a-switch v-model="inbound.stream.xhttp.noGRPCHeader"></a-switch>
</a-form-item>
</a-form>
{{end}}

View File

@@ -151,13 +151,13 @@ func (j *CheckClientIpJob) processLogFile() bool {
}
sort.Strings(ips)
inboundClientIps, err := j.getInboundClientIps(email)
clientIpsRecord, err := j.getInboundClientIps(email)
if err != nil {
j.addInboundClientIps(email, ips)
continue
}
shouldCleanLog = j.updateInboundClientIps(inboundClientIps, email, ips) || shouldCleanLog
shouldCleanLog = j.updateInboundClientIps(clientIpsRecord, email, ips) || shouldCleanLog
}
return shouldCleanLog
@@ -309,12 +309,12 @@ func (j *CheckClientIpJob) updateInboundClientIps(inboundClientIps *model.Inboun
func (j *CheckClientIpJob) getInboundByEmail(clientEmail string) (*model.Inbound, error) {
db := database.GetDB()
var inbounds *model.Inbound
inbound := &model.Inbound{}
err := db.Model(model.Inbound{}).Where("settings LIKE ?", "%"+clientEmail+"%").Find(&inbounds).Error
err := db.Model(&model.Inbound{}).Where("settings LIKE ?", "%"+clientEmail+"%").First(inbound).Error
if err != nil {
return nil, err
}
return inbounds, nil
return inbound, nil
}

View File

@@ -10,38 +10,41 @@ import (
)
const (
loginUser = "LOGIN_USER"
defaultPath = "/"
loginUserKey = "LOGIN_USER"
defaultPath = "/"
)
func init() {
gob.Register(model.User{})
}
func SetLoginUser(c *gin.Context, user *model.User) error {
func SetLoginUser(c *gin.Context, user *model.User) {
if user == nil {
return
}
s := sessions.Default(c)
s.Set(loginUser, user)
return s.Save()
s.Set(loginUserKey, *user)
}
func SetMaxAge(c *gin.Context, maxAge int) error {
func SetMaxAge(c *gin.Context, maxAge int) {
s := sessions.Default(c)
s.Options(sessions.Options{
Path: defaultPath,
MaxAge: maxAge,
HttpOnly: true,
})
return s.Save()
}
func GetLoginUser(c *gin.Context) *model.User {
s := sessions.Default(c)
obj := s.Get(loginUser)
obj := s.Get(loginUserKey)
if obj == nil {
return nil
}
user, ok := obj.(model.User)
if !ok {
s.Delete(loginUserKey)
return nil
}
return &user
@@ -51,7 +54,7 @@ func IsLogin(c *gin.Context) bool {
return GetLoginUser(c) != nil
}
func ClearSession(c *gin.Context) error {
func ClearSession(c *gin.Context) {
s := sessions.Default(c)
s.Clear()
s.Options(sessions.Options{
@@ -59,5 +62,4 @@ func ClearSession(c *gin.Context) error {
MaxAge: -1,
HttpOnly: true,
})
return s.Save()
}

44
x-ui.sh
View File

@@ -1278,8 +1278,8 @@ run_speedtest() {
}
create_iplimit_jails() {
# Use default bantime if not passed => 15 minutes
local bantime="${1:-15}"
# Use default bantime if not passed => 30 minutes
local bantime="${1:-30}"
# Uncomment 'allowipv6 = auto' in fail2ban.conf
sed -i 's/#allowipv6 = auto/allowipv6 = auto/g' /etc/fail2ban/fail2ban.conf
@@ -1358,10 +1358,12 @@ iplimit_main() {
echo -e "${green}\t2.${plain} Change Ban Duration"
echo -e "${green}\t3.${plain} Unban Everyone"
echo -e "${green}\t4.${plain} Ban Logs"
echo -e "${green}\t5.${plain} Real-Time Logs"
echo -e "${green}\t6.${plain} Service Status"
echo -e "${green}\t7.${plain} Service Restart"
echo -e "${green}\t8.${plain} Uninstall Fail2ban and IP Limit"
echo -e "${green}\t5.${plain} Unban an IP Address"
echo -e "${green}\t6.${plain} Ban an IP Address"
echo -e "${green}\t7.${plain} Real-Time Logs"
echo -e "${green}\t8.${plain} Service Status"
echo -e "${green}\t9.${plain} Service Restart"
echo -e "${green}\t10.${plain} Uninstall Fail2ban and IP Limit"
echo -e "${green}\t0.${plain} Back to Main Menu"
read -p "Choose an option: " choice
case "$choice" in
@@ -1389,7 +1391,7 @@ iplimit_main() {
3)
confirm "Proceed with Unbanning everyone from IP Limit jail?" "y"
if [[ $? == 0 ]]; then
fail2ban-client reload --restart --unban 3x-ipl
systemctl restart fail2ban
truncate -s 0 "${iplimit_banned_log_path}"
echo -e "${green}All users Unbanned successfully.${plain}"
iplimit_main
@@ -1403,22 +1405,42 @@ iplimit_main() {
iplimit_main
;;
5)
tail -f /var/log/fail2ban.log
read -rp "Enter the IP address you want to ban: " ban_ip
if [[ $ban_ip =~ ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9]))$ || $ban_ip =~ ^(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})$ ]]; then
fail2ban-client set 3x-ipl banip "$ban_ip"
echo -e "${green}IP Address ${ban_ip} has been banned successfully.${plain}"
else
echo -e "${red}Invalid IP address format! Please try again.${plain}"
fi
iplimit_main
;;
6)
service fail2ban status
read -rp "Enter the IP address you want to unban: " unban_ip
if [[ $unban_ip =~ ^(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9]))$ || $unban_ip =~ ^(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})$ ]]; then
fail2ban-client set 3x-ipl unbanip "$unban_ip"
echo -e "${green}IP Address ${unban_ip} has been unbanned successfully.${plain}"
else
echo -e "${red}Invalid IP address format! Please try again.${plain}"
fi
iplimit_main
;;
7)
systemctl restart fail2ban
tail -f /var/log/fail2ban.log
iplimit_main
;;
8)
service fail2ban status
iplimit_main
;;
9)
systemctl restart fail2ban
iplimit_main
;;
10)
remove_iplimit
iplimit_main
;;
*)
*)
echo -e "${red}Invalid option. Please select a valid number.${plain}\n"
iplimit_main
;;