mirror of
https://github.com/anten-ka/go_warp_pro.git
synced 2026-05-19 16:16:14 +00:00
v2.1: unified client toggle, 3X-UI SOCKS5 submenu, fix 14 bugs across 3 audit cycles
Made-with: Cursor
This commit is contained in:
65
README.md
65
README.md
@@ -40,7 +40,7 @@ WireGuard-интерфейс WARP внутри Docker-контейнера Amnez
|
||||
| JSON-конфиги для Xray | ✅ | — |
|
||||
| Маршрутизация по доменам | ✅ | — |
|
||||
| Изменение порта SOCKS5 | ✅ | — |
|
||||
| Управление клиентами (add/remove) | — | ✅ |
|
||||
| Управление клиентами (переключатели ✅/☐ в одном меню) | — | ✅ |
|
||||
| WireGuard внутри Docker | — | ✅ |
|
||||
| Перезапуск контейнера | — | ✅ |
|
||||
|
||||
@@ -249,31 +249,30 @@ curl -s --proxy socks5h://127.0.0.1:40000 ifconfig.me
|
||||
- Поднимет WG-интерфейс `warp` внутри контейнера
|
||||
- Покажет WARP IP
|
||||
|
||||
### Шаг 3. Добавление клиентов в WARP
|
||||
### Шаг 3. Включение клиентов в WARP
|
||||
|
||||
После установки WARP нужно указать, **каких клиентов** пускать через Cloudflare.
|
||||
|
||||
**Через SSH-меню:**
|
||||
|
||||
1. Выберите пункт **6** — ➕ Добавить клиентов в WARP
|
||||
2. Вы увидите список всех клиентов AmneziaWG с их IP и именами
|
||||
3. Введите номер клиента, которого хотите добавить, или `all` для всех
|
||||
1. Выберите пункт **6** — переключение клиентов WARP (единое меню)
|
||||
2. Вы увидите список всех клиентов AmneziaWG с их IP и именами; напротив каждого — **✅** (уже в WARP) или **☐** (не в WARP)
|
||||
3. Введите номер клиента, чтобы переключить состояние (в WARP или вне WARP)
|
||||
4. Скрипт:
|
||||
- Добавит `ip rule` для маршрутизации трафика клиента через WARP
|
||||
- Настроит `iptables` NAT для корректного выхода через WG-интерфейс
|
||||
- Добавит или снимет `ip rule` для маршрутизации трафика клиента через WARP
|
||||
- Настроит или уберёт `iptables` NAT для корректного выхода через WG-интерфейс
|
||||
- Пропишет правила в `start.sh` контейнера (персистентность)
|
||||
|
||||
**Через Telegram-бот:**
|
||||
|
||||
1. Нажмите **Клиенты** → **➕ Добавить**
|
||||
2. Выберите клиента из списка (✅ = уже в WARP, ➕ = можно добавить)
|
||||
3. Или нажмите **✅ Все в WARP** для добавления всех
|
||||
1. Нажмите **👥 Клиенты WARP** — откроется тот же список-переключатель
|
||||
2. Напротив клиентов отображаются **✅** (в WARP) и **☐** (вне WARP); выбор пункта переключает состояние
|
||||
|
||||
### Шаг 4. Проверка
|
||||
|
||||
1. Подключитесь к VPN через приложение Amnezia
|
||||
2. Откройте [https://whoer.net](https://whoer.net) или [https://ifconfig.me](https://ifconfig.me)
|
||||
3. Если ваш клиент добавлен в WARP — вы увидите **IP Cloudflare**
|
||||
3. Если ваш клиент включён в WARP — вы увидите **IP Cloudflare**
|
||||
4. Если клиент не в WARP — вы увидите **обычный IP сервера**
|
||||
|
||||
Проверка через SSH (внутри контейнера):
|
||||
@@ -284,17 +283,17 @@ docker exec <имя_контейнера> curl -s --interface warp ifconfig.me
|
||||
|
||||
### Управление клиентами
|
||||
|
||||
В SSH и в боте используется **одно меню переключателей**: у каждого клиента видно **✅** (трафик через WARP) или **☐** (напрямую); действие по пункту меняет состояние.
|
||||
|
||||
| Действие | SSH-меню | Telegram-бот |
|
||||
|----------|----------|--------------|
|
||||
| Добавить в WARP | пункт **6** | Клиенты → ➕ Добавить |
|
||||
| Убрать из WARP | пункт **7** | Клиенты → ➖ Убрать |
|
||||
| Список клиентов в WARP | пункт **8** | Клиенты |
|
||||
| Включить/выключить клиента в WARP (список ✅/☐) | пункт **6** | **👥 Клиенты WARP** |
|
||||
| Перевыпуск ключа | пункт **5** | 🔑 Перевыпуск ключа |
|
||||
| Перезапуск контейнера | пункт **9** | 🔄 Контейнер |
|
||||
| Перезапуск контейнера | пункт **7** | 🔄 Контейнер |
|
||||
|
||||
### Что происходит при добавлении клиента
|
||||
### Что происходит при включении клиента в WARP
|
||||
|
||||
Когда вы добавляете клиента (например, `10.8.1.2`) в WARP, скрипт:
|
||||
Когда вы переводите клиента в WARP (например, `10.8.1.2`), скрипт:
|
||||
|
||||
1. Создаёт **ip rule**: `ip rule add from 10.8.1.2 table 51820`
|
||||
2. Добавляет **iptables NAT**: `iptables -t nat -A POSTROUTING -s 10.8.1.2 -o warp -j MASQUERADE`
|
||||
@@ -320,7 +319,7 @@ docker exec <имя_контейнера> curl -s --interface warp ifconfig.me
|
||||
|
||||
## Меню WARP Manager
|
||||
|
||||
Меню организовано по секциям. Нумерация пунктов 1–5 и 10–13 одинакова в обоих режимах, а секция 6–9 адаптируется.
|
||||
Меню организовано по секциям. Пункты **1–5** (WARP) и **8–11** (бот, промо, инструкция, удаление) одинаковы в обоих режимах; пункты **6–7** зависят от режима (3X-UI или AmneziaWG).
|
||||
|
||||
### Общая секция — WARP-ключ (оба режима)
|
||||
|
||||
@@ -336,26 +335,24 @@ docker exec <имя_контейнера> curl -s --interface warp ifconfig.me
|
||||
|
||||
| Пункт | Действие |
|
||||
|-------|----------|
|
||||
| 6 | JSON конфиг для 3X-UI |
|
||||
| 6 | Настройки SOCKS5 / JSON для 3X-UI |
|
||||
| 7 | Изменить порт SOCKS5 |
|
||||
|
||||
### Секция AmneziaWG (только в режиме AmneziaWG)
|
||||
|
||||
| Пункт | Действие |
|
||||
|-------|----------|
|
||||
| 6 | ➕ Добавить клиентов в WARP |
|
||||
| 7 | ➖ Убрать клиентов из WARP |
|
||||
| 8 | Показать клиентов в WARP |
|
||||
| 9 | Перезапуск контейнера |
|
||||
| 6 | Переключение клиентов WARP (единое меню, ✅ / ☐) |
|
||||
| 7 | Перезапуск контейнера |
|
||||
|
||||
### Общая секция — бот и прочее (оба режима)
|
||||
|
||||
| Пункт | Действие |
|
||||
|-------|----------|
|
||||
| 10 | Telegram Bot (настройка и управление) |
|
||||
| 11 | PROMO |
|
||||
| 12 | Инструкция |
|
||||
| 13 | Полное удаление |
|
||||
| 8 | Telegram Bot (настройка и управление) |
|
||||
| 9 | PROMO |
|
||||
| 10 | Инструкция |
|
||||
| 11 | Полное удаление |
|
||||
| 0 | Выход |
|
||||
|
||||
---
|
||||
@@ -370,7 +367,7 @@ WARP Manager включает встроенный Telegram-бот для уда
|
||||
2. Отправьте `/newbot`
|
||||
3. Задайте имя и username бота
|
||||
4. Скопируйте полученный **токен**
|
||||
5. На сервере выполните `gowarp` → пункт **10** (Telegram Bot)
|
||||
5. На сервере выполните `gowarp` → пункт **8** (Telegram Bot)
|
||||
6. Выберите **1) Токен бота** — вставьте токен
|
||||
7. Выберите **2) Chat ID (авто)**:
|
||||
- Откройте вашего бота в Telegram
|
||||
@@ -405,9 +402,7 @@ WARP Manager включает встроенный Telegram-бот для уда
|
||||
| ▶️ Запустить | Поднять WG-интерфейс WARP |
|
||||
| ⏹ Остановить | Опустить WG-интерфейс WARP |
|
||||
| 🔑 Перевыпуск ключа | Пересоздать WARP-профиль |
|
||||
| 👥 Клиенты | Список клиентов в WARP |
|
||||
| ➕ Добавить | Добавить клиента в WARP (выбор из списка) |
|
||||
| ➖ Убрать | Убрать клиента из WARP |
|
||||
| 👥 Клиенты WARP | Единое меню переключателей: список клиентов с **✅** (в WARP) и **☐** (вне WARP) |
|
||||
| 🔄 Контейнер | Перезапуск Docker-контейнера AmneziaWG |
|
||||
| 🖥 Система | CPU, RAM, диск, uptime |
|
||||
| 🏷 Хостинг | Промо-материалы |
|
||||
@@ -453,7 +448,7 @@ docker exec <контейнер> cat /opt/warp/warp.conf
|
||||
docker exec <контейнер> ip link show warp
|
||||
```
|
||||
|
||||
Попробуйте перевыпустить ключ (пункт 5) или перезапустить контейнер (пункт 9).
|
||||
Попробуйте перевыпустить ключ (пункт 5) или перезапустить контейнер (пункт 7).
|
||||
|
||||
### Сайт всё ещё заблокирован после настройки (3X-UI)
|
||||
|
||||
@@ -464,9 +459,9 @@ docker exec <контейнер> ip link show warp
|
||||
|
||||
### Клиент не видит WARP IP (AmneziaWG)
|
||||
|
||||
1. Убедитесь, что клиент **добавлен** в WARP (`gowarp` → пункт 8)
|
||||
1. Убедитесь, что клиент **включён** в WARP (`gowarp` → пункт 6, в списке должна быть **✅**)
|
||||
2. Проверьте, что интерфейс `warp` поднят (`gowarp` → пункт 4)
|
||||
3. Перезапустите контейнер (`gowarp` → пункт 9)
|
||||
3. Перезапустите контейнер (`gowarp` → пункт 7)
|
||||
4. Переподключитесь к VPN на клиентском устройстве
|
||||
|
||||
### Как сменить WARP IP
|
||||
@@ -492,7 +487,7 @@ docker exec <контейнер> ip link show warp
|
||||
gowarp
|
||||
```
|
||||
|
||||
Выберите пункт **13** — Полное удаление.
|
||||
Выберите пункт **11** — Полное удаление.
|
||||
|
||||
### Что удаляется (3X-UI)
|
||||
|
||||
|
||||
382
warp.sh
382
warp.sh
@@ -283,7 +283,7 @@ install_warp_3xui() {
|
||||
else
|
||||
echo -e "${YELLOW} ⚠ Подключение не подтверждено.${NC}"
|
||||
fi
|
||||
echo -e "\n${WHITE}Интеграция с 3X-UI: пункт меню ${YELLOW}5${NC}"
|
||||
echo -e "\n${WHITE}Настройки SOCKS5 и JSON: пункт меню ${YELLOW}6${NC}"
|
||||
read -p "Enter..."
|
||||
}
|
||||
|
||||
@@ -292,8 +292,11 @@ start_warp_3xui() {
|
||||
is_warp_running_3xui && { echo -e "\n${YELLOW}Уже подключён.${NC}"; read -p "Enter..."; return; }
|
||||
echo -e "\n${YELLOW}Подключение...${NC}"
|
||||
warp-cli --accept-tos connect > /dev/null 2>&1; sleep 3
|
||||
is_warp_running_3xui && echo -e "${GREEN}[OK] Подключён.${NC}" && log_action "3XUI START" \
|
||||
|| echo -e "${RED}Ошибка подключения.${NC}"
|
||||
if is_warp_running_3xui; then
|
||||
echo -e "${GREEN}[OK] Подключён.${NC}"; log_action "3XUI START"
|
||||
else
|
||||
echo -e "${RED}Ошибка подключения.${NC}"
|
||||
fi
|
||||
read -p "Enter..."
|
||||
}
|
||||
|
||||
@@ -613,7 +616,7 @@ install_warp_awg() {
|
||||
|
||||
awg_detect_warp_exit_ip
|
||||
[ -n "$AWG_WARP_EXIT_IP" ] && echo -e "\n ${WHITE}WARP IP: ${GREEN}${AWG_WARP_EXIT_IP}${NC}"
|
||||
echo -e "\n${GREEN}WARP установлен! Добавьте клиентов через п.6.${NC}"
|
||||
echo -e "\n${GREEN}WARP установлен! Управление клиентами — п.6.${NC}"
|
||||
log_action "AWG INSTALL: endpoint=${ep}, warp_ip=${AWG_WARP_EXIT_IP}"
|
||||
read -p "Enter..."
|
||||
}
|
||||
@@ -622,8 +625,11 @@ start_warp_awg() {
|
||||
is_warp_installed_awg || { echo -e "\n${RED}WARP не установлен (п.1).${NC}"; read -p "Enter..."; return; }
|
||||
is_warp_running_awg && { echo -e "\n${YELLOW}Уже работает.${NC}"; read -p "Enter..."; return; }
|
||||
echo -e "\n${YELLOW}Поднимаю warp...${NC}"
|
||||
awg_warp_up && echo -e "${GREEN}[OK] WARP подключён.${NC}" && log_action "AWG START" \
|
||||
|| echo -e "${RED}Ошибка.${NC}"
|
||||
if awg_warp_up; then
|
||||
echo -e "${GREEN}[OK] WARP подключён.${NC}"; log_action "AWG START"
|
||||
else
|
||||
echo -e "${RED}Ошибка.${NC}"
|
||||
fi
|
||||
read -p "Enter..."
|
||||
}
|
||||
|
||||
@@ -649,8 +655,8 @@ rekey_warp_awg() {
|
||||
awg_apply_rules
|
||||
awg_patch_start_sh
|
||||
awg_detect_warp_exit_ip
|
||||
echo -e "${GREEN} ✓ Готово!"
|
||||
[ -n "$AWG_WARP_EXIT_IP" ] && echo -e " Новый WARP IP: ${AWG_WARP_EXIT_IP}${NC}"
|
||||
echo -e "${GREEN} ✓ Готово!${NC}"
|
||||
[ -n "$AWG_WARP_EXIT_IP" ] && echo -e " ${WHITE}Новый WARP IP: ${GREEN}${AWG_WARP_EXIT_IP}${NC}"
|
||||
log_action "AWG REKEY: warp_ip=${AWG_WARP_EXIT_IP}"
|
||||
read -p "Enter..."
|
||||
}
|
||||
@@ -828,105 +834,72 @@ awg_get_client_ips() {
|
||||
fi
|
||||
}
|
||||
|
||||
awg_add_clients_ssh() {
|
||||
awg_get_client_ips; awg_parse_clients_table; awg_load_clients
|
||||
local warp_set=" ${AWG_SELECTED_IPS[*]+"${AWG_SELECTED_IPS[*]}"} "
|
||||
clear; echo -e "\n${CYAN}━━━ Добавить клиентов в WARP ━━━${NC}\n"
|
||||
if [ ${#AWG_CLIENT_IPS[@]} -eq 0 ]; then echo -e "${RED}Нет клиентов.${NC}"; read -p "Enter..."; return; fi
|
||||
local i=1
|
||||
for ip in "${AWG_CLIENT_IPS[@]}"; do
|
||||
local label; label=$(awg_format_label "$ip")
|
||||
if [[ "$warp_set" == *" $ip "* ]]; then
|
||||
echo -e " ${GREEN}$i) $label [WARP]${NC}"
|
||||
else
|
||||
echo " $i) $label"
|
||||
awg_toggle_clients_ssh() {
|
||||
while true; do
|
||||
awg_get_client_ips; awg_parse_clients_table; awg_load_clients
|
||||
local warp_set=" ${AWG_SELECTED_IPS[*]+"${AWG_SELECTED_IPS[*]}"} "
|
||||
|
||||
clear; echo -e "\n${CYAN}━━━ Клиенты WARP ━━━${NC}\n"
|
||||
|
||||
if [ ${#AWG_CLIENT_IPS[@]} -eq 0 ]; then
|
||||
echo -e " ${RED}Нет клиентов в конфиге VPN.${NC}"
|
||||
read -p "Enter..."; return
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
echo " all) все клиенты"
|
||||
echo -e " ${DIM}0) Отмена${NC}\n"
|
||||
read -p "Номер (через запятую) или all: " answer
|
||||
[ -z "$answer" ] || [ "$answer" = "0" ] && return
|
||||
|
||||
local -a new_ips=()
|
||||
if [ "$answer" = "all" ]; then
|
||||
new_ips=("${AWG_CLIENT_IPS[@]}")
|
||||
else
|
||||
IFS=',' read -ra parts <<< "$answer"
|
||||
for p in "${parts[@]}"; do
|
||||
p=$(echo "$p" | xargs)
|
||||
[[ "$p" =~ ^[0-9]+$ ]] && (( p >= 1 && p <= ${#AWG_CLIENT_IPS[@]} )) && new_ips+=("${AWG_CLIENT_IPS[$((p-1))]}")
|
||||
local i=1 warp_count=0
|
||||
for ip in "${AWG_CLIENT_IPS[@]}"; do
|
||||
local label; label=$(awg_format_label "$ip")
|
||||
if [[ "$warp_set" == *" $ip "* ]]; then
|
||||
echo -e " ${GREEN}$i) ✅ $label${NC}"
|
||||
((warp_count++))
|
||||
else
|
||||
echo -e " $i) ☐ $label"
|
||||
fi
|
||||
((i++))
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
for nip in "${new_ips[@]}"; do
|
||||
local found=0
|
||||
for eip in "${AWG_SELECTED_IPS[@]}"; do [ "$nip" = "$eip" ] && found=1 && break; done
|
||||
if [ "$found" -eq 0 ]; then
|
||||
AWG_SELECTED_IPS+=("$nip")
|
||||
echo -e " ${GREEN}+${NC} $(awg_format_label "$nip")"
|
||||
echo ""
|
||||
echo -e " ${WHITE}В WARP: ${CYAN}${warp_count}${NC} из ${#AWG_CLIENT_IPS[@]}"
|
||||
echo ""
|
||||
echo -e " ${DIM}Введите номер для переключения (через запятую)${NC}"
|
||||
echo -e " ${DIM}all) все в WARP | none) убрать всех | 0) назад${NC}"
|
||||
echo ""
|
||||
read -p " Выбор: " answer
|
||||
|
||||
[ -z "$answer" ] || [ "$answer" = "0" ] && return
|
||||
|
||||
local changed=0
|
||||
if [ "$answer" = "all" ]; then
|
||||
AWG_SELECTED_IPS=("${AWG_CLIENT_IPS[@]}")
|
||||
changed=1
|
||||
elif [ "$answer" = "none" ]; then
|
||||
AWG_SELECTED_IPS=()
|
||||
changed=1
|
||||
else
|
||||
echo -e " ${DIM}Уже в WARP: $(awg_format_label "$nip")${NC}"
|
||||
IFS=',' read -ra parts <<< "$answer"
|
||||
for p in "${parts[@]}"; do
|
||||
p=$(echo "$p" | xargs)
|
||||
if [[ "$p" =~ ^[0-9]+$ ]] && (( p >= 1 && p <= ${#AWG_CLIENT_IPS[@]} )); then
|
||||
local ip="${AWG_CLIENT_IPS[$((p-1))]}"
|
||||
if [[ "$warp_set" == *" $ip "* ]]; then
|
||||
local -a tmp=()
|
||||
for eip in "${AWG_SELECTED_IPS[@]}"; do
|
||||
[ "$eip" != "$ip" ] && tmp+=("$eip")
|
||||
done
|
||||
AWG_SELECTED_IPS=("${tmp[@]+"${tmp[@]}"}")
|
||||
else
|
||||
AWG_SELECTED_IPS+=("$ip")
|
||||
fi
|
||||
changed=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$changed" -eq 1 ]; then
|
||||
awg_save_clients; awg_apply_rules; awg_patch_start_sh
|
||||
log_action "AWG TOGGLE: ${#AWG_SELECTED_IPS[@]} clients in WARP"
|
||||
fi
|
||||
done
|
||||
|
||||
awg_save_clients; awg_apply_rules; awg_patch_start_sh
|
||||
echo -e "\n${GREEN}Готово. Правила применены.${NC}"
|
||||
log_action "AWG ADD CLIENTS: ${#AWG_SELECTED_IPS[@]} total"
|
||||
read -p "Enter..."
|
||||
}
|
||||
|
||||
awg_remove_clients_ssh() {
|
||||
awg_load_clients
|
||||
if [ ${#AWG_SELECTED_IPS[@]} -eq 0 ]; then echo -e "\n${YELLOW}Нет клиентов в WARP.${NC}"; read -p "Enter..."; return; fi
|
||||
awg_parse_clients_table
|
||||
clear; echo -e "\n${CYAN}━━━ Убрать клиентов из WARP ━━━${NC}\n"
|
||||
local i=1
|
||||
for ip in "${AWG_SELECTED_IPS[@]}"; do echo " $i) $(awg_format_label "$ip")"; ((i++)); done
|
||||
echo " all) убрать всех"
|
||||
echo -e " ${DIM}0) Отмена${NC}\n"
|
||||
read -p "Номер (через запятую) или all: " answer
|
||||
[ -z "$answer" ] || [ "$answer" = "0" ] && return
|
||||
|
||||
local -a remove_ips=()
|
||||
if [ "$answer" = "all" ]; then
|
||||
remove_ips=("${AWG_SELECTED_IPS[@]}")
|
||||
else
|
||||
IFS=',' read -ra parts <<< "$answer"
|
||||
for p in "${parts[@]}"; do
|
||||
p=$(echo "$p" | xargs)
|
||||
[[ "$p" =~ ^[0-9]+$ ]] && (( p >= 1 && p <= ${#AWG_SELECTED_IPS[@]} )) && remove_ips+=("${AWG_SELECTED_IPS[$((p-1))]}")
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
local -a new_list=()
|
||||
for eip in "${AWG_SELECTED_IPS[@]}"; do
|
||||
local removing=0
|
||||
for rip in "${remove_ips[@]}"; do [ "$eip" = "$rip" ] && removing=1 && break; done
|
||||
if [ "$removing" -eq 0 ]; then new_list+=("$eip")
|
||||
else echo -e " ${RED}-${NC} $(awg_format_label "$eip")"; fi
|
||||
done
|
||||
AWG_SELECTED_IPS=("${new_list[@]+"${new_list[@]}"}")
|
||||
awg_save_clients; awg_apply_rules; awg_patch_start_sh
|
||||
echo -e "\n${GREEN}Готово.${NC}"
|
||||
log_action "AWG REMOVE CLIENTS: ${#AWG_SELECTED_IPS[@]} remaining"
|
||||
read -p "Enter..."
|
||||
}
|
||||
|
||||
awg_show_clients_ssh() {
|
||||
awg_load_clients; awg_parse_clients_table
|
||||
clear; echo -e "\n${CYAN}━━━ Клиенты в WARP ━━━${NC}\n"
|
||||
if [ ${#AWG_SELECTED_IPS[@]} -eq 0 ]; then
|
||||
echo -e " ${YELLOW}Нет клиентов в WARP.${NC}"
|
||||
else
|
||||
echo -e " ${WHITE}Всего: ${CYAN}${#AWG_SELECTED_IPS[@]}${NC}\n"
|
||||
for ip in "${AWG_SELECTED_IPS[@]}"; do
|
||||
echo -e " ${GREEN}●${NC} $(awg_format_label "$ip")"
|
||||
done
|
||||
fi
|
||||
echo ""; read -p "Enter..."
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
@@ -1030,7 +1003,7 @@ awg_remove_from_start_sh() {
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
get_warp_status() {
|
||||
[ "$MODE" = "3xui" ] && get_warp_status_3xui || get_warp_status_awg
|
||||
if [ "$MODE" = "3xui" ]; then get_warp_status_3xui; else get_warp_status_awg; fi
|
||||
}
|
||||
|
||||
get_warp_ip() {
|
||||
@@ -1042,7 +1015,7 @@ get_warp_ip() {
|
||||
}
|
||||
|
||||
is_warp_running() {
|
||||
[ "$MODE" = "3xui" ] && is_warp_running_3xui || is_warp_running_awg
|
||||
if [ "$MODE" = "3xui" ]; then is_warp_running_3xui; else is_warp_running_awg; fi
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
@@ -1107,15 +1080,15 @@ kbd_main_awg() {
|
||||
[{"text":"📊 Статус","callback_data":"st"},{"text":"🌐 IP","callback_data":"ip"}],
|
||||
[{"text":"▶️ Запустить","callback_data":"on"},{"text":"⏹ Остановить","callback_data":"off"}],
|
||||
[{"text":"🔑 Перевыпуск","callback_data":"rk"}],
|
||||
[{"text":"👥 Клиенты WARP","callback_data":"cl"},{"text":"➕ Добавить","callback_data":"cla"}],
|
||||
[{"text":"➖ Убрать","callback_data":"clr"},{"text":"🔄 Контейнер","callback_data":"rc"}],
|
||||
[{"text":"👥 Клиенты WARP","callback_data":"cl"}],
|
||||
[{"text":"🔄 Контейнер","callback_data":"rc"}],
|
||||
[{"text":"💻 Система","callback_data":"sys"}],
|
||||
[{"text":"🏢 Хостинг","callback_data":"promo"}]
|
||||
]
|
||||
JSON
|
||||
}
|
||||
|
||||
kbd_main() { [ "$MODE" = "3xui" ] && kbd_main_3xui || kbd_main_awg; }
|
||||
kbd_main() { if [ "$MODE" = "3xui" ]; then kbd_main_3xui; else kbd_main_awg; fi; }
|
||||
|
||||
kbd_back() { echo '[[{"text":"⬅️ Меню","callback_data":"m"}]]'; }
|
||||
kbd_rekey_confirm() { echo '[[{"text":"✅ Да","callback_data":"rk_y"}],[{"text":"⬅️ Отмена","callback_data":"m"}]]'; }
|
||||
@@ -1132,7 +1105,11 @@ bot_main_menu() {
|
||||
local mode_label="3X-UI"; [ "$MODE" = "amnezia" ] && mode_label="AmneziaWG"
|
||||
local text="<b>WARP Manager v${WARP_VERSION}</b> (${mode_label})\nСервер: <code>${MY_IP:-N/A}</code>\nСтатус: <b>${ws}</b>${wip}${extra}\n\nВыберите:"
|
||||
local kbd; kbd=$(kbd_main)
|
||||
[ -n "$msg_id" ] && tg_edit "$chat_id" "$msg_id" "$text" "$kbd" || tg_send "$chat_id" "$text" "$kbd"
|
||||
if [ -n "$msg_id" ]; then
|
||||
tg_edit "$chat_id" "$msg_id" "$text" "$kbd"
|
||||
else
|
||||
tg_send "$chat_id" "$text" "$kbd"
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── Bot handlers ────────────────────────────────────────────
|
||||
@@ -1171,8 +1148,12 @@ bot_handle_callback() {
|
||||
is_warp_running_3xui && { tg_edit "$chat_id" "$msg_id" "✅ Уже подключён." "$(kbd_back)"; return; }
|
||||
tg_edit "$chat_id" "$msg_id" "⏳ Подключение..." ""
|
||||
warp-cli --accept-tos connect > /dev/null 2>&1; sleep 3
|
||||
is_warp_running_3xui && { local w; w=$(get_warp_ip_3xui); tg_edit "$chat_id" "$msg_id" "✅ <b>Подключён</b>\nWARP IP: <code>${w}</code>" "$(kbd_back)"; log_action "BOT 3XUI ON"; } \
|
||||
|| tg_edit "$chat_id" "$msg_id" "❌ Ошибка." "$(kbd_back)"
|
||||
if is_warp_running_3xui; then
|
||||
local w; w=$(get_warp_ip_3xui)
|
||||
tg_edit "$chat_id" "$msg_id" "✅ <b>Подключён</b>\nWARP IP: <code>${w}</code>" "$(kbd_back)"; log_action "BOT 3XUI ON"
|
||||
else
|
||||
tg_edit "$chat_id" "$msg_id" "❌ Ошибка." "$(kbd_back)"
|
||||
fi
|
||||
else
|
||||
is_warp_installed_awg || { tg_edit "$chat_id" "$msg_id" "❌ Не установлен." "$(kbd_back)"; return; }
|
||||
is_warp_running_awg && { tg_edit "$chat_id" "$msg_id" "✅ Уже работает." "$(kbd_back)"; return; }
|
||||
@@ -1237,93 +1218,64 @@ bot_handle_callback() {
|
||||
fi ;;
|
||||
|
||||
cl)
|
||||
awg_load_clients; awg_parse_clients_table
|
||||
local t="👥 <b>Клиенты в WARP</b> (${#AWG_SELECTED_IPS[@]})\n\n"
|
||||
if [ ${#AWG_SELECTED_IPS[@]} -eq 0 ]; then
|
||||
t+="<i>Нет клиентов.</i>"
|
||||
else
|
||||
for ip in "${AWG_SELECTED_IPS[@]}"; do
|
||||
local name; name=$(awg_get_name "$ip")
|
||||
t+="● <code>${ip}</code>"
|
||||
[ -n "$name" ] && t+=" ($name)"
|
||||
t+="\n"
|
||||
done
|
||||
fi
|
||||
tg_edit "$chat_id" "$msg_id" "$t" "$(kbd_back)" ;;
|
||||
|
||||
cla)
|
||||
awg_get_client_ips; awg_parse_clients_table; awg_load_clients
|
||||
local warp_set=" ${AWG_SELECTED_IPS[*]+"${AWG_SELECTED_IPS[*]}"} "
|
||||
local kbd="["
|
||||
local first=1
|
||||
for i in "${!AWG_CLIENT_IPS[@]}"; do
|
||||
local ip="${AWG_CLIENT_IPS[$i]}"
|
||||
local name; name=$(awg_get_name "$ip")
|
||||
local label="${ip}"
|
||||
[ -n "$name" ] && label="$name"
|
||||
local in_warp=0
|
||||
[[ "$warp_set" == *" $ip "* ]] && in_warp=1
|
||||
[ "$in_warp" -eq 1 ] && label="✅ $label" || label="➕ $label"
|
||||
[ "$first" -eq 0 ] && kbd+=","
|
||||
kbd+="[{\"text\":\"${label}\",\"callback_data\":\"ca:${i}\"}]"
|
||||
first=0
|
||||
done
|
||||
kbd+=",[{\"text\":\"✅ Все в WARP\",\"callback_data\":\"ca:all\"}]"
|
||||
kbd+=",[{\"text\":\"⬅️ Меню\",\"callback_data\":\"m\"}]]"
|
||||
tg_edit "$chat_id" "$msg_id" "➕ <b>Добавить в WARP:</b>" "$kbd" ;;
|
||||
local t="👥 <b>Клиенты WARP</b> (${#AWG_SELECTED_IPS[@]} из ${#AWG_CLIENT_IPS[@]})\n\n"
|
||||
local kbd=""
|
||||
if [ ${#AWG_CLIENT_IPS[@]} -eq 0 ]; then
|
||||
t+="<i>Нет клиентов в конфиге VPN.</i>"
|
||||
kbd='[[{"text":"⬅️ Меню","callback_data":"m"}]]'
|
||||
else
|
||||
kbd="["
|
||||
local first=1
|
||||
for i in "${!AWG_CLIENT_IPS[@]}"; do
|
||||
local ip="${AWG_CLIENT_IPS[$i]}"
|
||||
local name; name=$(awg_get_name "$ip")
|
||||
local label="${ip}"
|
||||
[ -n "$name" ] && label="$name"
|
||||
if [[ "$warp_set" == *" $ip "* ]]; then
|
||||
t+="✅ <code>${ip}</code>"
|
||||
[ -n "$name" ] && t+=" ($name)"
|
||||
label="✅ ${label}"
|
||||
else
|
||||
t+="☐ <code>${ip}</code>"
|
||||
[ -n "$name" ] && t+=" ($name)"
|
||||
label="☐ ${label}"
|
||||
fi
|
||||
t+="\n"
|
||||
[ "$first" -eq 0 ] && kbd+=","
|
||||
kbd+="[{\"text\":\"${label}\",\"callback_data\":\"ct:${i}\"}]"
|
||||
first=0
|
||||
done
|
||||
kbd+=",[{\"text\":\"✅ Все\",\"callback_data\":\"ct:all\"},{\"text\":\"☐ Никого\",\"callback_data\":\"ct:none\"}]"
|
||||
kbd+=",[{\"text\":\"⬅️ Меню\",\"callback_data\":\"m\"}]]"
|
||||
fi
|
||||
tg_edit "$chat_id" "$msg_id" "$t" "$kbd" ;;
|
||||
|
||||
ca:*)
|
||||
local idx="${data#ca:}"
|
||||
ct:*)
|
||||
local idx="${data#ct:}"
|
||||
awg_get_client_ips; awg_load_clients
|
||||
if [ "$idx" = "all" ]; then
|
||||
AWG_SELECTED_IPS=("${AWG_CLIENT_IPS[@]}")
|
||||
elif [ "$idx" = "none" ]; then
|
||||
AWG_SELECTED_IPS=()
|
||||
else
|
||||
[[ "$idx" =~ ^[0-9]+$ ]] && (( idx < ${#AWG_CLIENT_IPS[@]} )) || { tg_edit "$chat_id" "$msg_id" "❌ Ошибка." "$(kbd_back)"; return; }
|
||||
local ip="${AWG_CLIENT_IPS[$idx]}"
|
||||
local found=0
|
||||
for e in "${AWG_SELECTED_IPS[@]}"; do [ "$e" = "$ip" ] && found=1 && break; done
|
||||
[ "$found" -eq 0 ] && AWG_SELECTED_IPS+=("$ip")
|
||||
local warp_set=" ${AWG_SELECTED_IPS[*]+"${AWG_SELECTED_IPS[*]}"} "
|
||||
if [[ "$warp_set" == *" $ip "* ]]; then
|
||||
local -a tmp=()
|
||||
for eip in "${AWG_SELECTED_IPS[@]}"; do
|
||||
[ "$eip" != "$ip" ] && tmp+=("$eip")
|
||||
done
|
||||
AWG_SELECTED_IPS=("${tmp[@]+"${tmp[@]}"}")
|
||||
else
|
||||
AWG_SELECTED_IPS+=("$ip")
|
||||
fi
|
||||
fi
|
||||
awg_save_clients; awg_apply_rules; awg_patch_start_sh
|
||||
tg_edit "$chat_id" "$msg_id" "✅ Обновлено. Клиентов: ${#AWG_SELECTED_IPS[@]}" "$(kbd_back)"
|
||||
log_action "BOT AWG ADD: ${#AWG_SELECTED_IPS[@]}" ;;
|
||||
|
||||
clr)
|
||||
awg_load_clients; awg_parse_clients_table
|
||||
if [ ${#AWG_SELECTED_IPS[@]} -eq 0 ]; then
|
||||
tg_edit "$chat_id" "$msg_id" "ℹ️ Нет клиентов в WARP." "$(kbd_back)"; return
|
||||
fi
|
||||
local kbd="["
|
||||
local first=1
|
||||
for i in "${!AWG_SELECTED_IPS[@]}"; do
|
||||
local ip="${AWG_SELECTED_IPS[$i]}"
|
||||
local name; name=$(awg_get_name "$ip")
|
||||
local label="${ip}"
|
||||
[ -n "$name" ] && label="$name"
|
||||
[ "$first" -eq 0 ] && kbd+=","
|
||||
kbd+="[{\"text\":\"❌ ${label}\",\"callback_data\":\"cr:${i}\"}]"
|
||||
first=0
|
||||
done
|
||||
kbd+=",[{\"text\":\"❌ Убрать всех\",\"callback_data\":\"cr:all\"}]"
|
||||
kbd+=",[{\"text\":\"⬅️ Меню\",\"callback_data\":\"m\"}]]"
|
||||
tg_edit "$chat_id" "$msg_id" "➖ <b>Убрать из WARP:</b>" "$kbd" ;;
|
||||
|
||||
cr:*)
|
||||
local idx="${data#cr:}"
|
||||
awg_load_clients
|
||||
if [ "$idx" = "all" ]; then
|
||||
AWG_SELECTED_IPS=()
|
||||
else
|
||||
[[ "$idx" =~ ^[0-9]+$ ]] && (( idx < ${#AWG_SELECTED_IPS[@]} )) || { tg_edit "$chat_id" "$msg_id" "❌ Ошибка." "$(kbd_back)"; return; }
|
||||
local -a new=()
|
||||
for i in "${!AWG_SELECTED_IPS[@]}"; do
|
||||
[ "$i" -ne "$idx" ] && new+=("${AWG_SELECTED_IPS[$i]}")
|
||||
done
|
||||
AWG_SELECTED_IPS=("${new[@]+"${new[@]}"}")
|
||||
fi
|
||||
awg_save_clients; awg_apply_rules; awg_patch_start_sh
|
||||
tg_edit "$chat_id" "$msg_id" "✅ Обновлено. Клиентов: ${#AWG_SELECTED_IPS[@]}" "$(kbd_back)"
|
||||
log_action "BOT AWG REMOVE: ${#AWG_SELECTED_IPS[@]}" ;;
|
||||
log_action "BOT AWG TOGGLE: ${#AWG_SELECTED_IPS[@]}"
|
||||
bot_handle_callback "$chat_id" "$msg_id" "" "cl" ;;
|
||||
|
||||
rc)
|
||||
if [ "$MODE" != "amnezia" ]; then
|
||||
@@ -1387,7 +1339,11 @@ bot_daemon() {
|
||||
mtx=$(echo "$upd" | jq -r '.message.text // empty')
|
||||
if [ -n "$mci" ] && [ -n "$mtx" ]; then
|
||||
[ -n "$BOT_CHAT_ID" ] && [ "$mci" != "$BOT_CHAT_ID" ] && { tg_send "$mci" "⛔ Нет доступа.\nChat ID: <code>$mci</code>" "" > /dev/null; continue; }
|
||||
[[ "$mtx" == "/start" || "$mtx" == "/menu" ]] && bot_main_menu "$mci" || tg_send "$mci" "Используйте /start или /menu" "" > /dev/null
|
||||
if [[ "$mtx" == "/start" || "$mtx" == "/menu" ]]; then
|
||||
bot_main_menu "$mci"
|
||||
else
|
||||
tg_send "$mci" "Используйте /start или /menu" "" > /dev/null
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -1413,8 +1369,11 @@ RestartSec=5
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload; systemctl enable warp-bot > /dev/null 2>&1; systemctl start warp-bot; sleep 1
|
||||
systemctl is-active warp-bot &>/dev/null && echo -e "${GREEN}[OK] Бот запущен.${NC}" && log_action "Bot started" \
|
||||
|| echo -e "${RED}[ERROR] journalctl -u warp-bot${NC}"
|
||||
if systemctl is-active warp-bot &>/dev/null; then
|
||||
echo -e "${GREEN}[OK] Бот запущен.${NC}"; log_action "Bot started"
|
||||
else
|
||||
echo -e "${RED}[ERROR] journalctl -u warp-bot${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
stop_bot() {
|
||||
@@ -1446,8 +1405,11 @@ bot_menu() {
|
||||
2) [ -z "${BOT_TOKEN:-}" ] && echo -e "${RED}Сначала токен!${NC}" && read -p "" && continue
|
||||
echo -e "${YELLOW}Отправьте боту сообщение, нажмите Enter.${NC}"; read -p ""
|
||||
local c; c=$(curl -s "https://api.telegram.org/bot${BOT_TOKEN}/getUpdates?limit=1&offset=-1" | jq -r '.result[0].message.chat.id // empty')
|
||||
[ -n "$c" ] && save_config_val "BOT_CHAT_ID" "$c" && BOT_CHAT_ID="$c" && echo -e "${GREEN}Chat ID: $c${NC}" \
|
||||
|| echo -e "${RED}Не удалось.${NC}"
|
||||
if [ -n "$c" ]; then
|
||||
save_config_val "BOT_CHAT_ID" "$c"; BOT_CHAT_ID="$c"; echo -e "${GREEN}Chat ID: $c${NC}"
|
||||
else
|
||||
echo -e "${RED}Не удалось.${NC}"
|
||||
fi
|
||||
read -p "Enter..." ;;
|
||||
3) echo "Chat ID:"; read -p "> " c
|
||||
[ -n "$c" ] && save_config_val "BOT_CHAT_ID" "$c" && BOT_CHAT_ID="$c" && echo -e "${GREEN}OK${NC}"
|
||||
@@ -1518,7 +1480,7 @@ full_uninstall() {
|
||||
read -p "$(echo -e "${RED}Удалить полностью? (y/n): ${NC}")" c1
|
||||
[[ "$c1" != "y" ]] && return
|
||||
|
||||
[ "$MODE" = "3xui" ] && uninstall_3xui || uninstall_awg
|
||||
if [ "$MODE" = "3xui" ]; then uninstall_3xui; else uninstall_awg; fi
|
||||
|
||||
rm -rf "$WARP_DIR" "$WARP_LOG"
|
||||
echo -e " ${GREEN}✓${NC} Конфигурация и логи"
|
||||
@@ -1568,43 +1530,39 @@ show_menu() {
|
||||
|
||||
if [ "$MODE" = "3xui" ]; then
|
||||
echo -e "\n${CYAN}── 3X-UI ──────────────────────────────────────────────${NC}"
|
||||
echo -e " 6) 📋 ${CYAN}JSON конфиг для 3X-UI${NC}"
|
||||
echo -e " 6) 📋 ${CYAN}Настройки SOCKS5 / JSON для 3X-UI${NC}"
|
||||
echo -e " 7) 🔧 ${WHITE}Изменить порт SOCKS5${NC}"
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "amnezia" ]; then
|
||||
echo -e "\n${CYAN}── AmneziaWG ──────────────────────────────────────────${NC}"
|
||||
echo -e " 6) ${GREEN}➕ Добавить клиентов в WARP${NC}"
|
||||
echo -e " 7) ${YELLOW}➖ Убрать клиентов из WARP${NC}"
|
||||
echo -e " 8) 👥 ${WHITE}Показать клиентов в WARP${NC}"
|
||||
echo -e " 9) 🔄 ${CYAN}Перезапуск контейнера${NC}"
|
||||
echo -e " 6) 👥 ${GREEN}Управление клиентами WARP${NC}"
|
||||
echo -e " 7) 🔄 ${CYAN}Перезапуск контейнера${NC}"
|
||||
fi
|
||||
|
||||
echo -e "\n${CYAN}── Telegram-бот ───────────────────────────────────────${NC}"
|
||||
echo -e " 10) 🤖 ${CYAN}Настройка и управление ботом${NC}"
|
||||
echo -e " 8) 🤖 ${CYAN}Настройка и управление ботом${NC}"
|
||||
|
||||
echo -e "\n${CYAN}── Прочее ─────────────────────────────────────────────${NC}"
|
||||
echo -e " 11) ${YELLOW}PROMO${NC}"
|
||||
echo -e " 12) ${MAGENTA}📚 Инструкция${NC}"
|
||||
echo -e " 13) ${RED}⚠ Полное удаление${NC}"
|
||||
echo -e " 9) ${YELLOW}PROMO${NC}"
|
||||
echo -e " 10) ${MAGENTA}📚 Инструкция${NC}"
|
||||
echo -e " 11) ${RED}⚠ Полное удаление${NC}"
|
||||
echo -e " 0) Выход"
|
||||
echo -e "${CYAN}──────────────────────────────────────────────────────${NC}"
|
||||
read -p " Выбор: " ch
|
||||
|
||||
case $ch in
|
||||
1) [ "$MODE" = "3xui" ] && install_warp_3xui || install_warp_awg ;;
|
||||
2) [ "$MODE" = "3xui" ] && start_warp_3xui || start_warp_awg ;;
|
||||
3) [ "$MODE" = "3xui" ] && stop_warp_3xui || stop_warp_awg ;;
|
||||
4) [ "$MODE" = "3xui" ] && show_status_3xui || show_status_awg ;;
|
||||
5) [ "$MODE" = "3xui" ] && rekey_warp_3xui || rekey_warp_awg ;;
|
||||
6) [ "$MODE" = "3xui" ] && show_xui_json || awg_add_clients_ssh ;;
|
||||
7) [ "$MODE" = "3xui" ] && change_port_3xui || awg_remove_clients_ssh ;;
|
||||
8) [ "$MODE" = "amnezia" ] && awg_show_clients_ssh ;;
|
||||
9) [ "$MODE" = "amnezia" ] && awg_restart_container ;;
|
||||
10) bot_menu ;;
|
||||
11) show_promo ;;
|
||||
12) show_info ;;
|
||||
13) full_uninstall ;;
|
||||
1) if [ "$MODE" = "3xui" ]; then install_warp_3xui; else install_warp_awg; fi ;;
|
||||
2) if [ "$MODE" = "3xui" ]; then start_warp_3xui; else start_warp_awg; fi ;;
|
||||
3) if [ "$MODE" = "3xui" ]; then stop_warp_3xui; else stop_warp_awg; fi ;;
|
||||
4) if [ "$MODE" = "3xui" ]; then show_status_3xui; else show_status_awg; fi ;;
|
||||
5) if [ "$MODE" = "3xui" ]; then rekey_warp_3xui; else rekey_warp_awg; fi ;;
|
||||
6) if [ "$MODE" = "3xui" ]; then show_xui_json; else awg_toggle_clients_ssh; fi ;;
|
||||
7) if [ "$MODE" = "3xui" ]; then change_port_3xui; else awg_restart_container; fi ;;
|
||||
8) bot_menu ;;
|
||||
9) show_promo ;;
|
||||
10) show_info ;;
|
||||
11) full_uninstall ;;
|
||||
0) exit 0 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user