poc2_worked

This commit is contained in:
Mateusz Gruszczyński
2026-08-15 18:29:36 +02:00
parent fc3a2944b2
commit 71b6c0d86f
62 changed files with 9112 additions and 375 deletions
+111
View File
@@ -64,6 +64,117 @@ class RouterOSClient:
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ValueError) as exc:
return BlockResult(False, f"RouterOS REST error: {exc}")
def list_blocks(self) -> list[dict]:
if not self.configured:
return []
try:
result = self._request(
"GET",
"/rest/ip/firewall/address-list",
query={"list": self.address_list},
)
if not isinstance(result, list):
return []
rows = []
for item in result:
if not isinstance(item, dict):
continue
rows.append({
"id": item.get(".id") or item.get("id"),
"address": item.get("address"),
"list": item.get("list"),
"timeout": item.get("timeout"),
"creation_time": item.get("creation-time") or item.get("creation_time"),
"comment": item.get("comment", ""),
"dynamic": str(item.get("dynamic", "false")).lower() == "true",
})
return rows
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ValueError):
return []
def list_arp(self) -> list[dict]:
"""Return RouterOS ARP observations for passive asset enrichment."""
if not self.configured:
return []
try:
result = self._request("GET", "/rest/ip/arp")
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ValueError):
return []
if not isinstance(result, list):
return []
rows = []
for item in result:
if not isinstance(item, dict):
continue
address = str(item.get("address") or "").strip()
if not address:
continue
rows.append({
"address": address,
"mac": str(item.get("mac-address") or item.get("mac_address") or "").strip(),
"interface": str(item.get("interface") or "").strip(),
"dynamic": str(item.get("dynamic", "false")).lower() == "true",
"complete": str(item.get("complete", "true")).lower() != "false",
})
return rows
def list_dhcp_leases(self) -> list[dict]:
"""Return DHCP lease identity data when the router exposes a DHCP server table."""
if not self.configured:
return []
try:
result = self._request("GET", "/rest/ip/dhcp-server/lease")
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ValueError):
return []
if not isinstance(result, list):
return []
rows = []
for item in result:
if not isinstance(item, dict):
continue
address = str(item.get("active-address") or item.get("address") or "").strip()
if not address:
continue
rows.append({
"address": address,
"mac": str(item.get("active-mac-address") or item.get("mac-address") or "").strip(),
"hostname": str(item.get("host-name") or "").strip(),
"status": str(item.get("status") or "").strip(),
"server": str(item.get("server") or "").strip(),
"expires_after": str(item.get("expires-after") or "").strip(),
"last_seen": str(item.get("last-seen") or "").strip(),
})
return rows
def unblock_ip(self, address: str) -> BlockResult:
if not self.configured:
return BlockResult(False, "RouterOS credentials are not configured")
try:
existing = self._request(
"GET",
"/rest/ip/firewall/address-list",
query={"list": self.address_list, "address": address},
)
if not isinstance(existing, list) or not existing:
return BlockResult(True, "address is not present in RouterOS address-list")
removed = 0
for item in existing:
if not isinstance(item, dict):
continue
item_id = item.get(".id") or item.get("id")
if not item_id:
continue
self._request(
"DELETE",
"/rest/ip/firewall/address-list/" + urllib.parse.quote(str(item_id), safe="*"),
)
removed += 1
return BlockResult(True, f"removed {removed} RouterOS address-list entr{'y' if removed == 1 else 'ies'}")
except (urllib.error.URLError, urllib.error.HTTPError, TimeoutError, ValueError) as exc:
return BlockResult(False, f"RouterOS REST error: {exc}")
def _request(
self,
method: str,