Загрузка данных


python3 <<'PY'
import os
import pty
import select
import subprocess
import sys
import time
import signal

USER = "user"
PASS = "user"
REMOTE_CMD = "systemctl poweroff"

def sh(cmd):
    return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.DEVNULL).strip()

# Все локальные IP, чтобы не выключить машину, с которой запускаете
local_ips = set()
try:
    out = sh("ip -o -4 addr show | awk '{split($4,a,\"/\"); print a[1]}'")
    local_ips = set(x.strip() for x in out.splitlines() if x.strip())
except Exception:
    pass

# Основной IP и подсеть
myip = sh("ip -4 route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if($i==\"src\"){print $(i+1); exit}}'")
net = ".".join(myip.split(".")[:3])

prompts = [
    "password:",
    "password for",
    "пароль",
    "authentication is required",
    "authenticate",
    "polkit",
]

def run_host(ip):
    print(f"\n=== POWER OFF {ip} ===", flush=True)

    cmd = [
        "ssh",
        "-tt",
        "-o", "ConnectTimeout=3",
        "-o", "ConnectionAttempts=1",
        "-o", "StrictHostKeyChecking=accept-new",
        "-o", "NumberOfPasswordPrompts=5",
        "-o", "PreferredAuthentications=password,keyboard-interactive",
        "-o", "PubkeyAuthentication=no",
        f"{USER}@{ip}",
        REMOTE_CMD,
    ]

    pid, fd = pty.fork()

    if pid == 0:
        os.execvp("ssh", cmd)

    buffer = ""
    last_send = 0
    sent_count = 0
    deadline = time.time() + 35

    while True:
        if time.time() > deadline:
            print(f"\nTIMEOUT: {ip}", flush=True)
            try:
                os.kill(pid, signal.SIGKILL)
            except ProcessLookupError:
                pass
            break

        r, _, _ = select.select([fd], [], [], 0.5)

        if fd in r:
            try:
                data = os.read(fd, 4096)
            except OSError:
                break

            if not data:
                break

            text = data.decode(errors="ignore")
            sys.stdout.write(text)
            sys.stdout.flush()

            buffer = (buffer + text).lower()[-3000:]

            if "continue connecting" in buffer:
                os.write(fd, b"yes\n")
                buffer = ""
                continue

            if any(p in buffer for p in prompts):
                now = time.time()

                # защита от слишком частой отправки
                if now - last_send > 0.7:
                    os.write(fd, (PASS + "\n").encode())
                    last_send = now
                    sent_count += 1
                    buffer = ""

                if sent_count > 10:
                    print(f"\nTOO MANY PASSWORD PROMPTS: {ip}", flush=True)
                    break

        try:
            done, status = os.waitpid(pid, os.WNOHANG)
            if done == pid:
                break
        except ChildProcessError:
            break

    try:
        os.close(fd)
    except OSError:
        pass

for i in range(1, 255):
    ip = f"{net}.{i}"

    if ip in local_ips:
        print(f"SKIP LOCAL: {ip}", flush=True)
        continue

    run_host(ip)

print("\nDONE")
PY