mirror of
https://github.com/alireza0/x-ui.git
synced 2026-03-14 05:23:09 +00:00
2
go.mod
2
go.mod
@@ -3,8 +3,8 @@ module x-ui
|
||||
go 1.23.2
|
||||
|
||||
require (
|
||||
github.com/Calidity/gin-sessions v1.3.1
|
||||
github.com/gin-contrib/gzip v1.0.1
|
||||
github.com/gin-contrib/sessions v1.0.1
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||
github.com/goccy/go-json v0.10.3
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1,7 +1,5 @@
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/Calidity/gin-sessions v1.3.1 h1:nF3dCBWa7TZ4j26iYLwGRmzZy9YODhWoOS3fmi+snyE=
|
||||
github.com/Calidity/gin-sessions v1.3.1/go.mod h1:I0+QE6qkO50TeN/n6If6novvxHk4Isvr23U8EdvPdns=
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I=
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
@@ -31,6 +29,8 @@ github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||
github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE=
|
||||
github.com/gin-contrib/gzip v1.0.1/go.mod h1:njt428fdUNRvjuJf16tZMYZ2Yl+WQB53X5wmhDwXvC4=
|
||||
github.com/gin-contrib/sessions v1.0.1 h1:3hsJyNs7v7N8OtelFmYXFrulAf6zSR7nW/putcPEHxI=
|
||||
github.com/gin-contrib/sessions v1.0.1/go.mod h1:ouxSFM24/OgIud5MJYQJLpy6AwxQ5EYO9yLhbtObGkM=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
|
||||
65
install.sh
65
install.sh
@@ -137,51 +137,62 @@ gen_random_string() {
|
||||
}
|
||||
|
||||
config_after_install() {
|
||||
echo -e "${yellow}Install/update finished! For security, it's recommended to modify panel settings ${plain}"
|
||||
read -p "Would you like to customize the panel settings? (If not, random settings may be applied) [y/n]: " config_confirm
|
||||
|
||||
local config_webBasePath=$(gen_random_string 10)
|
||||
local existing_username=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'username: .+' | awk '{print $2}')
|
||||
local existing_password=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'password: .+' | awk '{print $2}')
|
||||
local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
|
||||
|
||||
# Check if username and password exist
|
||||
if [[ -n "$existing_username" && -n "$existing_password" ]]; then
|
||||
# If webBasePath is missing, generate a new one
|
||||
if [[ ${#existing_webBasePath} -lt 4 ]]; then
|
||||
local config_webBasePath=$(gen_random_string 15)
|
||||
echo -e "${yellow}WebBasePath is missing or too short. Generating a new one...${plain}"
|
||||
/usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}"
|
||||
echo -e "${green}New WebBasePath: ${config_webBasePath}${plain}"
|
||||
else
|
||||
echo -e "${green}Username, Password, and WebBasePath are already set. Exiting...${plain}"
|
||||
fi
|
||||
/usr/local/x-ui/x-ui migrate
|
||||
return 0
|
||||
fi
|
||||
|
||||
read -p "Would you like to customize the Panel Port settings? (If not, random settings will be applied) [y/n]: " config_confirm
|
||||
|
||||
local config_webBasePath=$(gen_random_string 15)
|
||||
local config_username=$(gen_random_string 10)
|
||||
local config_password=$(gen_random_string 10)
|
||||
|
||||
if [[ "${config_confirm}" == "y" || "${config_confirm}" == "Y" ]]; then
|
||||
|
||||
read -p "Please set up your username: " config_account
|
||||
echo -e "${yellow}Your username will be: ${config_account}${plain}"
|
||||
|
||||
read -p "Please set up your password: " config_password
|
||||
echo -e "${yellow}Your password will be: ${config_password}${plain}"
|
||||
|
||||
read -p "Please set up the panel port: " config_port
|
||||
echo -e "${yellow}Your panel port is: ${config_port}${plain}"
|
||||
echo -e "${yellow}Your Panel Port is: ${config_port}${plain}"
|
||||
|
||||
echo -e "${yellow}Your web base path will be generated randomly: ${config_webBasePath}${plain}"
|
||||
echo -e "${yellow}Your Username will be generated randomly: ${config_username}${plain}"
|
||||
echo -e "${yellow}Your Password will be generated randomly: ${config_password}${plain}"
|
||||
echo -e "${yellow}Your Web Base Path will be generated randomly: ${config_webBasePath}${plain}"
|
||||
|
||||
echo -e "${yellow}Initializing, please wait...${plain}"
|
||||
|
||||
/usr/local/x-ui/x-ui setting -username "${config_account}" -password "${config_password}" -port "${config_port}" -webBasePath "${config_webBasePath}"
|
||||
echo -e "${yellow}Settings applied successfully!${plain}"
|
||||
/usr/local/x-ui/x-ui setting -username "${config_username}" -password "${config_password}" -port "${config_port}" -webBasePath "${config_webBasePath}"
|
||||
echo -e "${green}Settings applied successfully!${plain}"
|
||||
|
||||
echo -e "###############################################"
|
||||
echo -e "${green}Username: ${config_account}${plain}"
|
||||
echo -e "${green}Username: ${config_username}${plain}"
|
||||
echo -e "${green}Password: ${config_password}${plain}"
|
||||
echo -e "${green}Port: ${config_port}${plain}"
|
||||
echo -e "${green}WebBasePath: ${config_webBasePath}${plain}"
|
||||
echo -e "###############################################"
|
||||
|
||||
else
|
||||
|
||||
echo -e "${red}Cancel...${plain}"
|
||||
|
||||
if [[ ! -f "/etc/x-ui/x-ui.db" ]]; then
|
||||
|
||||
local usernameTemp=$(gen_random_string 10)
|
||||
local passwordTemp=$(gen_random_string 10)
|
||||
local portTemp=$(shuf -i 1024-62000 -n 1)
|
||||
|
||||
/usr/local/x-ui/x-ui setting -username "${usernameTemp}" -password "${passwordTemp}" -port "${portTemp}" -webBasePath "${config_webBasePath}"
|
||||
/usr/local/x-ui/x-ui setting -username "${config_username}" -password "${config_password}" -port "${portTemp}" -webBasePath "${config_webBasePath}"
|
||||
echo -e "This is a fresh installation, generating random login info for security concerns:"
|
||||
echo -e "###############################################"
|
||||
echo -e "${green}Username: ${usernameTemp}${plain}"
|
||||
echo -e "${green}Password: ${passwordTemp}${plain}"
|
||||
echo -e "${green}Username: ${config_username}${plain}"
|
||||
echo -e "${green}Password: ${config_password}${plain}"
|
||||
echo -e "${green}Port: ${portTemp}${plain}"
|
||||
echo -e "${green}WebBasePath: ${config_webBasePath}${plain}"
|
||||
echo -e "###############################################"
|
||||
@@ -189,14 +200,6 @@ config_after_install() {
|
||||
else
|
||||
echo -e "${yellow}This is your upgrade, keeping old settings. If you forgot your login info, you can type 'x-ui settings' to check${plain}"
|
||||
|
||||
local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
|
||||
|
||||
if [[ ${#existing_webBasePath} -lt 4 ]]; then
|
||||
echo -e "${yellow}WebBasePath is empty, generating a random one...${plain}"
|
||||
|
||||
/usr/local/x-ui/x-ui setting -webBasePath "${config_webBasePath}"
|
||||
echo -e "${green}New webBasePath: ${config_webBasePath}${plain}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -43,11 +43,13 @@
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"tag": "direct",
|
||||
"protocol": "freedom",
|
||||
"settings": {
|
||||
"domainStrategy": "UseIP"
|
||||
}
|
||||
"domainStrategy": "UseIP",
|
||||
"noises": [],
|
||||
"redirect": ""
|
||||
},
|
||||
"tag": "direct"
|
||||
},
|
||||
{
|
||||
"tag": "block",
|
||||
|
||||
@@ -459,9 +459,9 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
|
||||
noSSEHeader = false,
|
||||
xPaddingBytes = "100-1000",
|
||||
xmux = {
|
||||
maxConcurrency: 0,
|
||||
maxConcurrency: "16-32",
|
||||
maxConnections: 0,
|
||||
cMaxReuseTimes: 0,
|
||||
cMaxReuseTimes: "64-128",
|
||||
cMaxLifetimeMs: 0
|
||||
}
|
||||
) {
|
||||
|
||||
@@ -4,18 +4,21 @@
|
||||
<a-input v-model.trim="inbound.stream.splithttp.host"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "path" }}'>
|
||||
<a-input v-model.trim="inbound.stream.splithttp.path"></a-input>
|
||||
<a-input v-model.trim="inbound.stream.splithttp.path"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='{{ i18n "pages.inbounds.stream.tcp.requestHeader" }}'>
|
||||
<a-button icon="plus" size="small" @click="inbound.stream.splithttp.addHeader('host', '')"></a-button>
|
||||
<a-button icon="plus" size="small" @click="inbound.stream.splithttp.addHeader('host', '')"></a-button>
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{span:24}">
|
||||
<a-input-group compact v-for="(header, index) in inbound.stream.splithttp.headers">
|
||||
<a-input style="width: 50%" v-model.trim="header.name" placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'>
|
||||
<a-input style="width: 50%" v-model.trim="header.name"
|
||||
placeholder='{{ i18n "pages.inbounds.stream.general.name"}}'>
|
||||
<template slot="addonBefore" style="margin: 0;">[[ index+1 ]]</template>
|
||||
</a-input>
|
||||
<a-input style="width: 50%" v-model.trim="header.value" placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
||||
<a-button slot="addonAfter" size="small" @click="inbound.stream.splithttp.removeHeader(index)">-</a-button>
|
||||
<a-input style="width: 50%" v-model.trim="header.value"
|
||||
placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
|
||||
<a-button slot="addonAfter" size="small"
|
||||
@click="inbound.stream.splithttp.removeHeader(index)">-</a-button>
|
||||
</a-input>
|
||||
</a-input-group>
|
||||
</a-form-item>
|
||||
@@ -35,16 +38,16 @@
|
||||
<a-switch v-model="inbound.stream.splithttp.noSSEHeader"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Concurrency" v-if="!inbound.stream.splithttp.xmux.maxConnections">
|
||||
<a-input-number v-model="inbound.stream.splithttp.xmux.maxConcurrency"></a-input-number>
|
||||
<a-input v-model="inbound.stream.splithttp.xmux.maxConcurrency"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Connections" v-if="!inbound.stream.splithttp.xmux.maxConcurrency">
|
||||
<a-input-number v-model="inbound.stream.splithttp.xmux.maxConnections"></a-input-number>
|
||||
<a-input v-model="inbound.stream.splithttp.xmux.maxConnections"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Reuse Times">
|
||||
<a-input-number v-model="inbound.stream.splithttp.xmux.cMaxReuseTimes"></a-input-number>
|
||||
<a-input v-model="inbound.stream.splithttp.xmux.cMaxReuseTimes"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="Max Lifetime (ms)">
|
||||
<a-input-number v-model="inbound.stream.splithttp.xmux.cMaxLifetimeMs"></a-input-number>
|
||||
<a-input v-model="inbound.stream.splithttp.xmux.cMaxLifetimeMs"></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
{{end}}
|
||||
@@ -296,6 +296,7 @@
|
||||
<a-select-option value="20">20</a-select-option>
|
||||
<a-select-option value="50">50</a-select-option>
|
||||
<a-select-option value="100">100</a-select-option>
|
||||
<a-select-option value="500">500</a-select-option>
|
||||
</a-select>
|
||||
<a-select v-model="logModal.level" style="width:100px;"
|
||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||
|
||||
@@ -1,34 +1,44 @@
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "warning"
|
||||
},
|
||||
"api": {
|
||||
"tag": "api",
|
||||
"services": ["HandlerService", "LoggerService", "StatsService"]
|
||||
"services": [
|
||||
"HandlerService",
|
||||
"LoggerService",
|
||||
"StatsService"
|
||||
],
|
||||
"tag": "api"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "api",
|
||||
"listen": "127.0.0.1",
|
||||
"port": 62789,
|
||||
"protocol": "dokodemo-door",
|
||||
"settings": {
|
||||
"address": "127.0.0.1"
|
||||
}
|
||||
},
|
||||
"tag": "api"
|
||||
}
|
||||
],
|
||||
"log": {
|
||||
"access": "none",
|
||||
"dnsLog": false,
|
||||
"error": "",
|
||||
"loglevel": "warning",
|
||||
"maskAddress": ""
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"tag": "direct",
|
||||
"protocol": "freedom",
|
||||
"settings": {
|
||||
"domainStrategy": "UseIP"
|
||||
}
|
||||
"domainStrategy": "UseIP",
|
||||
"noises": [],
|
||||
"redirect": ""
|
||||
},
|
||||
"tag": "direct"
|
||||
},
|
||||
{
|
||||
"tag": "blocked",
|
||||
"protocol": "blackhole",
|
||||
"settings": {}
|
||||
"settings": {},
|
||||
"tag": "blocked"
|
||||
}
|
||||
],
|
||||
"policy": {
|
||||
@@ -47,19 +57,25 @@
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"inboundTag": ["api"],
|
||||
"outboundTag": "api"
|
||||
"inboundTag": [
|
||||
"api"
|
||||
],
|
||||
"outboundTag": "api",
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"geoip:private"
|
||||
],
|
||||
"outboundTag": "blocked",
|
||||
"ip": ["geoip:private"]
|
||||
"type": "field"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"outboundTag": "blocked",
|
||||
"protocol": ["bittorrent"]
|
||||
"protocol": [
|
||||
"bittorrent"
|
||||
],
|
||||
"type": "field"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"x-ui/database/model"
|
||||
|
||||
sessions "github.com/Calidity/gin-sessions"
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
||||
12
web/web.go
12
web/web.go
@@ -24,9 +24,9 @@ import (
|
||||
"x-ui/web/network"
|
||||
"x-ui/web/service"
|
||||
|
||||
sessions "github.com/Calidity/gin-sessions"
|
||||
"github.com/Calidity/gin-sessions/cookie"
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-contrib/sessions/cookie"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
@@ -332,13 +332,13 @@ func (s *Server) Start() (err error) {
|
||||
}
|
||||
listener = network.NewAutoHttpsListener(listener)
|
||||
listener = tls.NewListener(listener, c)
|
||||
logger.Info("web server run https on", listener.Addr())
|
||||
logger.Info("Web server running HTTPS on", listener.Addr())
|
||||
} else {
|
||||
logger.Error("error in loading certificates: ", err)
|
||||
logger.Info("web server run http on", listener.Addr())
|
||||
logger.Error("Error loading certificates:", err)
|
||||
logger.Info("Web server running HTTP on", listener.Addr())
|
||||
}
|
||||
} else {
|
||||
logger.Info("web server run http on", listener.Addr())
|
||||
logger.Info("Web server running HTTP on", listener.Addr())
|
||||
}
|
||||
s.listener = listener
|
||||
|
||||
|
||||
27
x-ui.sh
27
x-ui.sh
@@ -371,10 +371,31 @@ disable() {
|
||||
}
|
||||
|
||||
show_log() {
|
||||
journalctl -u x-ui.service -e --no-pager -f
|
||||
if [[ $# == 0 ]]; then
|
||||
echo -e "${green}\t1.${plain} Debug Log"
|
||||
echo -e "${green}\t2.${plain} Clear All logs"
|
||||
echo -e "${green}\t0.${plain} Back to Main Menu"
|
||||
read -p "Choose an option: " choice
|
||||
|
||||
case "$choice" in
|
||||
0)
|
||||
return
|
||||
;;
|
||||
1)
|
||||
journalctl -u x-ui -e --no-pager -f -p debug
|
||||
if [[ $# == 0 ]]; then
|
||||
before_show_menu
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
sudo journalctl --rotate
|
||||
sudo journalctl --vacuum-time=1s
|
||||
echo "All Logs cleared."
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
update_shell() {
|
||||
|
||||
Reference in New Issue
Block a user