mirror of
https://github.com/andrey271192/domen_hydra.git
synced 2026-09-21 14:51:59 +00:00
feat: кнопка «Снести с роутера» — удаляет VPN/туннель через SSH
POST /api/routers/{name}/wireguard/uninstall:
- killall autossh
- rm init.d S50hydravpn, S99hydra_tun
- rm hydra_tun, hydra_tk, wg0.conf, wg0.key
- ip link delete nwg50-70
Confirm-диалог с описанием что будет удалено.
This commit is contained in:
@@ -834,3 +834,40 @@ async def wg_remove_peer(name: str, x_admin_password: str = Header("")):
|
|||||||
_save_wg(data)
|
_save_wg(data)
|
||||||
await asyncio.to_thread(_wg_reload, _wg_server_conf(data))
|
await asyncio.to_thread(_wg_reload, _wg_server_conf(data))
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/api/routers/{name}/wireguard/uninstall")
|
||||||
|
async def wg_uninstall(name: str, x_admin_password: str = Header("")):
|
||||||
|
"""Удалить всё установленное сервером с роутера через SSH."""
|
||||||
|
_chk(x_admin_password)
|
||||||
|
rcfg = _get_router_cfg(name)
|
||||||
|
script = """\
|
||||||
|
echo '=== Удаление HydraVPN с роутера ==='
|
||||||
|
|
||||||
|
killall autossh 2>/dev/null && echo 'autossh остановлен' || true
|
||||||
|
|
||||||
|
if [ -f /opt/etc/init.d/S50hydravpn ]; then
|
||||||
|
/opt/etc/init.d/S50hydravpn stop 2>/dev/null || true
|
||||||
|
rm -f /opt/etc/init.d/S50hydravpn && echo 'S50hydravpn удалён'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /opt/etc/init.d/S99hydra_tun ]; then
|
||||||
|
/opt/etc/init.d/S99hydra_tun stop 2>/dev/null || true
|
||||||
|
rm -f /opt/etc/init.d/S99hydra_tun && echo 'S99hydra_tun удалён'
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f /opt/bin/hydra_tun && echo 'hydra_tun удалён' || true
|
||||||
|
rm -f /opt/etc/hydra_tk && echo 'SSH-ключ туннеля удалён' || true
|
||||||
|
rm -f /opt/etc/wireguard/wg0.conf /opt/etc/wireguard/wg0.key 2>/dev/null && echo 'WireGuard конфиг удалён' || true
|
||||||
|
rm -f /tmp/hydra_tun.log /tmp/rci.jar /tmp/wg_rci.json 2>/dev/null || true
|
||||||
|
|
||||||
|
for i in $(seq 50 70); do
|
||||||
|
ip link show nwg$i >/dev/null 2>&1 && ip link delete nwg$i && echo "nwg$i удалён"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo '=== OK: всё удалено ==='
|
||||||
|
echo 'Нативные WireGuard-интерфейсы (peer-1, HydraVPN...) удали вручную:'
|
||||||
|
echo ' Интернет → Другие подключения → WireGuard → Удалить подключение'
|
||||||
|
"""
|
||||||
|
rc, out, err = await _ssh_on_router(rcfg, script, timeout=60)
|
||||||
|
return {"ok": rc == 0, "output": (out + err)[:1500]}
|
||||||
|
|||||||
@@ -601,7 +601,8 @@ async function renderWgRouters(){
|
|||||||
? `<button class="btn btn-b" style="font-size:11px" onclick="wgAddPeer('${name}')">+ В VPN</button>`
|
? `<button class="btn btn-b" style="font-size:11px" onclick="wgAddPeer('${name}')">+ В VPN</button>`
|
||||||
: `<button class="btn btn-g" style="font-size:11px" onclick="wgDeploy('${name}')">📡 Установить на роутер</button>
|
: `<button class="btn btn-g" style="font-size:11px" onclick="wgDeploy('${name}')">📡 Установить на роутер</button>
|
||||||
<button class="btn btn-ghost" style="font-size:11px" onclick="wgShowRouterConfig('${name}')">📄 Конфиг</button>
|
<button class="btn btn-ghost" style="font-size:11px" onclick="wgShowRouterConfig('${name}')">📄 Конфиг</button>
|
||||||
<button class="btn btn-r" style="font-size:11px" onclick="wgRemovePeer('${name}')">✕ Убрать</button>`}
|
<button class="btn btn-r" style="font-size:11px" onclick="wgUninstall('${name}')" title="Удалить всё установленное с роутера через SSH">🗑 Снести с роутера</button>
|
||||||
|
<button class="btn btn-r" style="font-size:11px;opacity:.7" onclick="wgRemovePeer('${name}')">✕ Убрать из VPN</button>`}
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
@@ -628,13 +629,28 @@ async function wgAddPeer(name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function wgRemovePeer(name){
|
async function wgRemovePeer(name){
|
||||||
if(!confirm(`Удалить ${name} из WireGuard VPN?`)) return;
|
if(!confirm(`Убрать ${name} из VPN (только из списка, файлы на роутере не трогаем)?`)) return;
|
||||||
try {
|
try {
|
||||||
await fetch(`/api/routers/${encodeURIComponent(name)}/wireguard`, {method:'DELETE', headers: authHdr()});
|
await fetch(`/api/routers/${encodeURIComponent(name)}/wireguard`, {method:'DELETE', headers: authHdr()});
|
||||||
await loadWg();
|
await loadWg();
|
||||||
} catch(e){ alert('Ошибка: '+e); }
|
} catch(e){ alert('Ошибка: '+e); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function wgUninstall(name){
|
||||||
|
if(!confirm(`Удалить всё установленное сервером с роутера «${name}» через SSH?\n\n• autossh туннель\n• WireGuard файлы и init.d скрипты\n• nwg50+ интерфейсы\n\nНативные WireGuard-интерфейсы (peer-1, HydraVPN) надо удалить вручную в Keenetic UI.`)) return;
|
||||||
|
const log = document.getElementById('wg-ops-log');
|
||||||
|
log.style.display = 'block';
|
||||||
|
log.textContent = `Удаляю VPN/туннель с роутера «${name}»...\n`;
|
||||||
|
try {
|
||||||
|
const r = await fetch(`/api/routers/${encodeURIComponent(name)}/wireguard/uninstall`, {method:'POST', headers: authHdr()});
|
||||||
|
const d = await r.json();
|
||||||
|
log.textContent += d.output || '';
|
||||||
|
if(!d.ok) log.textContent += '\n❌ Завершилось с ошибкой';
|
||||||
|
else log.textContent += '\n✅ Готово';
|
||||||
|
log.scrollTop = log.scrollHeight;
|
||||||
|
} catch(e){ log.textContent += '\nОшибка: '+e; }
|
||||||
|
}
|
||||||
|
|
||||||
async function wgDeploy(name){
|
async function wgDeploy(name){
|
||||||
const log = document.getElementById('wg-ops-log');
|
const log = document.getElementById('wg-ops-log');
|
||||||
log.style.display = 'block';
|
log.style.display = 'block';
|
||||||
|
|||||||
Reference in New Issue
Block a user