Merge pull request 'feat: report what listens, and which OPNsense service it is' (#10) from feat/listening-sockets into master
This commit was merged in pull request #10.
This commit is contained in:
@@ -88,6 +88,7 @@ arguments.
|
|||||||
| `get_vlans` | ✅ | `GET /api/interfaces/vlan_settings/search_item` |
|
| `get_vlans` | ✅ | `GET /api/interfaces/vlan_settings/search_item` |
|
||||||
| `get_mac_address_table` | ❌ | Not applicable (firewall, no L2 switching) |
|
| `get_mac_address_table` | ❌ | Not applicable (firewall, no L2 switching) |
|
||||||
| `ping` | ✅ | `POST /api/diagnostics/ping/set` + `start` + `search_jobs` + `stop`/`remove` |
|
| `ping` | ✅ | `POST /api/diagnostics/ping/set` + `start` + `search_jobs` + `stop`/`remove` |
|
||||||
|
| `get_listening_sockets` | ✅ | `GET /api/diagnostics/interface/get_socket_statistics` + `/api/core/service/search` + `/api/wireguard/service/show` (WireGuard's kernel sockets by listen port) |
|
||||||
| `ping_sweep` | ✅ ³ | same endpoints, one batch of parallel jobs at a time |
|
| `ping_sweep` | ✅ ³ | same endpoints, one batch of parallel jobs at a time |
|
||||||
|
|
||||||
> ¹ Requires the `os-lldpd` plugin. Returns empty dict if the plugin is not installed.
|
> ¹ Requires the `os-lldpd` plugin. Returns empty dict if the plugin is not installed.
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
"""What listens on the firewall, and which OPNsense service it is. Pure: no I/O.
|
||||||
|
|
||||||
|
``/api/diagnostics/interface/get_socket_statistics`` is netstat's socket list
|
||||||
|
with sockstat's user, command and PID merged in, read by configd as root. The
|
||||||
|
contract this serves -- ``napalm_device_types.models.ListeningSocketsDict`` --
|
||||||
|
wants the sockets that listen: a TCP socket in LISTEN and a bound UDP socket,
|
||||||
|
both without a peer (``*:*``).
|
||||||
|
|
||||||
|
**Which service.** netOrk keeps a firewall's services under the names of its
|
||||||
|
service list (``/api/core/service/search``), so a socket's ``unit`` is one of
|
||||||
|
those names, or None. The statistics name the process, cut to ten characters
|
||||||
|
by FreeBSD (``mdns-repea``): a name the service list has wins, then one the
|
||||||
|
command starts with or -- cut short -- is the start of, then the few daemons
|
||||||
|
whose service is called otherwise (``sshd`` is ``openssh``, ``ospfd`` is
|
||||||
|
``frr``). The admin UI and the captive portal are both lighttpd; the portal's
|
||||||
|
runs as ``www``.
|
||||||
|
|
||||||
|
**WireGuard has no process.** Its sockets belong to the kernel (``??``) and are
|
||||||
|
told by the listen ports of the WireGuard interfaces.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any, Dict, Iterable, List, Optional, Set
|
||||||
|
|
||||||
|
from napalm_device_types.models import ListeningSocketDict
|
||||||
|
|
||||||
|
#: FRR's daemons, all under the one service ``frr``.
|
||||||
|
_FRR_DAEMONS = "zebra mgmtd staticd ospfd ospf6d bgpd bfdd ripd ripngd isisd pimd watchfrr".split()
|
||||||
|
#: Daemons whose OPNsense service has another name, by the command as reported.
|
||||||
|
_SERVICE_OF: Dict[str, str] = {
|
||||||
|
"sshd": "openssh",
|
||||||
|
"kea-ctrl-a": "kea-dhcp",
|
||||||
|
"kea-ctrl-agent": "kea-dhcp",
|
||||||
|
"charon": "strongswan",
|
||||||
|
**{daemon: "frr" for daemon in _FRR_DAEMONS},
|
||||||
|
}
|
||||||
|
#: FreeBSD cuts a command at this many characters in the socket list.
|
||||||
|
_COMMAND_LENGTH = 10
|
||||||
|
#: Below this length a service name is too short to match a command's start (``pf``).
|
||||||
|
_PREFIX_MIN = 4
|
||||||
|
_NOBODY = "??"
|
||||||
|
_PEERLESS = "*"
|
||||||
|
|
||||||
|
|
||||||
|
def _service_of(command: str, user: str, services: Set[str]) -> Optional[str]:
|
||||||
|
if command == "lighttpd":
|
||||||
|
name = "captiveportal" if user == "www" else "webgui"
|
||||||
|
return name if name in services else None
|
||||||
|
if command in services:
|
||||||
|
return command
|
||||||
|
alias = _SERVICE_OF.get(command)
|
||||||
|
if alias in services:
|
||||||
|
return alias
|
||||||
|
matches = [
|
||||||
|
name
|
||||||
|
for name in services
|
||||||
|
if (len(name) >= _PREFIX_MIN and command.startswith(name))
|
||||||
|
or (len(command) == _COMMAND_LENGTH and name.startswith(command))
|
||||||
|
]
|
||||||
|
return matches[0] if len(matches) == 1 else None
|
||||||
|
|
||||||
|
|
||||||
|
def _address(protocol: str, address: str) -> tuple:
|
||||||
|
"""``(address, interface)``: ``*`` is every address of the socket's family."""
|
||||||
|
if address == "*":
|
||||||
|
return ("::" if protocol.endswith("6") else "0.0.0.0"), None
|
||||||
|
host, _, zone = address.partition("%")
|
||||||
|
return host, zone or None
|
||||||
|
|
||||||
|
|
||||||
|
def _socket(
|
||||||
|
entry: Dict[str, Any], services: Set[str], wireguard_ports: Set[int]
|
||||||
|
) -> Optional[ListeningSocketDict]:
|
||||||
|
protocol = str(entry.get("protocol") or "")
|
||||||
|
proto = protocol[:3]
|
||||||
|
local, remote = entry.get("local") or {}, entry.get("remote") or {}
|
||||||
|
port = str(local.get("port") or "")
|
||||||
|
if proto not in ("tcp", "udp") or not port.isdigit():
|
||||||
|
return None
|
||||||
|
if remote.get("address") != _PEERLESS or remote.get("port") != _PEERLESS:
|
||||||
|
return None
|
||||||
|
command, pid = str(entry.get("command") or _NOBODY), str(entry.get("pid") or _NOBODY)
|
||||||
|
process = None if command == _NOBODY else command
|
||||||
|
if process is not None:
|
||||||
|
unit = _service_of(process, str(entry.get("user") or ""), services)
|
||||||
|
elif proto == "udp" and int(port) in wireguard_ports and "wireguard" in services:
|
||||||
|
unit = "wireguard"
|
||||||
|
else:
|
||||||
|
unit = None
|
||||||
|
address, interface = _address(protocol, str(local.get("address") or ""))
|
||||||
|
return {
|
||||||
|
"proto": proto,
|
||||||
|
"address": address,
|
||||||
|
"port": int(port),
|
||||||
|
"interface": interface,
|
||||||
|
"process": process,
|
||||||
|
"pid": int(pid) if pid.isdigit() else None,
|
||||||
|
"unit": unit,
|
||||||
|
"container_id": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def wireguard_listen_ports(show: Dict[str, Any]) -> Set[int]:
|
||||||
|
"""The listen ports of the WireGuard interfaces in ``/api/wireguard/service/show``."""
|
||||||
|
ports: Set[int] = set()
|
||||||
|
for row in show.get("rows") or []:
|
||||||
|
port = str(row.get("listen-port") or "")
|
||||||
|
if row.get("type") == "interface" and port.isdigit():
|
||||||
|
ports.add(int(port))
|
||||||
|
return ports
|
||||||
|
|
||||||
|
|
||||||
|
def parse_socket_statistics(
|
||||||
|
statistics: Dict[str, Any], services: Iterable[str], wireguard_ports: Set[int]
|
||||||
|
) -> List[ListeningSocketDict]:
|
||||||
|
"""The listening sockets of ``get_socket_statistics``, sorted by protocol,
|
||||||
|
port and address. Every section is read: the UNIX sockets have no ``local``."""
|
||||||
|
names = set(services)
|
||||||
|
sockets: List[ListeningSocketDict] = []
|
||||||
|
for section in (statistics.get("statistics") or {}).values():
|
||||||
|
for entry in (section or {}).values() if isinstance(section, dict) else ():
|
||||||
|
socket = _socket(entry, names, wireguard_ports) if isinstance(entry, dict) else None
|
||||||
|
if socket is not None:
|
||||||
|
sockets.append(socket)
|
||||||
|
return sorted(
|
||||||
|
sockets, key=lambda s: (s["proto"], s["port"], s["address"], s["interface"] or "")
|
||||||
|
)
|
||||||
@@ -53,8 +53,10 @@ import requests
|
|||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
|
|
||||||
from napalm_device_types import FingerprintRule, FirewallDriver
|
from napalm_device_types import FingerprintRule, FirewallDriver
|
||||||
|
from napalm_device_types.models import ListeningSocketsDict
|
||||||
from napalm.base.exceptions import ConnectionException, ConnectionClosedException, MergeConfigException
|
from napalm.base.exceptions import ConnectionException, ConnectionClosedException, MergeConfigException
|
||||||
|
|
||||||
|
from napalm_opnsense.listening import parse_socket_statistics, wireguard_listen_ports
|
||||||
from napalm_opnsense.ping_mixin import OPNsensePingMixin
|
from napalm_opnsense.ping_mixin import OPNsensePingMixin
|
||||||
from napalm_opnsense.port_forwards import alias_index, port_forwards, wan_interfaces
|
from napalm_opnsense.port_forwards import alias_index, port_forwards, wan_interfaces
|
||||||
|
|
||||||
@@ -1789,6 +1791,26 @@ class OPNsenseDriver(OPNsensePingMixin, FirewallDriver):
|
|||||||
})
|
})
|
||||||
return sorted(result, key=lambda x: x["name"].lower())
|
return sorted(result, key=lambda x: x["name"].lower())
|
||||||
|
|
||||||
|
def get_listening_sockets(self) -> ListeningSocketsDict:
|
||||||
|
"""Every listening TCP and bound UDP socket, with the OPNsense service behind it.
|
||||||
|
|
||||||
|
Read from ``/api/diagnostics/interface/get_socket_statistics``, which
|
||||||
|
configd collects as root, so every socket names its process where it has
|
||||||
|
one (``attributed``). Which service: :mod:`napalm_opnsense.listening`.
|
||||||
|
"""
|
||||||
|
statistics = self._get("/api/diagnostics/interface/get_socket_statistics")
|
||||||
|
services = [service["name"] for service in self.get_services()]
|
||||||
|
try:
|
||||||
|
wireguard = wireguard_listen_ports(self._get("/api/wireguard/service/show"))
|
||||||
|
except Exception as exc:
|
||||||
|
# No WireGuard here: its kernel sockets stay nobody's.
|
||||||
|
logger.debug("WireGuard listen ports not read: %s", exc)
|
||||||
|
wireguard = set()
|
||||||
|
return {
|
||||||
|
"attributed": True,
|
||||||
|
"sockets": parse_socket_statistics(statistics, services, wireguard),
|
||||||
|
}
|
||||||
|
|
||||||
def manage_service(self, name: str, action: str) -> dict[str, Any]:
|
def manage_service(self, name: str, action: str) -> dict[str, Any]:
|
||||||
"""Execute a lifecycle action on an OPNsense service.
|
"""Execute a lifecycle action on an OPNsense service.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,935 @@
|
|||||||
|
{
|
||||||
|
"statistics": {
|
||||||
|
"Active Internet connections": {
|
||||||
|
"tcp4/[192.0.2.1:443-192.0.2.50:38544]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "443",
|
||||||
|
"0": "192.0.2.1:443"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "192.0.2.50",
|
||||||
|
"port": "38544",
|
||||||
|
"0": "192.0.2.50:38544"
|
||||||
|
},
|
||||||
|
"receive-high-water": 65700,
|
||||||
|
"send-high-water": 65700,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 525600,
|
||||||
|
"send-mbuf-bytes-max": 525600,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "7199.77",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "0.02",
|
||||||
|
"flow-id": "f6ae054e",
|
||||||
|
"flow-type": 130,
|
||||||
|
"user": "root",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "46564",
|
||||||
|
"fd": "19",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[192.0.2.1:443-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "443",
|
||||||
|
"0": "192.0.2.1:443"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "33552.00",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "46564",
|
||||||
|
"fd": "11",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[198.51.100.1:443-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "198.51.100.1",
|
||||||
|
"port": "443",
|
||||||
|
"0": "198.51.100.1:443"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "33552.00",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "46564",
|
||||||
|
"fd": "10",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[127.0.0.1:443-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": "443",
|
||||||
|
"0": "127.0.0.1:443"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "33552.00",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "46564",
|
||||||
|
"fd": "7",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[192.0.2.1:80-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "80",
|
||||||
|
"0": "192.0.2.1:80"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "33552.00",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "46564",
|
||||||
|
"fd": "16",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[*:8000-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "8000",
|
||||||
|
"0": "*:8000"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41043.28",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "www",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "7612",
|
||||||
|
"fd": "7",
|
||||||
|
"proto": "tcp4",
|
||||||
|
"listen-queue-sizes": {
|
||||||
|
"qlen": "0",
|
||||||
|
"incqlen": "0",
|
||||||
|
"maxqlen": "128"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tcp6/[*:8000-*:*]": {
|
||||||
|
"protocol": "tcp6",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "8000",
|
||||||
|
"0": "*:8000"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41043.28",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "www",
|
||||||
|
"command": "lighttpd",
|
||||||
|
"pid": "7612",
|
||||||
|
"fd": "4",
|
||||||
|
"proto": "tcp6",
|
||||||
|
"listen-queue-sizes": {
|
||||||
|
"qlen": "0",
|
||||||
|
"incqlen": "0",
|
||||||
|
"maxqlen": "128"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tcp4/[192.0.2.1:8080-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "8080",
|
||||||
|
"0": "192.0.2.1:8080"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "21096.55",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "crowdsec",
|
||||||
|
"pid": "90423",
|
||||||
|
"fd": "26",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[127.0.0.1:6060-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": "6060",
|
||||||
|
"0": "127.0.0.1:6060"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41044.32",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "crowdsec",
|
||||||
|
"pid": "90423",
|
||||||
|
"fd": "20",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[192.0.2.1:10050-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "10050",
|
||||||
|
"0": "192.0.2.1:10050"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41044.31",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "zabbix",
|
||||||
|
"command": "zabbix_age",
|
||||||
|
"pid": "70051",
|
||||||
|
"fd": "5",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[192.0.2.1:22-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "22",
|
||||||
|
"0": "192.0.2.1:22"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41054.14",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "sshd",
|
||||||
|
"pid": "12554",
|
||||||
|
"fd": "6",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[127.0.0.1:22-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": "22",
|
||||||
|
"0": "127.0.0.1:22"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41054.14",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "sshd",
|
||||||
|
"pid": "12554",
|
||||||
|
"fd": "11",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[203.0.113.1:53-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "203.0.113.1",
|
||||||
|
"port": "53",
|
||||||
|
"0": "203.0.113.1:53"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "9830.17",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "unbound",
|
||||||
|
"command": "unbound",
|
||||||
|
"pid": "10992",
|
||||||
|
"fd": "116",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[127.0.0.1:953-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": "953",
|
||||||
|
"0": "127.0.0.1:953"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "9830.17",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "unbound",
|
||||||
|
"command": "unbound",
|
||||||
|
"pid": "10992",
|
||||||
|
"fd": "117",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[127.0.0.1:8000-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": "8000",
|
||||||
|
"0": "127.0.0.1:8000"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "10006.15",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "kea-ctrl-a",
|
||||||
|
"pid": "14979",
|
||||||
|
"fd": "7",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"tcp4/[127.0.0.1:2604-*:*]": {
|
||||||
|
"protocol": "tcp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "127.0.0.1",
|
||||||
|
"port": "2604",
|
||||||
|
"0": "127.0.0.1:2604"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 0,
|
||||||
|
"send-high-water": 0,
|
||||||
|
"receive-low-water": 0,
|
||||||
|
"send-low-water": 0,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 0,
|
||||||
|
"send-mbuf-bytes-max": 0,
|
||||||
|
"retransmit-timer": "0.00",
|
||||||
|
"persist-timer": "0.00",
|
||||||
|
"keepalive-timer": "0.00",
|
||||||
|
"msl2-timer": "0.00",
|
||||||
|
"delay-ack-timer": "0.00",
|
||||||
|
"inactivity-timer": "41047.92",
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "frr",
|
||||||
|
"command": "ospfd",
|
||||||
|
"pid": "89416",
|
||||||
|
"fd": "11",
|
||||||
|
"proto": "tcp4"
|
||||||
|
},
|
||||||
|
"udp4/[203.0.113.1:53-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "203.0.113.1",
|
||||||
|
"port": "53",
|
||||||
|
"0": "203.0.113.1:53"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "b8a211",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "unbound",
|
||||||
|
"command": "unbound",
|
||||||
|
"pid": "10992",
|
||||||
|
"fd": "115",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp4/[192.0.2.1:67-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "67",
|
||||||
|
"0": "192.0.2.1:67"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "b899f5",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "root",
|
||||||
|
"command": "kea-dhcp4",
|
||||||
|
"pid": "12917",
|
||||||
|
"fd": "19",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp4/[*:123-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "123",
|
||||||
|
"0": "*:123"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "c23b49",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "root",
|
||||||
|
"command": "ntpd",
|
||||||
|
"pid": "69031",
|
||||||
|
"fd": "21",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp6/[*:123-*:*]": {
|
||||||
|
"protocol": "udp6",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "123",
|
||||||
|
"0": "*:123"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "root",
|
||||||
|
"command": "ntpd",
|
||||||
|
"pid": "69031",
|
||||||
|
"fd": "20",
|
||||||
|
"proto": "udp6"
|
||||||
|
},
|
||||||
|
"udp4/[198.51.100.1:5353-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 42052,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "198.51.100.1",
|
||||||
|
"port": "5353",
|
||||||
|
"0": "198.51.100.1:5353"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 321536,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "13f3",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "root",
|
||||||
|
"command": "mdns-repea",
|
||||||
|
"pid": "12222",
|
||||||
|
"fd": "10",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp4/[*:1900-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "1900",
|
||||||
|
"0": "*:1900"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "c27",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "root",
|
||||||
|
"command": "udpbroadca",
|
||||||
|
"pid": "78873",
|
||||||
|
"fd": "3",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp4/[192.0.2.1:161-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": "161",
|
||||||
|
"0": "192.0.2.1:161"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "130d",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "root",
|
||||||
|
"command": "snmpd",
|
||||||
|
"pid": "53743",
|
||||||
|
"fd": "8",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp4/[*:51821-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "51821",
|
||||||
|
"0": "*:51821"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "945",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "??",
|
||||||
|
"command": "??",
|
||||||
|
"pid": "??",
|
||||||
|
"fd": "??",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp6/[*:51821-*:*]": {
|
||||||
|
"protocol": "udp6",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "51821",
|
||||||
|
"0": "*:51821"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "0",
|
||||||
|
"flow-type": 0,
|
||||||
|
"user": "??",
|
||||||
|
"command": "??",
|
||||||
|
"pid": "??",
|
||||||
|
"fd": "??",
|
||||||
|
"proto": "udp6"
|
||||||
|
},
|
||||||
|
"udp4/[*:29281-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "29281",
|
||||||
|
"0": "*:29281"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "c23c01",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "??",
|
||||||
|
"command": "??",
|
||||||
|
"pid": "??",
|
||||||
|
"fd": "??",
|
||||||
|
"proto": "udp4"
|
||||||
|
},
|
||||||
|
"udp4/[*:*-*:*]": {
|
||||||
|
"protocol": "udp4",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"local": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"address": "*",
|
||||||
|
"port": "*",
|
||||||
|
"0": "*:*"
|
||||||
|
},
|
||||||
|
"receive-high-water": 42080,
|
||||||
|
"send-high-water": 57344,
|
||||||
|
"receive-low-water": 1,
|
||||||
|
"send-low-water": 2048,
|
||||||
|
"receive-mbuf-bytes": 0,
|
||||||
|
"send-mbuf-bytes": 0,
|
||||||
|
"receive-mbuf-bytes-max": 336640,
|
||||||
|
"send-mbuf-bytes-max": 458752,
|
||||||
|
"flow-id": "1441",
|
||||||
|
"flow-type": 63,
|
||||||
|
"user": "_lldpd",
|
||||||
|
"command": "lldpd",
|
||||||
|
"pid": "72768",
|
||||||
|
"fd": "6",
|
||||||
|
"proto": "udp4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Active UNIX domain sockets": {
|
||||||
|
"fffff80016c50c80 - /var/run/configd.socket": {
|
||||||
|
"address": "fffff80016c50c80",
|
||||||
|
"type": "stream",
|
||||||
|
"receive-bytes-waiting": 0,
|
||||||
|
"send-bytes-waiting": 0,
|
||||||
|
"vnode": "0",
|
||||||
|
"connection": "fffff8006e7b8640",
|
||||||
|
"first-reference": "0",
|
||||||
|
"next-reference": "0",
|
||||||
|
"path": "/var/run/configd.socket"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
"""What listens on an OPNsense firewall, and which OPNsense service it is (netOrk #673).
|
||||||
|
|
||||||
|
OPNsense answers through its API, ``diagnostics/interface/get_socket_statistics``:
|
||||||
|
netstat's sockets with sockstat's user, command and PID merged in, read by configd
|
||||||
|
as root. A socket that listens has no peer (``*:*``). Which service holds it comes
|
||||||
|
from the command -- cut to ten characters by FreeBSD -- matched against the
|
||||||
|
firewall's own service list; WireGuard's sockets belong to the kernel and are
|
||||||
|
told by their port.
|
||||||
|
|
||||||
|
The fixture is a real OPNsense 26.7.5 firewall's answer, cut down, with
|
||||||
|
documentation addresses.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from napalm_opnsense.opnsense import OPNsenseDriver
|
||||||
|
|
||||||
|
STATISTICS = json.loads((Path(__file__).parent / "fixtures" / "socket_statistics.json").read_text())
|
||||||
|
SERVICES = [
|
||||||
|
"acme", "captiveportal", "configd", "cron", "crowdsec", "frr", "kea-dhcp", "lldpd",
|
||||||
|
"login", "mdns-repeater", "ntpd", "openssh", "pf", "snmpd", "udpbroadcastrelay",
|
||||||
|
"unbound", "webgui", "wireguard", "zabbix_agentd",
|
||||||
|
] # fmt: skip
|
||||||
|
WIREGUARD = {
|
||||||
|
"rows": [
|
||||||
|
{"if": "wg1", "type": "interface", "listen-port": "51821", "status": "up"},
|
||||||
|
{"if": "wg1", "type": "peer", "allowed-ips": "10.99.99.2/32"},
|
||||||
|
{"if": "wg2", "type": "interface", "listen-port": "29281", "status": "up"},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _driver(services=SERVICES, wireguard=WIREGUARD) -> OPNsenseDriver:
|
||||||
|
with patch("napalm_opnsense.opnsense.requests.Session"):
|
||||||
|
drv = OPNsenseDriver(hostname="fw", username="k", password="s")
|
||||||
|
drv.session = MagicMock()
|
||||||
|
|
||||||
|
def get(path: str) -> dict:
|
||||||
|
if path == "/api/diagnostics/interface/get_socket_statistics":
|
||||||
|
return STATISTICS
|
||||||
|
if path == "/api/core/service/search":
|
||||||
|
return {"rows": [{"id": n, "name": n, "running": 1} for n in services]}
|
||||||
|
if path == "/api/wireguard/service/show":
|
||||||
|
if isinstance(wireguard, Exception):
|
||||||
|
raise wireguard
|
||||||
|
return wireguard
|
||||||
|
raise AssertionError(f"unexpected GET {path}")
|
||||||
|
|
||||||
|
drv._get = get # type: ignore[method-assign]
|
||||||
|
return drv
|
||||||
|
|
||||||
|
|
||||||
|
def _sockets(drv: OPNsenseDriver | None = None) -> dict:
|
||||||
|
reading = (drv or _driver()).get_listening_sockets()
|
||||||
|
return {(s["proto"], s["port"], s["address"]): s for s in reading["sockets"]}
|
||||||
|
|
||||||
|
|
||||||
|
class TestTheReading:
|
||||||
|
def test_read_as_root(self):
|
||||||
|
assert _driver().get_listening_sockets()["attributed"] is True
|
||||||
|
|
||||||
|
def test_a_socket_comes_with_its_process_and_service(self):
|
||||||
|
assert _sockets()[("tcp", 8080, "192.0.2.1")] == {
|
||||||
|
"proto": "tcp",
|
||||||
|
"address": "192.0.2.1",
|
||||||
|
"port": 8080,
|
||||||
|
"interface": None,
|
||||||
|
"process": "crowdsec",
|
||||||
|
"pid": 90423,
|
||||||
|
"unit": "crowdsec",
|
||||||
|
"container_id": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_only_what_listens(self):
|
||||||
|
"""A connection has a peer; a socket without a port listens on nothing."""
|
||||||
|
sockets = _driver().get_listening_sockets()["sockets"]
|
||||||
|
|
||||||
|
assert len(sockets) == 25
|
||||||
|
assert all(s["port"] > 0 for s in sockets)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"proto, port, address",
|
||||||
|
[
|
||||||
|
("tcp", 8000, "0.0.0.0"),
|
||||||
|
("tcp", 8000, "::"),
|
||||||
|
("udp", 123, "0.0.0.0"),
|
||||||
|
("udp", 123, "::"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_every_address_of_a_family_is_its_any_address(self, proto, port, address):
|
||||||
|
assert (proto, port, address) in _sockets()
|
||||||
|
|
||||||
|
def test_sorted_by_protocol_port_and_address(self):
|
||||||
|
sockets = _driver().get_listening_sockets()["sockets"]
|
||||||
|
keys = [(s["proto"], s["port"], s["address"]) for s in sockets]
|
||||||
|
|
||||||
|
assert keys == sorted(keys)
|
||||||
|
|
||||||
|
|
||||||
|
class TestWhichService:
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"proto, port, address, service",
|
||||||
|
[
|
||||||
|
("tcp", 22, "192.0.2.1", "openssh"),
|
||||||
|
("tcp", 443, "192.0.2.1", "webgui"),
|
||||||
|
("tcp", 8000, "0.0.0.0", "captiveportal"), # lighttpd as www
|
||||||
|
("udp", 67, "192.0.2.1", "kea-dhcp"), # kea-dhcp4
|
||||||
|
("tcp", 8000, "127.0.0.1", "kea-dhcp"), # kea-ctrl-agent, cut short
|
||||||
|
("tcp", 2604, "127.0.0.1", "frr"), # ospfd
|
||||||
|
("udp", 5353, "198.51.100.1", "mdns-repeater"), # cut short
|
||||||
|
("udp", 1900, "0.0.0.0", "udpbroadcastrelay"),
|
||||||
|
("tcp", 10050, "192.0.2.1", "zabbix_agentd"),
|
||||||
|
("udp", 53, "203.0.113.1", "unbound"),
|
||||||
|
("udp", 123, "0.0.0.0", "ntpd"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_by_its_command(self, proto, port, address, service):
|
||||||
|
assert _sockets()[(proto, port, address)]["unit"] == service
|
||||||
|
|
||||||
|
def test_the_command_stays_as_reported(self):
|
||||||
|
assert _sockets()[("udp", 5353, "198.51.100.1")]["process"] == "mdns-repea"
|
||||||
|
|
||||||
|
def test_a_service_the_firewall_does_not_list_is_none(self):
|
||||||
|
without_snmpd = [n for n in SERVICES if n != "snmpd"]
|
||||||
|
|
||||||
|
assert _sockets(_driver(services=without_snmpd))[("udp", 161, "192.0.2.1")]["unit"] is None
|
||||||
|
|
||||||
|
def test_wireguard_s_kernel_sockets_by_their_port(self):
|
||||||
|
wg = _sockets()[("udp", 51821, "0.0.0.0")]
|
||||||
|
|
||||||
|
assert (wg["process"], wg["pid"], wg["unit"]) == (None, None, "wireguard")
|
||||||
|
|
||||||
|
def test_without_wireguard_a_kernel_socket_is_nobody_s(self):
|
||||||
|
sockets = _sockets(_driver(wireguard=RuntimeError("404")))
|
||||||
|
|
||||||
|
assert sockets[("udp", 29281, "0.0.0.0")]["unit"] is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_netork_finds_it():
|
||||||
|
"""netOrk asks ``hasattr(driver, "get_listening_sockets")``."""
|
||||||
|
assert hasattr(OPNsenseDriver, "get_listening_sockets")
|
||||||
Reference in New Issue
Block a user