fix(server): ignore datagrams that are not named HTB/PLG messages
A scanner's SIP INVITE on the public UDP port was parsed as a message without a name and signed on a host called "unknown". Non-client datagrams are still journaled but no longer create hosts or get an ACK. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
+7
-1
@@ -422,6 +422,12 @@ def handle_datagram(msg: dict, addr, transport, ctx: dict):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Failed to log message to journal: {e}")
|
logger.debug(f"Failed to log message to journal: {e}")
|
||||||
|
|
||||||
|
# Only named HTB/PLG datagrams come from clients; anything else (e.g. an internet scanner's
|
||||||
|
# SIP probe) is journaled above but must not sign on a host.
|
||||||
|
if msg.get("ID") not in ("HTB", "PLG") or not msg.get("name"):
|
||||||
|
logger.debug("Ignoring non-client datagram from %s", addr)
|
||||||
|
return
|
||||||
|
|
||||||
cfg = ctx.get("config", {})
|
cfg = ctx.get("config", {})
|
||||||
hbdcls = ctx.get("hbdclass")
|
hbdcls = ctx.get("hbdclass")
|
||||||
msg_to_websockets = ctx.get("msg_to_websockets")
|
msg_to_websockets = ctx.get("msg_to_websockets")
|
||||||
@@ -430,7 +436,7 @@ def handle_datagram(msg: dict, addr, transport, ctx: dict):
|
|||||||
|
|
||||||
# normalize addr (ip, port)
|
# normalize addr (ip, port)
|
||||||
ip = addr[0] if isinstance(addr, (list, tuple)) else addr
|
ip = addr[0] if isinstance(addr, (list, tuple)) else addr
|
||||||
name = msg.get("name", "unknown")
|
name = msg["name"]
|
||||||
from ..common.utils import shortname
|
from ..common.utils import shortname
|
||||||
from . import config as config_mod
|
from . import config as config_mod
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
"""Datagrams that are not heartbeat traffic (internet scanners) must not create hosts."""
|
||||||
|
from hbd.common.proto import dicttos
|
||||||
|
from hbd.server import hbdclass
|
||||||
|
from hbd.server.udp import handle_datagram, parse_message
|
||||||
|
|
||||||
|
|
||||||
|
class _FakeTransport:
|
||||||
|
sent = 0
|
||||||
|
|
||||||
|
def sendto(self, data, addr):
|
||||||
|
_FakeTransport.sent += 1
|
||||||
|
|
||||||
|
|
||||||
|
def _ctx():
|
||||||
|
return {"config": {}, "hbdclass": hbdclass, "msg_to_websockets": None,
|
||||||
|
"DEBUG": 0, "verbose": False}
|
||||||
|
|
||||||
|
|
||||||
|
def _handle(raw):
|
||||||
|
handle_datagram(parse_message(raw), ("192.0.2.9", 50000), _FakeTransport(), _ctx())
|
||||||
|
|
||||||
|
|
||||||
|
def test_sip_invite_does_not_create_a_host():
|
||||||
|
hbdclass.Host.hosts.pop("unknown", None)
|
||||||
|
_handle(b"INVITE sip:10000@192.0.2.1:50003 SIP/2.0\r\nTo: <sip:10000@192.0.2.1>\r\n\r\n")
|
||||||
|
assert "unknown" not in hbdclass.Host.hosts
|
||||||
|
|
||||||
|
|
||||||
|
def test_nameless_heartbeat_does_not_create_a_host_or_get_acked():
|
||||||
|
hbdclass.Host.hosts.pop("unknown", None)
|
||||||
|
_FakeTransport.sent = 0
|
||||||
|
_handle(dicttos("HTB", {"id": 0}))
|
||||||
|
assert "unknown" not in hbdclass.Host.hosts
|
||||||
|
assert _FakeTransport.sent == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_named_heartbeat_still_creates_its_host():
|
||||||
|
hbdclass.Host.hosts.pop("stray-ok", None)
|
||||||
|
_handle(dicttos("HTB", {"name": "stray-ok", "id": 0}))
|
||||||
|
assert "stray-ok" in hbdclass.Host.hosts
|
||||||
Reference in New Issue
Block a user