feat: multi-VLESS server selection + direct mode (stop xray)
- Добавлен home-configs/vless/servers.conf с двумя VLESS серверами - При выборе Y: интерактивное меню выбора сервера (IP + имя) - Парсер vless:// URL через python3 (извлекает все поля) - Конфиг xray генерируется динамически, а не копируется статический - При выборе N: xray стопается и дизейблится (systemctl stop+disable) - Автоотключение IPv6 (sysctl + persist), автонастройка Firefox SOCKS5 - Автонастройка системного прокси через gsettings - Зачистка старых drop-in оверрайдов и дефолтных конфигов xray Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
203
ai-setup.sh
203
ai-setup.sh
@@ -30,15 +30,104 @@ if ! command -v python3 &>/dev/null; then
|
||||
fi
|
||||
success "Python 3 найден"
|
||||
|
||||
# ── VLESS URL parser ───────────────────────────────────────────
|
||||
# Принимает vless:// URL, устанавливает переменные VL_*
|
||||
parse_vless_url() {
|
||||
local url="$1"
|
||||
eval "$(python3 -c "
|
||||
import urllib.parse, sys
|
||||
|
||||
url = sys.argv[1]
|
||||
rest = url[8:] # strip 'vless://'
|
||||
|
||||
at_pos = rest.index('@')
|
||||
uuid = rest[:at_pos]
|
||||
rest = rest[at_pos+1:]
|
||||
|
||||
colon_pos = rest.index(':')
|
||||
q_pos = rest.index('?')
|
||||
host = rest[:colon_pos]
|
||||
port = rest[colon_pos+1:q_pos]
|
||||
|
||||
rest = rest[q_pos+1:]
|
||||
hash_pos = rest.index('#') if '#' in rest else len(rest)
|
||||
qs = rest[:hash_pos]
|
||||
name = rest[hash_pos+1:] if '#' in rest else ''
|
||||
|
||||
params = urllib.parse.parse_qs(qs)
|
||||
def get(p, default=''):
|
||||
vals = params.get(p, [default])
|
||||
return vals[0] if vals else default
|
||||
|
||||
print(f'VL_UUID={uuid}')
|
||||
print(f'VL_ADDRESS={host}')
|
||||
print(f'VL_PORT={port}')
|
||||
print(f'VL_ENCRYPTION={get(\"encryption\")}')
|
||||
print(f'VL_SECURITY={get(\"security\")}')
|
||||
print(f'VL_SNI={get(\"sni\")}')
|
||||
print(f'VL_FP={get(\"fp\", \"chrome\")}')
|
||||
print(f'VL_PBK={get(\"pbk\")}')
|
||||
print(f'VL_SID={get(\"sid\")}')
|
||||
print(f'VL_TYPE={get(\"type\", \"xhttp\")}')
|
||||
print(f'VL_PATH={urllib.parse.unquote(get(\"path\", \"/\"))}')
|
||||
print(f'VL_MODE={get(\"mode\", \"auto\")}')
|
||||
print(f'VL_NAME={name}')
|
||||
" "$url")"
|
||||
}
|
||||
|
||||
# ── 0. Выбор режима работы (vless / direct) ─────────────────
|
||||
read -r -p "Установить встроенный vless? [Y/n] " _vless_ans
|
||||
_vless_ans="${_vless_ans:-Y}"
|
||||
if [[ "$_vless_ans" =~ ^[Yy]$ ]]; then
|
||||
USE_VLESS=1
|
||||
info "Режим: vless + proxychains4"
|
||||
|
||||
# Читаем список серверов
|
||||
_VL_URLS=()
|
||||
_VL_LABELS=()
|
||||
_SERVERS_FILE="$SCRIPT_DIR/home-configs/vless/servers.conf"
|
||||
|
||||
if [ ! -f "$_SERVERS_FILE" ]; then
|
||||
err "Файл servers.conf не найден: $_SERVERS_FILE"
|
||||
fi
|
||||
|
||||
while IFS= read -r line; do
|
||||
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
||||
[[ -z "$line" ]] && continue
|
||||
_vl_rest="${line#vless://}"
|
||||
_vl_rest="${_vl_rest#*@}"
|
||||
_vl_ip="${_vl_rest%%:*}"
|
||||
_vl_name="${line##*#}"
|
||||
[[ "$_vl_name" == "$line" ]] && _vl_name=""
|
||||
_VL_URLS+=("$line")
|
||||
_VL_LABELS+=("$_vl_ip ($_vl_name)")
|
||||
done < "$_SERVERS_FILE"
|
||||
|
||||
if [ "${#_VL_URLS[@]}" -eq 0 ]; then
|
||||
err "Нет VLESS серверов в $_SERVERS_FILE"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
info "Доступные VLESS серверы:"
|
||||
for i in "${!_VL_LABELS[@]}"; do
|
||||
echo -e " ${GREEN}$((i+1))${NC}) ${_VL_LABELS[$i]}"
|
||||
done
|
||||
|
||||
read -r -p "Выбери сервер [1-${#_VL_URLS[@]}]: " _vl_choice
|
||||
_vl_choice="${_vl_choice:-1}"
|
||||
if ! [[ "$_vl_choice" =~ ^[0-9]+$ ]] || [ "$_vl_choice" -lt 1 ] || [ "$_vl_choice" -gt "${#_VL_URLS[@]}" ]; then
|
||||
err "Неверный выбор: $_vl_choice"
|
||||
fi
|
||||
|
||||
_VL_SELECTED="${_VL_URLS[$((_vl_choice-1))]}"
|
||||
parse_vless_url "$_VL_SELECTED"
|
||||
info "Выбран: $VL_ADDRESS ($VL_NAME)"
|
||||
else
|
||||
USE_VLESS=0
|
||||
info "Режим: direct (без проксирования)"
|
||||
|
||||
# Останавливаем и отключаем xray (мог остаться от предыдущей установки)
|
||||
sudo systemctl stop xray 2>/dev/null || true
|
||||
sudo systemctl disable xray 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# ── 1. npm prefix в домашнюю папку ──────────────────────────
|
||||
@@ -88,6 +177,10 @@ if [ "$USE_VLESS" -eq 1 ]; then
|
||||
fi
|
||||
|
||||
info "Устанавливаю xray..."
|
||||
|
||||
# Останавливаем старый процесс (мог остаться от предыдущей установки)
|
||||
sudo systemctl stop xray 2>/dev/null || true
|
||||
|
||||
XRAY_VERSION="26.3.27"
|
||||
XRAY_ARCH="64"
|
||||
XRAY_URL="https://github.com/XTLS/Xray-core/releases/download/v${XRAY_VERSION}/Xray-linux-${XRAY_ARCH}.zip"
|
||||
@@ -99,7 +192,58 @@ if [ "$USE_VLESS" -eq 1 ]; then
|
||||
rm -rf "$TMPDIR"
|
||||
|
||||
sudo mkdir -p /etc/xray
|
||||
sudo cp "$SCRIPT_DIR/home-configs/xray/config.json" /etc/xray/config.json
|
||||
sudo tee /etc/xray/config.json > /dev/null << XRAYEOF
|
||||
{
|
||||
"log": { "loglevel": "warning" },
|
||||
"inbounds": [
|
||||
{
|
||||
"port": 1080,
|
||||
"listen": "127.0.0.1",
|
||||
"protocol": "socks",
|
||||
"settings": { "udp": true }
|
||||
},
|
||||
{
|
||||
"port": 2080,
|
||||
"listen": "127.0.0.1",
|
||||
"protocol": "http"
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "$VL_ADDRESS",
|
||||
"port": $VL_PORT,
|
||||
"users": [
|
||||
{
|
||||
"id": "$VL_UUID",
|
||||
"encryption": "$VL_ENCRYPTION",
|
||||
"flow": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "$VL_TYPE",
|
||||
"security": "$VL_SECURITY",
|
||||
"realitySettings": {
|
||||
"serverName": "$VL_SNI",
|
||||
"fingerprint": "$VL_FP",
|
||||
"publicKey": "$VL_PBK",
|
||||
"shortId": "$VL_SID"
|
||||
},
|
||||
"xhttpSettings": {
|
||||
"path": "$VL_PATH",
|
||||
"mode": "$VL_MODE"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
XRAYEOF
|
||||
sudo chmod 644 /etc/xray/config.json
|
||||
|
||||
sudo tee /etc/systemd/system/xray.service > /dev/null << 'SVCEOF'
|
||||
@@ -115,12 +259,67 @@ Restart=on-failure
|
||||
WantedBy=multi-user.target
|
||||
SVCEOF
|
||||
|
||||
# Удаляем чужие drop-in оверрайды (могут переопределять ExecStart на старый конфиг)
|
||||
sudo rm -rf /etc/systemd/system/xray.service.d/
|
||||
# Удаляем старый дефолтный конфиг xray из других путей
|
||||
sudo rm -rf /usr/local/etc/xray/
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now xray
|
||||
success "xray установлен и запущен"
|
||||
|
||||
# ── Отключение IPv6 (VLESS не тянет IPv6, браузеры зависают) ──
|
||||
info "Отключаю IPv6 на уровне системы..."
|
||||
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
|
||||
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
|
||||
sudo tee /etc/sysctl.d/99-disable-ipv6.conf > /dev/null << 'SYSCTEOF'
|
||||
# Отключение IPv6 — требуется для стабильной работы VLESS/xray
|
||||
net.ipv6.conf.all.disable_ipv6=1
|
||||
net.ipv6.conf.default.disable_ipv6=1
|
||||
SYSCTEOF
|
||||
sudo systemctl restart systemd-resolved
|
||||
success "IPv6 отключён, DNS-кэш очищен"
|
||||
|
||||
cp "$SCRIPT_DIR/home-configs/proxychains/proxychains-xray.conf" "$HOME/.proxychains-xray.conf"
|
||||
success "Proxychains конфиг обновлён"
|
||||
|
||||
# ── Настройка Firefox на SOCKS5 + remote DNS ────────────────
|
||||
info "Настраиваю Firefox на SOCKS5 прокси..."
|
||||
FIREFOX_PROFILE=""
|
||||
if [ -d "$HOME/snap/firefox/common/.mozilla/firefox" ]; then
|
||||
FIREFOX_PROFILE=$(find "$HOME/snap/firefox/common/.mozilla/firefox" -name "*.default*" -type d | head -1)
|
||||
elif [ -d "$HOME/.mozilla/firefox" ]; then
|
||||
FIREFOX_PROFILE=$(find "$HOME/.mozilla/firefox" -name "*.default*" -type d | head -1)
|
||||
fi
|
||||
|
||||
if [ -n "$FIREFOX_PROFILE" ]; then
|
||||
cat > "$FIREFOX_PROFILE/user.js" << 'FJSEOF'
|
||||
user_pref("network.proxy.type", 1);
|
||||
user_pref("network.proxy.socks", "127.0.0.1");
|
||||
user_pref("network.proxy.socks_port", 1080);
|
||||
user_pref("network.proxy.socks_remote_dns", true);
|
||||
user_pref("network.proxy.http", "");
|
||||
user_pref("network.proxy.http_port", 0);
|
||||
user_pref("network.proxy.ssl", "");
|
||||
user_pref("network.proxy.ssl_port", 0);
|
||||
FJSEOF
|
||||
success "Firefox настроен на SOCKS5 (профиль: $FIREFOX_PROFILE)"
|
||||
else
|
||||
warn "Firefox не найден, пропускаю настройку прокси"
|
||||
fi
|
||||
|
||||
# ── Настройка системного прокси (для Chrome/Chromium) ───────
|
||||
info "Настраиваю системный прокси..."
|
||||
if command -v gsettings &>/dev/null; then
|
||||
gsettings set org.gnome.system.proxy mode 'manual' 2>/dev/null || true
|
||||
gsettings set org.gnome.system.proxy.http host '127.0.0.1' 2>/dev/null || true
|
||||
gsettings set org.gnome.system.proxy.http port 2080 2>/dev/null || true
|
||||
gsettings set org.gnome.system.proxy.socks host '127.0.0.1' 2>/dev/null || true
|
||||
gsettings set org.gnome.system.proxy.socks port 1080 2>/dev/null || true
|
||||
success "Системный прокси настроен (HTTP 2080 + SOCKS 1080)"
|
||||
else
|
||||
warn "gsettings не найден, пропускаю настройку системного прокси"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 3. Claude Code ───────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user