#!/usr/bin/env python3 import ssl import sys import json import argparse from datetime import datetime try: from librouteros import connect from librouteros.query import Key except ImportError: print("Error: librouteros module not found") print("Install with: pip install librouteros") sys.exit(1) def get_router_data(host, username='grahamro', password='cFKhz8q5gPLoucMbcT1Iy58r3IXgc3', port=8729): """ Connect to a MikroTik router and retrieve network configuration Args: host: IP address or hostname of the router username: Router username (default: grahamro) password: Router password port: API-SSL port (default: 8729) Returns: Dictionary containing router configuration data """ print(f"=== Connecting to MikroTik Router ({host}) ===\n") # SSL context for secure connection ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE try: # Connect to router api = connect( username=username, password=password, host=host, port=port, ssl_wrapper=ctx.wrap_socket ) print("āœ“ Connected successfully\n") # Get router identity identity = None try: identity_data = api('/system/identity/print') if identity_data: identity = identity_data[0].get('name', 'Unknown') print(f"Router Identity: {identity}\n") except: print("Could not retrieve router identity\n") # Get IP addresses print("=== IP Addresses ===") ip_addresses = api('/ip/address/print') subnets = [] for addr in ip_addresses: if not addr.get('disabled', False): address = addr['address'] interface = addr.get('interface', 'unknown') network = addr.get('network', '') comment = addr.get('comment', '') dynamic = addr.get('dynamic', False) print(f"Interface: {interface}") print(f" Address: {address}") print(f" Network: {network}") if comment: print(f" Comment: {comment}") if dynamic: print(f" Dynamic: Yes") print() subnets.append({ 'address': address, 'network': network, 'interface': interface, 'comment': comment, 'dynamic': dynamic }) # Get interfaces print("\n=== Active Interfaces ===") interfaces = api('/interface/print') active_interfaces = [] for iface in interfaces: if not iface.get('disabled', False) and iface.get('running', False): name = iface['name'] itype = iface.get('type', 'unknown') mac = iface.get('mac-address', 'N/A') comment = iface.get('comment', '') mtu = iface.get('mtu', 'default') active_interfaces.append({ 'name': name, 'type': itype, 'mac': mac, 'comment': comment, 'mtu': mtu }) print(f"{name} ({itype})") if comment: print(f" Comment: {comment}") if mac != 'N/A': print(f" MAC: {mac}") # Get VLANs print("\n\n=== VLANs ===") vlans = [] try: vlan_interfaces = api('/interface/vlan/print') for vlan in vlan_interfaces: if not vlan.get('disabled', False): name = vlan['name'] vlan_id = vlan.get('vlan-id', 'unknown') interface = vlan.get('interface', 'unknown') vlans.append({ 'name': name, 'vlan_id': vlan_id, 'interface': interface }) print(f"{name}: VLAN {vlan_id} on {interface}") except: print("No VLANs found or access denied") # Get PPPoE servers print("\n\n=== PPPoE Servers ===") pppoe_servers = [] try: servers = api('/interface/pppoe-server/server/print') for server in servers: if not server.get('disabled', False): name = server.get('service-name', 'unnamed') interface = server.get('interface', 'unknown') pppoe_servers.append({ 'service_name': name, 'interface': interface }) print(f"Service: {name} on {interface}") except: print("No PPPoE servers found or access denied") # Get static routes print("\n\n=== Static Routes ===") routes = [] try: static_routes = api('/ip/route/print') for route in static_routes: if not route.get('dynamic', False) and not route.get('disabled', False): dst = route.get('dst-address', '') gateway = route.get('gateway', '') distance = route.get('distance', '') comment = route.get('comment', '') if dst != '0.0.0.0/0': # Skip default route for brevity routes.append({ 'destination': dst, 'gateway': gateway, 'distance': distance, 'comment': comment }) print(f"{dst} via {gateway}") if comment: print(f" Comment: {comment}") except: print("Could not retrieve routes") # Close connection api.close() # Compile all data router_data = { 'host': host, 'identity': identity, 'timestamp': datetime.now().isoformat(), 'subnets': subnets, 'interfaces': active_interfaces, 'vlans': vlans, 'pppoe_servers': pppoe_servers, 'routes': routes } print(f"\n\n=== Summary ===") print(f"Router: {identity or host}") print(f"Found {len(subnets)} IP addresses/subnets") print(f"Found {len(active_interfaces)} active interfaces") print(f"Found {len(vlans)} VLANs") print(f"Found {len(pppoe_servers)} PPPoE servers") print(f"Found {len(routes)} static routes") return router_data except Exception as e: print(f"āœ— Connection failed: {e}") return None def save_router_data(data, filename=None): """Save router data to a JSON file""" if not filename: # Generate filename based on router identity or IP identity = data.get('identity') or data.get('host', 'router') identity_clean = identity.replace(' ', '_').replace('/', '_').replace('.', '_') filename = f"router_data_{identity_clean}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" with open(filename, 'w') as f: json.dump(data, f, indent=2) print(f"\nData saved to: {filename}") return filename def main(): parser = argparse.ArgumentParser(description='Retrieve configuration from a MikroTik router') parser.add_argument('host', help='IP address or hostname of the router') parser.add_argument('--username', '-u', default='grahamro', help='Router username (default: grahamro)') parser.add_argument('--password', '-p', default='cFKhz8q5gPLoucMbcT1Iy58r3IXgc3', help='Router password') parser.add_argument('--port', type=int, default=8729, help='API-SSL port (default: 8729)') parser.add_argument('--output', '-o', help='Output filename (default: auto-generated)') parser.add_argument('--json', action='store_true', help='Output raw JSON to stdout') args = parser.parse_args() # Get router data data = get_router_data(args.host, args.username, args.password, args.port) if data: if args.json: # Output JSON to stdout print("\n=== JSON Output ===") print(json.dumps(data, indent=2)) else: # Save to file save_router_data(data, args.output) print("\nāœ“ Router data retrieved successfully") else: print("\nāœ— Failed to retrieve router data") return 1 return 0 if __name__ == "__main__": sys.exit(main())