Skip to content

Replace PORT_SERVICE_MAP with IANA service-names database for network graph node classification #154

@NotYuSheng

Description

@NotYuSheng

Problem

frontend/src/features/network/services/networkService.ts contains a hardcoded PORT_SERVICE_MAP with 27 entries mapping "port/PROTOCOL" strings to semantic NodeType values (dns-server, web-server, ssh-server, etc.). This approach has two fundamental limitations:

  1. Services on non-standard ports (e.g. HTTPS on 8444, SSH on 2222) are never classified correctly.
  2. Encrypted flows (TLS/QUIC) carrying web traffic over arbitrary ports are classified as unknown.

Additionally, NodeDetails.tsx has a parallel NODE_TYPE_DISPLAY map (11 entries) and constants.ts has NODE_TYPE_COLORS (11 entries) — three maps covering the same NodeType values that must be kept in sync manually.

Research findings

Surveyed npm packages (port-numbers, services-db, service-names-port-numbers) all map port numbers to IANA service names (e.g. "https", "domain") — not to the application-semantic NodeType labels the graph needs. A mapping layer from IANA name to NodeType would still be required, so no package removes the custom logic.

Better alternative: use nDPI appName as the primary signal. The appName field is already populated per-conversation by the backend nDPI service and is available on every Conversation in the graph. nDPI identifies:

  • TLS/QUIC → "TLS" / "QUIC" (web traffic on any port)
  • "DNS", "SSH", "FTP_CONTROL", "SMTP", "IMAP", "POP", "DHCP", "NTP"
  • "MySQL", "PostgreSQL", "Redis", "MongoDB", "Elasticsearch"

This is more accurate than port-based guessing, especially for encrypted flows.

Proposed Solution

1. Add nDPI app name → NodeType lookup as primary classifier

Add a NDPI_APP_MAP alongside PORT_SERVICE_MAP. In buildNetworkGraph, accumulate the set of distinct appName values seen on inbound edges to each node. In classifyNodeType, try NDPI_APP_MAP first, then fall back to PORT_SERVICE_MAP (for captures where nDPI / ndpiReader is unavailable and appName is null).

const NDPI_APP_MAP: Partial<Record<string, NodeType>> = {
  'DNS':          'dns-server',
  'HTTP':         'web-server',
  'TLS':          'web-server',
  'QUIC':         'web-server',
  'SSH':          'ssh-server',
  'FTP_CONTROL':  'ftp-server',
  'FTP_DATA':     'ftp-server',
  'SMTP':         'mail-server',
  'SMTPTLS':      'mail-server',
  'IMAP':         'mail-server',
  'POP':          'mail-server',
  'DHCP':         'dhcp-server',
  'NTP':          'ntp-server',
  'MySQL':        'database-server',
  'PostgreSQL':   'database-server',
  'Redis':        'database-server',
  'MongoDB':      'database-server',
  'Elasticsearch':'database-server',
};

2. Consolidate the three parallel node-type maps

PORT_SERVICE_MAP, NODE_TYPE_COLORS, and NODE_TYPE_DISPLAY all key on NodeType. Replace with a single NODE_TYPE_CONFIG object:

export const NODE_TYPE_CONFIG: Record<NodeType, {
  label: string;
  icon: string;
  badgeClass: string;
  color: string;
}> = {
  'dns-server':      { label: 'DNS Server',      icon: 'bi-globe2',          badgeClass: 'bg-warning text-dark', color: '#f39c12' },
  'web-server':      { label: 'Web Server',       icon: 'bi-server',          badgeClass: 'bg-success',           color: '#2ecc71' },
  'ssh-server':      { label: 'SSH Server',       icon: 'bi-terminal',        badgeClass: 'bg-info text-dark',    color: '#1abc9c' },
  // ...all 11 types
};

This means adding a new node type requires touching exactly one place.

Files to Change

  • frontend/src/features/network/services/networkService.ts
  • frontend/src/features/network/constants.ts
  • frontend/src/components/network/NodeDetails/NodeDetails.tsx

Acceptance Criteria

  • PORT_SERVICE_MAP kept as a port-based fallback; NDPI_APP_MAP added as primary classifier
  • nDPI appName values accumulated per graph node during buildNetworkGraph
  • Node classification correctly identifies services on non-standard ports when nDPI appName is available
  • NODE_TYPE_COLORS and NODE_TYPE_DISPLAY merged into a single NODE_TYPE_CONFIG
  • All existing port→node-type mappings continue to work when appName is null

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions