keenetic-dpr-bypass/main.py

205 lines
5.7 KiB
Python
Raw Permalink Normal View History

2023-09-04 23:43:45 +03:00
import httplib
import hashlib
import json
2023-09-05 09:14:32 +03:00
import argparse
import socket
import urllib
2023-09-06 15:13:28 +03:00
import ConfigParser
2023-09-07 11:43:32 +03:00
import os
import sys
parent_dir = os.path.abspath(os.path.dirname(__file__))
2023-09-07 12:06:24 +03:00
vendor_dir = os.path.join(parent_dir, 'vendor')
2023-09-07 11:43:32 +03:00
sys.path.append(vendor_dir)
from netaddr import IPNetwork
2023-09-04 23:43:45 +03:00
class KeeneticAPI:
def __init__(self, destination="192.168.1.1"):
self._conn = httplib.HTTPConnection(destination)
self._cookie = ""
pass
def _get(self, url):
headers = {"Cookie": self._cookie}
self._conn.request("GET", url, "", headers)
res = self._conn.getresponse()
data = res.read()
return res, data
def _post(self, url, body):
headers = {"Content-type": "application/json", "Cookie": self._cookie}
self._conn.request("POST", url, body, headers)
res = self._conn.getresponse()
data = res.read()
return res, data
2023-09-05 09:14:32 +03:00
def _delete(self, url):
headers = {"Cookie": self._cookie}
self._conn.request("DELETE", url, "", headers)
res = self._conn.getresponse()
data = res.read()
return res, data
2023-09-04 23:43:45 +03:00
def auth(self, login, passw):
res, _ = self._get("/auth")
self._cookie = res.getheader("Set-Cookie")
if res.status == 401:
md5 = login + ":" + res.getheader("X-NDM-Realm") + ":" + passw
md5 = hashlib.md5(md5.encode('utf-8'))
sha = res.getheader("X-NDM-Challenge") + md5.hexdigest()
sha = hashlib.sha256(sha.encode('utf-8'))
self._post("/auth", json.dumps({"login": login, "password": sha.hexdigest()}))
2023-09-07 11:30:22 +03:00
def get_ip_route(self):
2023-09-05 09:14:32 +03:00
res, data = self._get("/rci/ip/route")
return json.loads(data)
2023-09-04 23:43:45 +03:00
2023-09-05 09:14:32 +03:00
def set_ip_route(self, route_data):
res, data = self._post("/rci/ip/route", json.dumps(route_data))
return res.status == 200
2023-09-04 23:43:45 +03:00
2023-09-05 09:14:32 +03:00
def remove_ip_route(self, route):
res, _ = self._delete("/rci/ip/route?" + urllib.urlencode(route))
return res.status == 200
def get_interfaces(self):
res, data = self._get("/rci/show/interface")
return json.loads(data, encoding='utf-8')
2023-09-06 15:13:28 +03:00
def set_ip_routes(self, routes):
res, _ = self._post("/rci/ip/route", json.dumps(routes))
return res.status == 200
2023-09-05 09:14:32 +03:00
def interfaces(args):
2023-09-07 12:36:22 +03:00
config_file = os.path.normpath(os.path.join(parent_dir, args.config_file))
2023-09-07 11:30:22 +03:00
config = ConfigParser.ConfigParser()
2023-09-07 12:36:22 +03:00
config.read(config_file)
2023-09-04 23:43:45 +03:00
api = KeeneticAPI()
2023-09-07 11:30:22 +03:00
api.auth(
config.get('auth', 'login'),
config.get('auth', 'password')
)
2023-09-05 09:14:32 +03:00
ifaces = api.get_interfaces()
2023-09-06 15:13:28 +03:00
max_len = 0
for iface in ifaces:
max_len = max(len(iface), max_len)
max_len = max(len(ifaces[iface].get('description') or '-'), max_len)
print "{:^{width}} {:^{width}}".format("ID", "DESCRIPTION", width=max_len)
2023-09-05 09:14:32 +03:00
for iface in ifaces:
2023-09-06 15:13:28 +03:00
print "{:^{width}} {:^{width}}".format(iface, (ifaces[iface].get('description') or '-'), width=max_len)
def start(args):
2023-09-07 12:36:22 +03:00
config_file = os.path.normpath(os.path.join(parent_dir, args.config_file))
2023-09-06 15:13:28 +03:00
config = ConfigParser.ConfigParser()
2023-09-07 12:36:22 +03:00
config.read(config_file)
2023-09-06 15:13:28 +03:00
2023-09-07 11:30:22 +03:00
api = KeeneticAPI()
api.auth(
config.get('auth', 'login'),
config.get('auth', 'password')
)
old_routes = api.get_ip_route()
def filter_old_routes(item):
return item['comment'].startswith('[A]')
old_routes = list(filter(filter_old_routes, old_routes))
for route in old_routes:
api.remove_ip_route(route)
2023-09-07 20:27:37 +03:00
routes_dir = os.path.normpath(os.path.join(parent_dir, config.get('app', 'dir')))
2023-09-06 15:13:28 +03:00
routes = list()
for filename in os.listdir(routes_dir):
fp = os.path.join(routes_dir, filename)
if not os.path.isfile(fp):
continue
interface_name = os.path.splitext(filename)[0]
data = list()
with open(fp) as f:
comment = ''
lst = list()
for line in f:
ln = line.strip()
if ln == '':
continue
if ln.startswith('#'):
if len(lst) > 0:
data.append(
(lst, comment)
)
comment = ln.lstrip('# ')
lst = list()
else:
lst.append(ln)
2023-09-07 11:30:22 +03:00
if len(lst) > 0:
data.append(
(lst, comment)
)
2023-09-06 15:13:28 +03:00
for group in data:
hosts, description = group
for host in hosts:
2023-09-10 20:30:55 +03:00
try:
2023-09-07 11:30:22 +03:00
ipnet = socket.gethostbyname(host)
2023-09-10 20:30:55 +03:00
except:
2023-09-07 11:30:22 +03:00
ipnet = host
ipnetwork = IPNetwork(ipnet)
2023-09-06 15:13:28 +03:00
routes.append(
{
'network': str(ipnetwork.network),
'mask': str(ipnetwork.netmask),
'interface': interface_name,
'auto': True,
'comment': '[A] {}'.format(description)
}
)
api = KeeneticAPI()
api.auth(
config.get('auth', 'login'),
config.get('auth', 'password')
)
api.set_ip_routes(routes)
2023-09-05 09:14:32 +03:00
def main():
parser = argparse.ArgumentParser(description="a script to do stuff")
2023-09-07 11:30:22 +03:00
parser.add_argument("--config-file", default="app.cfg")
2023-09-05 09:14:32 +03:00
subparsers = parser.add_subparsers()
2023-09-06 15:13:28 +03:00
parser_interfaces = subparsers.add_parser('interfaces')
parser_interfaces.set_defaults(func=interfaces)
parser_start = subparsers.add_parser('start')
parser_start.set_defaults(func=start)
2023-09-05 09:14:32 +03:00
args = parser.parse_args()
args.func(args)
2023-09-04 23:43:45 +03:00
if __name__ == "__main__":
main()