feat: report what listens, and which OPNsense service it is
CI / test (3.10) (push) Successful in 40s
CI / test (3.11) (push) Successful in 30s
CI / test (3.12) (push) Successful in 31s
CI / test (3.10) (pull_request) Successful in 29s
CI / test (3.11) (pull_request) Successful in 28s
CI / test (3.12) (pull_request) Successful in 30s
CI / test (3.10) (push) Successful in 40s
CI / test (3.11) (push) Successful in 30s
CI / test (3.12) (push) Successful in 31s
CI / test (3.10) (pull_request) Successful in 29s
CI / test (3.11) (pull_request) Successful in 28s
CI / test (3.12) (pull_request) Successful in 30s
get_listening_sockets reads /api/diagnostics/interface/get_socket_statistics: netstat's sockets with sockstat's user, command and PID, collected by configd as root, so no SSH is needed. A listening socket is one without a peer (*:*); "*" is the any-address of the socket's family. Which service: the socket's unit is a name of the firewall's own service list, so netOrk can match it to the service. The command (cut to ten characters by FreeBSD) matches a service name, the start of one, or one of the daemons whose service is called otherwise (sshd is openssh, the FRR daemons are frr, kea-ctrl-agent is kea-dhcp). lighttpd is the web UI, or the captive portal when it runs as www. WireGuard's sockets belong to the kernel and are told by the listen ports of /api/wireguard/service/show. The fixture is a real OPNsense 26.7.5 firewall's answer, cut down, with documentation addresses. For netOrk#673.
This commit is contained in:
@@ -53,8 +53,10 @@ import requests
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
from napalm_device_types import FingerprintRule, FirewallDriver
|
||||
from napalm_device_types.models import ListeningSocketsDict
|
||||
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.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())
|
||||
|
||||
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]:
|
||||
"""Execute a lifecycle action on an OPNsense service.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user