multi login support, tested MC889
parent
936dcde75c
commit
57503b356c
|
@ -3,4 +3,4 @@ FROM python:3.11
|
||||||
RUN pip install requests urllib3
|
RUN pip install requests urllib3
|
||||||
ADD zte_exporter.py .
|
ADD zte_exporter.py .
|
||||||
|
|
||||||
CMD python3 zte_exporter.py $PORT $IP $USERNAME $PASSWORD
|
CMD python3 zte_exporter.py $PORT $IP $USERNAME $PASSWORD $LOGIN
|
||||||
|
|
|
@ -9,3 +9,4 @@ services:
|
||||||
- IP=192.168.8.1
|
- IP=192.168.8.1
|
||||||
- USERNAME=admin
|
- USERNAME=admin
|
||||||
- PASSWORD=1234
|
- PASSWORD=1234
|
||||||
|
- LOGIN=single
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
One can just run the provided python script by `python3 zte_exporter <port> <router ip> <admin username> <admin password>`
|
One can just run the provided python script by `python3 zte_exporter.py <port> <router ip> <admin username> <admin password> <login method>`
|
||||||
|
|
||||||
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
|
## 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
|
## Thanks
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,9 @@ import argparse
|
||||||
parser = argparse.ArgumentParser("ZTE simple exporter")
|
parser = argparse.ArgumentParser("ZTE simple exporter")
|
||||||
parser.add_argument("port", help="Serve metrics on what port", type=int)
|
parser.add_argument("port", help="Serve metrics on what port", type=int)
|
||||||
parser.add_argument("ip", help="Router ip address")
|
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("password", help="Router password")
|
||||||
|
parser.add_argument("--login", help="Login method (multi, single)", default="single")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||||
|
@ -25,7 +26,8 @@ s = requests.Session()
|
||||||
|
|
||||||
class zteRouter:
|
class zteRouter:
|
||||||
|
|
||||||
def __init__(self, ip, username, password):
|
def __init__(self, ip, username, password, login):
|
||||||
|
self.login = login
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.protocol = "http" # default to http
|
self.protocol = "http" # default to http
|
||||||
self.username = username
|
self.username = username
|
||||||
|
@ -50,44 +52,37 @@ class zteRouter:
|
||||||
def hash(self, str):
|
def hash(self, str):
|
||||||
return hashlib.sha256(str.encode()).hexdigest()
|
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):
|
def get_LD(self):
|
||||||
header = {"Referer": self.referer}
|
header = {"Referer": self.referer}
|
||||||
payload = "isTest=false&cmd=LD"
|
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()
|
return r.json()["LD"].upper()
|
||||||
|
|
||||||
def getCookie(self, username, password, LD):
|
def getCookie(self, username, password, LD, login):
|
||||||
header = {"Referer": self.referer}
|
header = {"Referer": self.referer}
|
||||||
hashPassword = self.hash(password).upper()
|
hashPassword = self.hash(password).upper()
|
||||||
ztePass = self.hash(hashPassword + LD).upper()
|
ztePass = self.hash(hashPassword + LD).upper()
|
||||||
old_login = self.getVersion()
|
|
||||||
|
|
||||||
|
if login == "multi":
|
||||||
payload = {
|
payload = {
|
||||||
'isTest': 'false',
|
'isTest': 'false',
|
||||||
'goformId': 'LOGIN' if username is not None and old_login in 'MC801' or 'MC7010' else 'LOGIN_MULTI_USER',
|
'goformId': 'LOGIN_MULTI_USER',
|
||||||
'password': ztePass
|
'password': ztePass,
|
||||||
|
'user': username
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
payload = {
|
||||||
|
'isTest': 'false',
|
||||||
|
'goformId': 'LOGIN',
|
||||||
|
'password': ztePass,
|
||||||
}
|
}
|
||||||
if username is not None and username != "":
|
|
||||||
payload['username'] = username
|
|
||||||
|
|
||||||
r = s.post(self.referer + "goform/goform_set_cmd_process", headers=header, data=payload, verify=False)
|
r = s.post(self.referer + "goform/goform_set_cmd_process", headers=header, data=payload, verify=False)
|
||||||
return "stok=" + r.cookies["stok"].strip('\"')
|
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):
|
def zteinfo(self):
|
||||||
ip = self.ip
|
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"
|
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
|
cookie_pass = cookie
|
||||||
|
|
||||||
|
@ -100,7 +95,7 @@ class zteRouter:
|
||||||
response = s.get(cmd_url, headers=headers, verify=False)
|
response = s.get(cmd_url, headers=headers, verify=False)
|
||||||
return response.text
|
return response.text
|
||||||
|
|
||||||
zteInstance = zteRouter(args.ip, args.username, args.password)
|
zteInstance = zteRouter(args.ip, args.username, args.password, args.login)
|
||||||
serverPort = args.port
|
serverPort = args.port
|
||||||
|
|
||||||
class serveInfos(BaseHTTPRequestHandler):
|
class serveInfos(BaseHTTPRequestHandler):
|
||||||
|
|
Loading…
Reference in New Issue