Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f335c8d39a | ||
|
|
36d9a43421 | ||
|
|
5d118afb07 | ||
|
|
56c30d4d0c | ||
|
|
4c4a70e742 | ||
|
|
581e3b835a | ||
|
|
ccfeb28492 | ||
|
|
100bd29c92 | ||
|
|
6ed818cd67 | ||
|
|
698bf1d390 | ||
|
|
aeed8db419 | ||
|
|
10191887af |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,4 +5,5 @@ bin/config.json
|
|||||||
dist/
|
dist/
|
||||||
x-ui-*.tar.gz
|
x-ui-*.tar.gz
|
||||||
/x-ui
|
/x-ui
|
||||||
/release.sh
|
/release.sh
|
||||||
|
.sync*
|
||||||
11
README.md
11
README.md
@@ -13,11 +13,11 @@
|
|||||||
|
|
||||||
# 安装&升级
|
# 安装&升级
|
||||||
```
|
```
|
||||||
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)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 手动安装&升级
|
## 手动安装&升级
|
||||||
1. 首先从 https://github.com/sprov065/x-ui/releases 下载最新的压缩包,一般选择`amd64`架构
|
1. 首先从 https://github.com/vaxilu/x-ui/releases 下载最新的压缩包,一般选择`amd64`架构
|
||||||
2. 然后将这个压缩包上传到服务器的`/root/`目录下,并使用`root`用户登录服务器
|
2. 然后将这个压缩包上传到服务器的`/root/`目录下,并使用`root`用户登录服务器
|
||||||
|
|
||||||
> 如果你的服务器 cpu 架构不是`amd64`,自行将命令中的`amd64`替换为其他架构
|
> 如果你的服务器 cpu 架构不是`amd64`,自行将命令中的`amd64`替换为其他架构
|
||||||
@@ -53,11 +53,6 @@ x-ui 可与 v2-ui 并存,数据不互通,不影响对方的运行
|
|||||||
x-ui v2-ui
|
x-ui v2-ui
|
||||||
```
|
```
|
||||||
|
|
||||||
# Telegram
|
|
||||||
群组:https://t.me/sprov_blog
|
|
||||||
|
|
||||||
频道:https://t.me/sprov_channel
|
|
||||||
|
|
||||||
## Stargazers over time
|
## Stargazers over time
|
||||||
|
|
||||||
[](https://starchart.cc/sprov065/x-ui)
|
[](https://starchart.cc/vaxilu/x-ui)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.3.1
|
0.3.2
|
||||||
@@ -84,20 +84,20 @@ install_x-ui() {
|
|||||||
cd /usr/local/
|
cd /usr/local/
|
||||||
|
|
||||||
if [ $# == 0 ] ;then
|
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
|
if [[ ! -n "$last_version" ]]; then
|
||||||
echo -e "${red}检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装${plain}"
|
echo -e "${red}检测 x-ui 版本失败,可能是超出 Github API 限制,请稍后再试,或手动指定 x-ui 版本安装${plain}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo -e "检测到 x-ui 最新版本:${last_version},开始安装"
|
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
|
if [[ $? -ne 0 ]]; then
|
||||||
echo -e "${red}下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件${plain}"
|
echo -e "${red}下载 x-ui 失败,请确保你的服务器能够下载 Github 的文件${plain}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
last_version=$1
|
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"
|
echo -e "开始安装 x-ui v$1"
|
||||||
wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url}
|
wget -N --no-check-certificate -O /usr/local/x-ui-linux-${arch}.tar.gz ${url}
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const RULE_DOMAIN = {
|
|||||||
SPEEDTEST: 'geosite:speedtest',
|
SPEEDTEST: 'geosite:speedtest',
|
||||||
};
|
};
|
||||||
|
|
||||||
const VLESS_FLOW = {
|
const FLOW_CONTROL = {
|
||||||
ORIGIN: "xtls-rprx-origin",
|
ORIGIN: "xtls-rprx-origin",
|
||||||
DIRECT: "xtls-rprx-direct",
|
DIRECT: "xtls-rprx-direct",
|
||||||
};
|
};
|
||||||
@@ -50,7 +50,7 @@ Object.freeze(VmessMethods);
|
|||||||
Object.freeze(SSMethods);
|
Object.freeze(SSMethods);
|
||||||
Object.freeze(RULE_IP);
|
Object.freeze(RULE_IP);
|
||||||
Object.freeze(RULE_DOMAIN);
|
Object.freeze(RULE_DOMAIN);
|
||||||
Object.freeze(VLESS_FLOW);
|
Object.freeze(FLOW_CONTROL);
|
||||||
|
|
||||||
class XrayCommonClass {
|
class XrayCommonClass {
|
||||||
|
|
||||||
@@ -697,11 +697,13 @@ class Inbound extends XrayCommonClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VLess
|
// VLess & Trojan
|
||||||
get flow() {
|
get flow() {
|
||||||
switch (this.protocol) {
|
switch (this.protocol) {
|
||||||
case Protocols.VLESS:
|
case Protocols.VLESS:
|
||||||
return this.settings.vlesses[0].flow;
|
return this.settings.vlesses[0].flow;
|
||||||
|
case Protocols.TROJAN:
|
||||||
|
return this.settings.clients[0].flow;
|
||||||
default:
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -1008,18 +1010,6 @@ class Inbound extends XrayCommonClass {
|
|||||||
params.set("flow", this.settings.vlesses[0].flow);
|
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 link = `vless://${uuid}@${address}:${port}`;
|
||||||
const url = new URL(link);
|
const url = new URL(link);
|
||||||
for (const [key, value] of params) {
|
for (const [key, value] of params) {
|
||||||
@@ -1217,7 +1207,7 @@ Inbound.VLESSSettings = class extends Inbound.Settings {
|
|||||||
};
|
};
|
||||||
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
|
||||||
|
|
||||||
constructor(id=RandomUtil.randomUUID(), flow=VLESS_FLOW.DIRECT) {
|
constructor(id=RandomUtil.randomUUID(), flow=FLOW_CONTROL.DIRECT) {
|
||||||
super();
|
super();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.flow = flow;
|
this.flow = flow;
|
||||||
@@ -1270,14 +1260,26 @@ Inbound.VLESSSettings.Fallback = class extends XrayCommonClass {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Inbound.TrojanSettings = class extends Inbound.Settings {
|
Inbound.TrojanSettings = class extends Inbound.Settings {
|
||||||
constructor(protocol, clients=[new Inbound.TrojanSettings.Client()]) {
|
constructor(protocol,
|
||||||
|
clients=[new Inbound.TrojanSettings.Client()],
|
||||||
|
fallbacks=[],) {
|
||||||
super(protocol);
|
super(protocol);
|
||||||
this.clients = clients;
|
this.clients = clients;
|
||||||
|
this.fallbacks = fallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
addTrojanFallback() {
|
||||||
|
this.fallbacks.push(new Inbound.TrojanSettings.Fallback());
|
||||||
|
}
|
||||||
|
|
||||||
|
delTrojanFallback(index) {
|
||||||
|
this.fallbacks.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
clients: Inbound.TrojanSettings.toJsonArray(this.clients),
|
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) {
|
for (const c of json.clients) {
|
||||||
clients.push(Inbound.TrojanSettings.Client.fromJson(c));
|
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 {
|
Inbound.TrojanSettings.Client = class extends XrayCommonClass {
|
||||||
constructor(password=RandomUtil.randomSeq(10)) {
|
constructor(password=RandomUtil.randomSeq(10), flow=FLOW_CONTROL.DIRECT) {
|
||||||
super();
|
super();
|
||||||
this.password = password;
|
this.password = password;
|
||||||
|
this.flow = flow;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
return {
|
return {
|
||||||
password: this.password,
|
password: this.password,
|
||||||
|
flow: this.flow,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
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 {
|
Inbound.ShadowsocksSettings = class extends Inbound.Settings {
|
||||||
constructor(protocol,
|
constructor(protocol,
|
||||||
method=SSMethods.AES_256_GCM,
|
method=SSMethods.AES_256_GCM,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<a-icon type="link"></a-icon>
|
<a-icon type="link"></a-icon>
|
||||||
<span>其他</span>
|
<span>其他</span>
|
||||||
</template>
|
</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>
|
<a-icon type="github"></a-icon>
|
||||||
<span>Github</span>
|
<span>Github</span>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
|
|||||||
@@ -3,5 +3,47 @@
|
|||||||
<a-form-item label="密码">
|
<a-form-item label="密码">
|
||||||
<a-input v-model.trim="inbound.settings.clients[0].password"></a-input>
|
<a-input v-model.trim="inbound.settings.clients[0].password"></a-input>
|
||||||
</a-form-item>
|
</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>
|
</a-form>
|
||||||
{{end}}
|
{{end}}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<a-form-item v-if="inbound.xtls" label="flow">
|
<a-form-item v-if="inbound.xtls" label="flow">
|
||||||
<a-select v-model="inbound.settings.vlesses[0].flow" style="width: 150px">
|
<a-select v-model="inbound.settings.vlesses[0].flow" style="width: 150px">
|
||||||
<a-select-option value="">无</a-select-option>
|
<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-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, error) {
|
|||||||
func (s *XrayService) RestartXray(isForce bool) error {
|
func (s *XrayService) RestartXray(isForce bool) error {
|
||||||
lock.Lock()
|
lock.Lock()
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
logger.Debug("restart xray")
|
logger.Debug("restart xray, force:", isForce)
|
||||||
|
|
||||||
xrayConfig, err := s.GetXrayConfig()
|
xrayConfig, err := s.GetXrayConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
13
x-ui.sh
13
x-ui.sh
@@ -82,7 +82,7 @@ before_show_menu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
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
|
||||||
if [[ $# == 0 ]]; then
|
if [[ $# == 0 ]]; then
|
||||||
start
|
start
|
||||||
@@ -101,7 +101,7 @@ update() {
|
|||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
fi
|
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
|
if [[ $? == 0 ]]; then
|
||||||
echo -e "${green}更新完成,已自动重启面板${plain}"
|
echo -e "${green}更新完成,已自动重启面板${plain}"
|
||||||
exit 0
|
exit 0
|
||||||
@@ -127,9 +127,6 @@ uninstall() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e "卸载成功,如果你想删除此脚本,则退出脚本后运行 ${green}rm /usr/bin/x-ui -f${plain} 进行删除"
|
echo -e "卸载成功,如果你想删除此脚本,则退出脚本后运行 ${green}rm /usr/bin/x-ui -f${plain} 进行删除"
|
||||||
echo ""
|
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
|
if [[ $# == 0 ]]; then
|
||||||
before_show_menu
|
before_show_menu
|
||||||
@@ -277,13 +274,14 @@ migrate_v2_ui() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_bbr() {
|
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 ""
|
echo ""
|
||||||
before_show_menu
|
before_show_menu
|
||||||
}
|
}
|
||||||
|
|
||||||
update_shell() {
|
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
|
if [[ $? != 0 ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${red}下载脚本失败,请检查本机能否连接 Github${plain}"
|
echo -e "${red}下载脚本失败,请检查本机能否连接 Github${plain}"
|
||||||
@@ -409,7 +407,6 @@ show_usage() {
|
|||||||
show_menu() {
|
show_menu() {
|
||||||
echo -e "
|
echo -e "
|
||||||
${green}x-ui 面板管理脚本${plain}
|
${green}x-ui 面板管理脚本${plain}
|
||||||
--- https://blog.sprov.xyz/x-ui ---
|
|
||||||
${green}0.${plain} 退出脚本
|
${green}0.${plain} 退出脚本
|
||||||
————————————————
|
————————————————
|
||||||
${green}1.${plain} 安装 x-ui
|
${green}1.${plain} 安装 x-ui
|
||||||
|
|||||||
Reference in New Issue
Block a user