chore(router): Rename reset_router.py to router_reset.py
This commit is contained in:
1 parent
545098eceb
commit
c781ad84c4
1 file changed
Executable
+93
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
import ssl
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ROUTER_HOST = "192.168.1.1"
|
||||
ROUTER_USERNAME = "abdus"
|
||||
ROUTER_PASSWORD = "xAsametk50"
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Log in to the Zyxel router over HTTPS and reboot it",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
parser.add_argument("--host", default=ROUTER_HOST)
|
||||
parser.add_argument("--username", default=ROUTER_USERNAME)
|
||||
parser.add_argument("--timeout", type=float, default=15.0, help="Request timeout in seconds")
|
||||
parser.add_argument("--dry-run", action="store_true", help="Log in but do not reboot")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def build_opener() -> urllib.request.OpenerDirector:
|
||||
# The router uses a self-signed certificate. Over HTTPS the UI skips its RSA/AES login layer.
|
||||
context = ssl.create_default_context()
|
||||
context.check_hostname = False
|
||||
context.verify_mode = ssl.CERT_NONE
|
||||
return urllib.request.build_opener(
|
||||
urllib.request.HTTPSHandler(context=context),
|
||||
urllib.request.HTTPCookieProcessor(),
|
||||
)
|
||||
|
||||
|
||||
def post(opener: urllib.request.OpenerDirector, url: str, body: dict, timeout: float) -> dict:
|
||||
request = urllib.request.Request(
|
||||
url=url,
|
||||
data=json.dumps(body).encode(),
|
||||
headers={"Content-Type": "application/json"},
|
||||
method="POST",
|
||||
)
|
||||
with opener.open(request, timeout=timeout) as response:
|
||||
raw = response.read().decode()
|
||||
return json.loads(raw) if raw.strip() else {}
|
||||
|
||||
|
||||
def login(opener: urllib.request.OpenerDirector, base_url: str, username: str, timeout: float) -> str:
|
||||
body = post(
|
||||
opener=opener,
|
||||
url=f"{base_url}/UserLogin",
|
||||
body={
|
||||
"Input_Account": username,
|
||||
"Input_Passwd": base64.b64encode(ROUTER_PASSWORD.encode()).decode(),
|
||||
"currLang": "en",
|
||||
"RememberPassword": 0,
|
||||
"SHA512_password": False,
|
||||
},
|
||||
timeout=timeout,
|
||||
)
|
||||
if body.get("result") != "ZCFG_SUCCESS":
|
||||
raise RuntimeError(f"Login rejected: {body}")
|
||||
return body.get("sessionkey", "")
|
||||
|
||||
|
||||
def reboot(opener: urllib.request.OpenerDirector, base_url: str, session_key: str, timeout: float) -> None:
|
||||
query = f"?{urllib.parse.urlencode({'sessionkey': session_key})}" if session_key else ""
|
||||
body = post(opener=opener, url=f"{base_url}/cgi-bin/Reboot{query}", body={}, timeout=timeout)
|
||||
logger.info("Reboot response: %s", body)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
args = parse_args()
|
||||
base_url = f"https://{args.host}"
|
||||
opener = build_opener()
|
||||
|
||||
session_key = login(opener=opener, base_url=base_url, username=args.username, timeout=args.timeout)
|
||||
logger.info("Logged in as %s", args.username)
|
||||
if args.dry_run:
|
||||
logger.info("Dry run, not rebooting")
|
||||
return
|
||||
reboot(opener=opener, base_url=base_url, session_key=session_key, timeout=args.timeout)
|
||||
logger.info("Reboot request sent, router is back in about a minute")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user