Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f335c8d39a | ||
|
|
36d9a43421 | ||
|
|
5d118afb07 | ||
|
|
56c30d4d0c | ||
|
|
4c4a70e742 | ||
|
|
581e3b835a | ||
|
|
ccfeb28492 | ||
|
|
100bd29c92 | ||
|
|
6ed818cd67 | ||
|
|
698bf1d390 | ||
|
|
aeed8db419 | ||
|
|
10191887af | ||
|
|
b240b843c8 | ||
|
|
500b08b112 | ||
|
|
64c5ecce99 | ||
|
|
3e08b794be | ||
|
|
e473b7393e | ||
|
|
942ac7f562 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,4 +5,5 @@ bin/config.json
|
||||
dist/
|
||||
x-ui-*.tar.gz
|
||||
/x-ui
|
||||
/release.sh
|
||||
/release.sh
|
||||
.sync*
|
||||
30
README.md
30
README.md
@@ -6,14 +6,33 @@
|
||||
- 支持多用户多协议,网页可视化操作
|
||||
- 支持的协议:vmess、vless、trojan、shadowsocks、dokodemo-door、socks、http
|
||||
- 支持配置更多传输配置
|
||||
- 账号流量统计
|
||||
- 流量统计,限制流量,限制到期时间
|
||||
- 可自定义 xray 配置模板
|
||||
- 支持 https 访问面板(自备域名 + ssl 证书)
|
||||
- 更多高级配置项,详见面板
|
||||
|
||||
# 安装&升级
|
||||
```
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/sprov065/x-ui/master/install.sh) 0.2.0
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh)
|
||||
```
|
||||
|
||||
## 手动安装&升级
|
||||
1. 首先从 https://github.com/vaxilu/x-ui/releases 下载最新的压缩包,一般选择`amd64`架构
|
||||
2. 然后将这个压缩包上传到服务器的`/root/`目录下,并使用`root`用户登录服务器
|
||||
|
||||
> 如果你的服务器 cpu 架构不是`amd64`,自行将命令中的`amd64`替换为其他架构
|
||||
|
||||
```
|
||||
cd /root/
|
||||
rm x-ui/ /usr/local/x-ui/ /usr/bin/x-ui -rf
|
||||
tar zxvf x-ui-linux-amd64.tar.gz
|
||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
||||
mv x-ui/ /usr/local/
|
||||
systemctl daemon-reload
|
||||
systemctl enable x-ui
|
||||
systemctl restart x-ui
|
||||
```
|
||||
|
||||
## 建议系统
|
||||
@@ -34,11 +53,6 @@ x-ui 可与 v2-ui 并存,数据不互通,不影响对方的运行
|
||||
x-ui v2-ui
|
||||
```
|
||||
|
||||
# Telegram
|
||||
群组:https://t.me/sprov_blog
|
||||
|
||||
频道:https://t.me/sprov_channel
|
||||
|
||||
## Stargazers over time
|
||||
|
||||
[](https://starchart.cc/sprov065/x-ui)
|
||||
[](https://starchart.cc/vaxilu/x-ui)
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.3.0
|
||||
0.3.2
|
||||
18
install.sh
18
install.sh
@@ -82,25 +82,22 @@ install_base() {
|
||||
install_x-ui() {
|
||||
systemctl stop x-ui
|
||||
cd /usr/local/
|
||||
if [[ -e /usr/local/x-ui/ ]]; then
|
||||
rm /usr/local/x-ui/ -rf
|
||||
fi
|
||||
|
||||
if [ $# == 0 ] ;then
|
||||
last_version=$(curl -Ls "https://api.github.com/repos/sprov065/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
last_version=$(curl -Ls "https://api.github.com/repos/vaxilu/x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||
if [[ ! -n "$last_version" ]]; then
|
||||
echo -e "${red}检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装${plain}"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "检测到 x-ui 最新版本:${last_version},开始安装"
|
||||
wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/sprov065/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz
|
||||
wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz https://github.com/vaxilu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo -e "${red}下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件${plain}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
last_version=$1
|
||||
url="https://github.com/sprov065/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz"
|
||||
url="https://github.com/vaxilu/x-ui/releases/download/${last_version}/x-ui-linux-${arch}.tar.gz"
|
||||
echo -e "开始安装 x-ui v$1"
|
||||
wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url}
|
||||
if [[ $? -ne 0 ]]; then
|
||||
@@ -109,11 +106,16 @@ install_x-ui() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -e /usr/local/x-ui/ ]]; then
|
||||
rm /usr/local/x-ui/ -rf
|
||||
fi
|
||||
|
||||
tar zxvf x-ui-linux-${arch}.tar.gz
|
||||
rm x-ui-linux-${arch}.tar.gz -f
|
||||
cd x-ui
|
||||
chmod +x x-ui bin/xray-linux-${arch}
|
||||
chmod +x x-ui bin/xray-linux-${arch} x-ui.sh
|
||||
cp -f x-ui.service /etc/systemd/system/
|
||||
cp -f x-ui.sh /usr/bin/x-ui
|
||||
systemctl daemon-reload
|
||||
systemctl enable x-ui
|
||||
systemctl start x-ui
|
||||
@@ -125,8 +127,6 @@ install_x-ui() {
|
||||
echo -e ""
|
||||
echo -e "如果是更新面板,则按你之前的方式访问面板"
|
||||
echo -e ""
|
||||
curl -o /usr/bin/x-ui -Ls https://raw.githubusercontent.com/sprov065/x-ui/master/x-ui.sh
|
||||
chmod +x /usr/bin/x-ui
|
||||
echo -e "x-ui 管理脚本使用方法: "
|
||||
echo -e "----------------------------------------------"
|
||||
echo -e "x-ui - 显示管理菜单 (功能更多)"
|
||||
|
||||
@@ -40,7 +40,7 @@ const RULE_DOMAIN = {
|
||||
SPEEDTEST: 'geosite:speedtest',
|
||||
};
|
||||
|
||||
const VLESS_FLOW = {
|
||||
const FLOW_CONTROL = {
|
||||
ORIGIN: "xtls-rprx-origin",
|
||||
DIRECT: "xtls-rprx-direct",
|
||||
};
|
||||
@@ -50,7 +50,7 @@ Object.freeze(VmessMethods);
|
||||
Object.freeze(SSMethods);
|
||||
Object.freeze(RULE_IP);
|
||||
Object.freeze(RULE_DOMAIN);
|
||||
Object.freeze(VLESS_FLOW);
|
||||
Object.freeze(FLOW_CONTROL);
|
||||
|
||||
class XrayCommonClass {
|
||||
|
||||
@@ -697,11 +697,13 @@ class Inbound extends XrayCommonClass {
|
||||
}
|
||||
}
|
||||
|
||||
// VLess
|
||||
// VLess & Trojan
|
||||
get flow() {
|
||||
switch (this.protocol) {
|
||||
case Protocols.VLESS:
|
||||
return this.settings.vlesses[0].flow;
|
||||
case Protocols.TROJAN:
|
||||
return this.settings.clients[0].flow;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -1008,18 +1010,6 @@ class Inbound extends XrayCommonClass {
|
||||
params.set("flow", this.settings.vlesses[0].flow);
|
||||
}
|
||||
|
||||
for (const [key, value] of params) {
|
||||
switch (key) {
|
||||
case "host":
|
||||
case "path":
|
||||
case "seed":
|
||||
case "key":
|
||||
case "alpn":
|
||||
params.set(key, encodeURIComponent(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const link = `vless://${uuid}@${address}:${port}`;
|
||||
const url = new URL(link);
|
||||
for (const [key, value] of params) {
|
||||
@@ -1217,7 +1207,7 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
|
||||
};
|
||||
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
||||
|
||||
constructor(id=RandomUtil.randomUUID(), flow=VLESS_FLOW.DIRECT) {
|
||||
constructor(id=RandomUtil.randomUUID(), flow=FLOW_CONTROL.DIRECT) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.flow = flow;
|
||||
@@ -1270,14 +1260,26 @@ Inbound.VLESSSettings.Fallback = class extends XrayCommonClass {
|
||||
};
|
||||
|
||||
Inbound.TrojanSettings = class extends Inbound.Settings {
|
||||
constructor(protocol, clients=[new Inbound.TrojanSettings.Client()]) {
|
||||
constructor(protocol,
|
||||
clients=[new Inbound.TrojanSettings.Client()],
|
||||
fallbacks=[],) {
|
||||
super(protocol);
|
||||
this.clients = clients;
|
||||
this.fallbacks = fallbacks;
|
||||
}
|
||||
|
||||
addTrojanFallback() {
|
||||
this.fallbacks.push(new Inbound.TrojanSettings.Fallback());
|
||||
}
|
||||
|
||||
delTrojanFallback(index) {
|
||||
this.fallbacks.splice(index, 1);
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
clients: Inbound.TrojanSettings.toJsonArray(this.clients),
|
||||
fallbacks: Inbound.TrojanSettings.toJsonArray(this.fallbacks),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1286,27 +1288,74 @@ Inbound.TrojanSettings = class extends Inbound.Settings {
|
||||
for (const c of json.clients) {
|
||||
clients.push(Inbound.TrojanSettings.Client.fromJson(c));
|
||||
}
|
||||
return new Inbound.TrojanSettings(Protocols.TROJAN, clients);
|
||||
return new Inbound.TrojanSettings(
|
||||
Protocols.TROJAN,
|
||||
clients,
|
||||
Inbound.TrojanSettings.Fallback.fromJson(json.fallbacks),);
|
||||
}
|
||||
};
|
||||
Inbound.TrojanSettings.Client = class extends XrayCommonClass {
|
||||
constructor(password=RandomUtil.randomSeq(10)) {
|
||||
constructor(password=RandomUtil.randomSeq(10), flow=FLOW_CONTROL.DIRECT) {
|
||||
super();
|
||||
this.password = password;
|
||||
this.flow = flow;
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
password: this.password,
|
||||
flow: this.flow,
|
||||
};
|
||||
}
|
||||
|
||||
static fromJson(json={}) {
|
||||
return new Inbound.TrojanSettings.Client(json.password);
|
||||
return new Inbound.TrojanSettings.Client(
|
||||
json.password,
|
||||
json.flow,
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Inbound.TrojanSettings.Fallback = class extends XrayCommonClass {
|
||||
constructor(name="", alpn='', path='', dest='', xver=0) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.alpn = alpn;
|
||||
this.path = path;
|
||||
this.dest = dest;
|
||||
this.xver = xver;
|
||||
}
|
||||
|
||||
toJson() {
|
||||
let xver = this.xver;
|
||||
if (!Number.isInteger(xver)) {
|
||||
xver = 0;
|
||||
}
|
||||
return {
|
||||
name: this.name,
|
||||
alpn: this.alpn,
|
||||
path: this.path,
|
||||
dest: this.dest,
|
||||
xver: xver,
|
||||
}
|
||||
}
|
||||
|
||||
static fromJson(json=[]) {
|
||||
const fallbacks = [];
|
||||
for (let fallback of json) {
|
||||
fallbacks.push(new Inbound.TrojanSettings.Fallback(
|
||||
fallback.name,
|
||||
fallback.alpn,
|
||||
fallback.path,
|
||||
fallback.dest,
|
||||
fallback.xver,
|
||||
))
|
||||
}
|
||||
return fallbacks;
|
||||
}
|
||||
};
|
||||
|
||||
Inbound.ShadowsocksSettings = class extends Inbound.Settings {
|
||||
constructor(protocol,
|
||||
method=SSMethods.AES_256_GCM,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<a-icon type="link"></a-icon>
|
||||
<span>其他</span>
|
||||
</template>
|
||||
<a-menu-item key="https://github.com/sprov065/x-ui/">
|
||||
<a-menu-item key="https://github.com/vaxilu/x-ui/">
|
||||
<a-icon type="github"></a-icon>
|
||||
<span>Github</span>
|
||||
</a-menu-item>
|
||||
|
||||
@@ -3,5 +3,47 @@
|
||||
<a-form-item label="密码">
|
||||
<a-input v-model.trim="inbound.settings.clients[0].password"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="inbound.xtls" label="flow">
|
||||
<a-select v-model="inbound.settings.clients[0].flow" style="width: 150px">
|
||||
<a-select-option value="">无</a-select-option>
|
||||
<a-select-option v-for="key in FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<a-form layout="inline">
|
||||
<a-form-item label="fallbacks">
|
||||
<a-row>
|
||||
<a-button type="primary" size="small"
|
||||
@click="inbound.settings.addTrojanFallback()">
|
||||
+
|
||||
</a-button>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<!-- trojan fallbacks -->
|
||||
<a-form v-for="(fallback, index) in inbound.settings.fallbacks" layout="inline">
|
||||
<a-divider>
|
||||
fallback[[ index + 1 ]]
|
||||
<a-icon type="delete" @click="() => inbound.settings.delTrojanFallback(index)"
|
||||
style="color: rgb(255, 77, 79);cursor: pointer;"/>
|
||||
</a-divider>
|
||||
<a-form-item label="name">
|
||||
<a-input v-model="fallback.name"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="alpn">
|
||||
<a-input v-model="fallback.alpn"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="path">
|
||||
<a-input v-model="fallback.path"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="dest">
|
||||
<a-input v-model="fallback.dest"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="xver">
|
||||
<a-input type="number" v-model.number="fallback.xver"></a-input>
|
||||
</a-form-item>
|
||||
<a-divider v-if="inbound.settings.fallbacks.length - 1 === index"/>
|
||||
</a-form>
|
||||
{{end}}
|
||||
@@ -6,7 +6,7 @@
|
||||
<a-form-item v-if="inbound.xtls" label="flow">
|
||||
<a-select v-model="inbound.settings.vlesses[0].flow" style="width: 150px">
|
||||
<a-select-option value="">无</a-select-option>
|
||||
<a-select-option v-for="key in VLESS_FLOW" :value="key">[[ key ]]</a-select-option>
|
||||
<a-select-option v-for="key in FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
@@ -167,7 +167,7 @@ func (s *InboundService) AddTraffic(traffics []*xray.Traffic) (err error) {
|
||||
|
||||
func (s *InboundService) DisableInvalidInbounds() (int64, error) {
|
||||
db := database.GetDB()
|
||||
now := time.Now()
|
||||
now := time.Now().Unix() * 1000
|
||||
result := db.Model(model.Inbound{}).
|
||||
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
|
||||
Update("enable", false)
|
||||
|
||||
@@ -87,7 +87,7 @@ func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, error) {
|
||||
func (s *XrayService) RestartXray(isForce bool) error {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
logger.Debug("restart xray")
|
||||
logger.Debug("restart xray, force:", isForce)
|
||||
|
||||
xrayConfig, err := s.GetXrayConfig()
|
||||
if err != nil {
|
||||
|
||||
13
x-ui.sh
13
x-ui.sh
@@ -82,7 +82,7 @@ before_show_menu() {
|
||||
}
|
||||
|
||||
install() {
|
||||
bash <(curl -Ls https://blog.sprov.xyz/x-ui.sh)
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh)
|
||||
if [[ $? == 0 ]]; then
|
||||
if [[ $# == 0 ]]; then
|
||||
start
|
||||
@@ -101,7 +101,7 @@ update() {
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/sprov065/x-ui/master/install.sh)
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/vaxilu/x-ui/master/install.sh)
|
||||
if [[ $? == 0 ]]; then
|
||||
echo -e "${green}更新完成,已自动重启面板${plain}"
|
||||
exit 0
|
||||
@@ -127,9 +127,6 @@ uninstall() {
|
||||
echo ""
|
||||
echo -e "卸载成功,如果你想删除此脚本,则退出脚本后运行 ${green}rm /usr/bin/x-ui -f${plain} 进行删除"
|
||||
echo ""
|
||||
echo -e "Telegram 群组: ${green}https://t.me/sprov_blog${plain}"
|
||||
echo -e "Github issues: ${green}https://github.com/sprov065/x-ui/issues${plain}"
|
||||
echo -e "博客: ${green}https://blog.sprov.xyz/x-ui${plain}"
|
||||
|
||||
if [[ $# == 0 ]]; then
|
||||
before_show_menu
|
||||
@@ -277,13 +274,14 @@ migrate_v2_ui() {
|
||||
}
|
||||
|
||||
install_bbr() {
|
||||
bash <(curl -L -s https://raw.githubusercontent.com/sprov065/blog/master/bbr.sh)
|
||||
# temporary workaround for installing bbr
|
||||
bash <(curl -L -s https://raw.githubusercontent.com/teddysun/across/master/bbr.sh)
|
||||
echo ""
|
||||
before_show_menu
|
||||
}
|
||||
|
||||
update_shell() {
|
||||
wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/sprov065/x-ui/raw/master/x-ui.sh
|
||||
wget -O /usr/bin/x-ui -N --no-check-certificate https://github.com/vaxilu/x-ui/raw/master/x-ui.sh
|
||||
if [[ $? != 0 ]]; then
|
||||
echo ""
|
||||
echo -e "${red}下载脚本失败,请检查本机能否连接 Github${plain}"
|
||||
@@ -409,7 +407,6 @@ show_usage() {
|
||||
show_menu() {
|
||||
echo -e "
|
||||
${green}x-ui 面板管理脚本${plain}
|
||||
--- https://blog.sprov.xyz/x-ui ---
|
||||
${green}0.${plain} 退出脚本
|
||||
————————————————
|
||||
${green}1.${plain} 安装 x-ui
|
||||
|
||||
Reference in New Issue
Block a user