Controlling network access of a specific device to a router using web interface is a pain. Thanks to Mathieu Velten, who developed pynetgear, a Python package that supports scripting Netgear router, by reverse engineering the Netgear Genie App.
I wrote the following code utilizing the pynetgear package to turn on (Allow) and off (Block) network access for a specific device to my router.
#!/usr/bin/env python
import sys
import time
import click
from pynetgear import Netgear
class NetgearManager:
"""
Netgear Router Manager
"""
def __init__(self, pwd):
self.session = Netgear(password=pwd)
def search_connected_device_by_name(self, name):
found = []
for device in self.session.get_attached_devices():
if device.name == name:
found.append(device)
if len(found) >= 0:
return found
return None
def get_device_status_by_name(self, name):
devices = self.search_connected_device_by_name(name)
if len(devices) > 1:
print(f'More than one device has the name {name}', file=sys.stderr)
for d in devices:
print(d.ip, d.type, d.mac, d.allow_block_device)
return False
def set_device_status_by_name(self, name, status_code, delay):
assert status_code in ['Allow', 'Block']
devices = self.search_connected_device_by_name(name)
if len(devices)==1:
mac_address = devices[0].mac
return self.set_device_status_by_mac(self, mac_address, status_code, delay)
elif len(devices)>1:
print(f'More than one device has the name {name}', file=sys.stderr)
for d in devices:
print(d.ip, d.type, d.mac, d.allow_or_block, file=sys.stderr)
return False
def set_device_status_by_mac(self, mac, status_code, delay):
if delay > 0:
time.sleep(delay)
return self.session.allow_block_device(mac, device_status=status_code)
@click.group()
def cli():
pass
@click.command()
@click.option('--password', prompt=True, hide_input=True, confirmation_prompt=False, help='Netgear outer admmin password')
@click.option('--name', help='Device name')
@click.option('--mac', default=None, help='Device MAC address')
@click.option('--status', help='Status: Allow or Block')
@click.option('--delay', default=0, help='Time delay in minutes')
def switch(password, name, mac, status, delay):
manager = NetgearManager(password)
delay *= 60 # minutes to seconds
if mac:
result = manager.set_device_status_by_mac(mac, status, delay)
else:
result = manager.set_device_status_by_name(name, status, delay)
if not result:
msg = f'Cannot switch device {name} status to {status}'
print(msg, file=sys.stderr)
@click.command()
@click.option('--password', prompt=True, hide_input=True, confirmation_prompt=False, help='Netgear outer admmin password')
def show(password):
manager = NetgearManager(password)
devices = []
for idx, dev in enumerate(manager.session.get_attached_devices()):
print(str(idx), dev.name, dev.ip, dev.type, dev.mac, dev.allow_or_block)
cli.add_command(switch)
cli.add_command(show)
if __name__ == '__main__':
cli()