diff --git a/Dockerfile b/Dockerfile index 26a01a3..aefbeee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,4 +3,4 @@ FROM python:3.11 RUN pip install requests urllib3 ADD zte_exporter.py . -CMD python3 zte_exporter.py $PORT $IP $USERNAME $PASSWORD +CMD python3 zte_exporter.py $PORT $IP $USERNAME $PASSWORD $LOGIN diff --git a/compose.yml b/compose.yml index 0e0c377..8c6d6bf 100644 --- a/compose.yml +++ b/compose.yml @@ -9,3 +9,4 @@ services: - IP=192.168.8.1 - USERNAME=admin - PASSWORD=1234 + - LOGIN=single diff --git a/readme.md b/readme.md index 9f8768b..78c623f 100644 --- a/readme.md +++ b/readme.md @@ -2,13 +2,15 @@ ## Getting started -One can just run the provided python script by `python3 zte_exporter ` +One can just run the provided python script by `python3 zte_exporter.py ` -A docker file is provided to compile this and example compose.yml to use in compose tools. To use with docker run, just create .env with the correct values. dockerhub vvkvvk/zte-exporter has the latest version of this available. +Login method depends on the used router, f.e MC7010 uses single login and MC889A has multi. You can tell by if the login page asks for username (multi) or if it's just password (single). On single login the username variable is not used at all so it can be set whatever you fancy. + +A docker file is provided to compile this and example compose.yml to use in compose tools. To use with docker run, just create .env with the correct values. dockerhub vvkvvk/zte-exporter has the latest version of this available. A compose.yml file is provided as example. ## Tested devices -Probably works with other ZTE models, only tested with ZTE MC7010. A simple Grafana dashboard included with the grafana.json. +Probably works with other ZTE models, only tested with ZTE MC7010 and MC889A. A simple Grafana dashboard included with the grafana.json. ## Thanks diff --git a/zte_exporter.py b/zte_exporter.py index 94e44aa..dfeab12 100644 --- a/zte_exporter.py +++ b/zte_exporter.py @@ -15,8 +15,9 @@ import argparse parser = argparse.ArgumentParser("ZTE simple exporter") parser.add_argument("port", help="Serve metrics on what port", type=int) parser.add_argument("ip", help="Router ip address") -parser.add_argument("username", help="Router username") +parser.add_argument("username", help="Router username", default="admin") parser.add_argument("password", help="Router password") +parser.add_argument("--login", help="Login method (multi, single)", default="single") args = parser.parse_args() urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -25,7 +26,8 @@ s = requests.Session() class zteRouter: - def __init__(self, ip, username, password): + def __init__(self, ip, username, password, login): + self.login = login self.ip = ip self.protocol = "http" # default to http self.username = username @@ -50,44 +52,37 @@ class zteRouter: def hash(self, str): return hashlib.sha256(str.encode()).hexdigest() - def getVersion(self): - header = {"Referer": self.referer} - payload = "isTest=false&cmd=wa_inner_version" - r = s.get(self.referer + f"goform/goform_get_cmd_process?{payload}", headers=header, data=payload, verify=False) - return r.json()["wa_inner_version"] - def get_LD(self): header = {"Referer": self.referer} payload = "isTest=false&cmd=LD" - r = s.get(self.referer + f"goform/goform_get_cmd_process?{payload}", headers=header, data=payload, verify=False) + r = s.get(self.referer + f"goform/goform_get_cmd_process?{payload}&_=", headers=header, data=payload, verify=False) return r.json()["LD"].upper() - def getCookie(self, username, password, LD): + def getCookie(self, username, password, LD, login): header = {"Referer": self.referer} hashPassword = self.hash(password).upper() ztePass = self.hash(hashPassword + LD).upper() - old_login = self.getVersion() - payload = { - 'isTest': 'false', - 'goformId': 'LOGIN' if username is not None and old_login in 'MC801' or 'MC7010' else 'LOGIN_MULTI_USER', - 'password': ztePass - } - if username is not None and username != "": - payload['username'] = username + if login == "multi": + payload = { + 'isTest': 'false', + 'goformId': 'LOGIN_MULTI_USER', + 'password': ztePass, + 'user': username + } + else: + payload = { + 'isTest': 'false', + 'goformId': 'LOGIN', + 'password': ztePass, + } r = s.post(self.referer + "goform/goform_set_cmd_process", headers=header, data=payload, verify=False) return "stok=" + r.cookies["stok"].strip('\"') - def get_RD(self): - header = {"Referer": self.referer} - payload = "isTest=false&cmd=RD" - r = s.post(self.referer + "goform/goform_get_cmd_process", headers=header, data=payload, verify=False) - return r.json()["RD"] - def zteinfo(self): ip = self.ip - cookie = self.getCookie(username=self.username, password=self.password, LD=self.get_LD()) + cookie = self.getCookie(username=self.username, password=self.password, LD=self.get_LD(), login=self.login) cmd_url = f"{self.protocol}://{self.ip}/goform/goform_get_cmd_process?multi_data=1&isTest=false&cmd=wa_inner_version%2Clte_rssi%2CZ5g_rssi%2Clte_rsrp%2CZ5g_rsrp%2Clte_rsrq%2CZ5g_rsrq%2Clte_snr%2CZ5g_SINR%2Csignalbar%2Ccell_id%2Cnr5g_action_band%2Ccell_id%2Cnetwork_provider%2Cmonthly_tx_bytes%2Cmonthly_rx_bytes%2Crealtime_tx_bytes%2Crealtime_rx_bytes%2Crealtime_tx_thrpt%2Crealtime_rx_thrpt%2Cwan_ipaddr%2Cwan_apn" cookie_pass = cookie @@ -100,7 +95,7 @@ class zteRouter: response = s.get(cmd_url, headers=headers, verify=False) return response.text -zteInstance = zteRouter(args.ip, args.username, args.password) +zteInstance = zteRouter(args.ip, args.username, args.password, args.login) serverPort = args.port class serveInfos(BaseHTTPRequestHandler):