Sniffer distributed architecture: Difference between revisions

From VoIPmonitor.org
(Fix mismatched heading level)
(Add HEP Protocol in Client/Server Mode documentation)
 
(45 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{DISPLAYTITLE:Distributed Architecture: Client-Server and Mirroring Modes}}
{{DISPLAYTITLE:Distributed Architecture: Client-Server Mode}}


This guide covers deploying multiple VoIPmonitor sensors in a distributed architecture using Client-Server mode (v20+).


=Distributed Architecture: Client-Server and Mirroring Modes=
For deployment options including on-host vs dedicated sensors and traffic forwarding methods (SPAN, GRE, TZSP, VXLAN), see [[Sniffing_modes|VoIPmonitor Deployment & Topology Guide]].


This guide explains how to deploy VoIPmonitor in distributed architectures using client-server mode, packet mirroring, and hybrid configurations.
= Overview =


==Overview==
VoIPmonitor v20+ uses '''Client-Server architecture''' for distributed deployments. Remote sensors connect to a central server via encrypted TCP (default port 60024, zstd compression).


VoIPmonitor sniffers can be deployed in multiple architectural patterns:
{| class="wikitable"
|-
! Mode !! <code>packetbuffer_sender</code> !! What is Sent !! Processing Location !! Use Case
|-
| '''Local Processing''' || <code>no</code> (default) || CDRs only || Remote sensor || Multi-site, low bandwidth
|-
| '''Packet Mirroring''' || <code>yes</code> || Raw packets || Central server || Centralized analysis, low-resource remotes
|}


* '''Standalone mode''': Single instance capturing and analyzing traffic
<kroki lang="plantuml">
* '''Client-Server mode''': Multiple clients sending CDRs to central server
@startuml
* '''Mirroring mode''': Forwarding raw packets to another instance
skinparam shadowing false
* '''Hybrid mode''': Combining mirroring with client-server (workaround)
skinparam defaultFontName Arial
skinparam rectangle {
  BorderColor #4A90E2
  BackgroundColor #FFFFFF
}


==== Architecture Diagrams (PlantUML) ====
rectangle "Remote Sensor A" as A
rectangle "Remote Sensor B" as B
rectangle "Central Server\n(server_bind)" as S
database "MySQL" as DB


<kroki lang="plantuml">
A -down-> S : encrypted TCP/60024\n(zstd compressed)
  @startuml
B -down-> S : encrypted TCP/60024\n(zstd compressed)
  skinparam shadowing false
S -right-> DB : CDRs
  skinparam defaultFontName Arial
  skinparam rectangle {
    BorderColor #4A90E2
    BackgroundColor #FFFFFF
    stereotypeFontColor #333333
  }


   title Multiple Clients Single Server (Client-Server Mode)
note bottom of S
   packetbuffer_sender=no receives CDRs
  packetbuffer_sender=yes → receives raw packets
end note
@enduml
</kroki>


  rectangle "Sensor A\n(client)" as A
== Use Cases ==
  rectangle "Sensor B\n(client)" as B
  rectangle "Sensor C\n(client)" as C
  rectangle "Central Server\n(server_bind)" as S


  A --> S : CDRs
'''AWS VPC Traffic Mirroring Alternative:'''
  B --> S : CDRs
If experiencing packet loss with AWS VPC Traffic Mirroring (VXLAN overhead, MTU fragmentation), use client-server mode instead:
  C --> S : CDRs
* Install VoIPmonitor on each source EC2 instance
* Send via encrypted TCP to central server
* Eliminates VXLAN encapsulation and MTU issues


  note right of S
= Configuration =
    Stores all CDRs to MySQL
    PCAPs remain on sensors by default
  end note


  @enduml
== Remote Sensor (Client) ==
</kroki>


<kroki lang="plantuml">
<syntaxhighlight lang="ini">
   @startuml
id_sensor              = 2                    # Unique per sensor (1-65535)
  skinparam shadowing false
server_destination      = central.server.ip
  skinparam defaultFontName Arial
server_destination_port = 60024
server_password        = your_strong_password
 
# Choose mode:
packetbuffer_sender    = no    # Local Processing: analyze locally, send CDRs
# packetbuffer_sender   = yes    # Packet Mirroring: send raw packets
 
interface              = eth0
sipport                = 5060
# No MySQL credentials needed on remote sensors
</syntaxhighlight>
 
{{Tip|1=For HA setups with floating IPs, use <code>manager_ip = 10.0.0.5</code> to bind outgoing connections to a static IP address.}}
 
== Central Server ==


  title Packet Mirroring (Sensor A → Sensor B)
<syntaxhighlight lang="ini">
server_bind            = 0.0.0.0
server_bind_port        = 60024
server_password        = your_strong_password


  rectangle "Sensor A\n(source capture)" as A
mysqlhost              = localhost
  rectangle "Sensor B\n(receiver / analysis)" as B
mysqldb                = voipmonitor
mysqluser              = voipmonitor
mysqlpassword          = db_password


  A -[#black]-> B : mirrored packets\n(SIP, RTP, TCP, TLS)
# If receiving raw packets (packetbuffer_sender=yes on clients):
sipport                = 5060
savertp                = yes
savesip                = yes
</syntaxhighlight>


  note right of B
{{Warning|1='''Critical:''' Exclude <code>server_bind_port</code> from <code>sipport</code> on the central server. Including it causes continuously increasing memory usage.
    Analyzes mirrored traffic
<syntaxhighlight lang="ini">
    Can store CDRs and PCAPs
# WRONG - includes sensor communication port:
  end note
sipport = 1-65535


  @enduml
# CORRECT - excludes port 60024:
</kroki>
sipport = 1-60023,60025-65535
</syntaxhighlight>}}


<kroki lang="plantuml">
== Key Configuration Rules ==
  @startuml
  skinparam shadowing false
  skinparam defaultFontName Arial


  title Hybrid Chain (Mirror + Client)
{| class="wikitable"
|-
! Rule !! Applies To !! Why
|-
| <code>server_bind_port</code> must match <code>server_destination_port</code> || Both || Connection fails if mismatched
|-
| <code>sipport</code> must match on probe and central server || Packet Mirroring || Missing ports = missing calls
|-
| <code>natalias</code> only on central server || Packet Mirroring || Prevents RTP correlation issues
|-
| Each sensor needs unique <code>id_sensor</code> || All || Required for identification
|}


  rectangle "Sensor A\nmirror_destination" as A
= Local Processing vs Packet Mirroring =
  rectangle "Sensor B\nmirror_bind +\nserver_destination" as B
  rectangle "Central Server C\nserver_bind" as C


  A -[#black]-> B : mirrored packets
{| class="wikitable"
  B -[#black]-> C : CDRs and/or packets
|-
! !! Local Processing !! Packet Mirroring
|-
| '''<code>packetbuffer_sender</code>''' || <code>no</code> (default) || <code>yes</code>
|-
| '''Processing location''' || Remote sensor || Central server
|-
| '''PCAP storage''' || Remote sensor || Central server
|-
| '''WAN bandwidth''' || Low (CDRs only, 1Gb sufficient) || High (full packets)
|-
| '''Remote CPU load''' || Higher || Minimal
|-
| '''Capture rules applied''' || On sensor || On central server only
|}


  note right of B
== PCAP Access in Local Processing Mode ==
    Workaround only
    Not officially supported
  end note


  @enduml
PCAPs are stored on remote sensors. The GUI retrieves them through the central server, which proxies the request to the sensor '''over the existing TCP/60024 connection''' - the same persistent encrypted channel the sensor uses for sending CDRs. This connection is bidirectional; the central server does not open any separate connection back to the sensor.
</kroki>


==Standard Architectures==
'''Firewall requirements:'''


===Multiple Clients to Single Server (Recommended)===
{| class="wikitable"
|-
! Direction !! Port !! Purpose
|-
| Remote sensors → Central server || TCP/60024 || Persistent encrypted channel (CDRs from sensor, PCAP requests from server - bidirectional)
|-
| GUI → Central server || TCP/5029 || Manager API (sensor status, active calls, configuration)
|-
| GUI → Central server || TCP/60024 || Server API (list connected sensors, proxy PCAP retrieval)
|}


This is the standard and fully supported architecture for distributed deployments.
{{Note|1=The central server does '''not''' initiate connections to remote sensors. All server↔sensor communication happens over the single TCP/60024 connection that the sensor established.}}


<kroki lang="plantuml">
{{Tip|1=Packet Mirroring (<code>packetbuffer_sender=yes</code>) '''automatically deduplicates calls''' - the central server merges packets from all probes for the same Call-ID into a single unified CDR. This also ensures one logical call only consumes one license channel.}}
  @startuml
= Advanced Topics =
  title Multiple Clients → Single Server
  rectangle "Sensor A\n(client)" as A
  rectangle "Sensor B\n(client)" as B
  rectangle "Sensor C\n(client)" as C
  rectangle "Central Server\n(server_bind)" as S


  A --> S : CDRs
== High Availability (Failover) ==
  B --> S : CDRs
  C --> S : CDRs
  @enduml
</kroki>


'''Configuration:'''
Remote sensors can specify multiple central servers:


On each client (A, B, C):
<syntaxhighlight lang="ini">
<syntaxhighlight lang="bash">
server_destination = 192.168.0.1, 192.168.0.2
server_destination = central.server.ip
server_destination_port = 60024
server_password = shared_secret
</syntaxhighlight>
</syntaxhighlight>


On central server:
If primary is unavailable, the sensor automatically connects to the next server.
<syntaxhighlight lang="bash">
 
server_bind = 0.0.0.0
== Connection Compression ==
server_bind_port = 60024
 
server_password = shared_secret
<syntaxhighlight lang="ini">
# On both client and server (default: zstd)
server_type_compress = zstd  # Options: zstd, gzip, lzo, none
</syntaxhighlight>
</syntaxhighlight>


'''Important notes:'''
== Intermediate Server (Hub-and-Spoke) ==
* All clients and the server must use the same <code>server_password</code>
* Clients do not store CDRs to MySQL (they only send to server)
* Server stores all CDRs to MySQL database
* PCAP files are stored on clients by default


===Packet Mirroring===
An intermediate server can receive from multiple sensors and forward to a central server:


Mirror mode forwards raw network packets from one sniffer to another.
<kroki lang="plantuml">
@startuml
skinparam shadowing false
skinparam defaultFontName Arial


<syntaxhighlight>
rectangle "Remote Sensors" as RS
Sensor A ──(packets)──→ Sensor B
rectangle "Intermediate Server" as INT
rectangle "Central Server" as CS
database "MySQL" as DB
 
RS --> INT : TCP/60024
INT --> CS : TCP/60024
CS --> DB
@enduml
</kroki>
 
<syntaxhighlight lang="ini">
# On INTERMEDIATE SERVER
id_sensor              = 100
 
# Receive from remote sensors
server_bind            = 0.0.0.0
server_bind_port        = 60024
server_password        = sensor_password
 
# Forward to central server
server_destination      = central.server.ip
server_destination_port = 60024
 
packetbuffer_sender    = no    # or yes, depending on desired mode
</syntaxhighlight>
</syntaxhighlight>


<kroki lang="plantuml">
{{Note|1=This works because the intermediate server does NOT do local packet capture - it only relays. Original remote sensors must be manually added to GUI Settings for visibility.}}
  @startuml
 
  title Packet Mirroring (A → B)
== Multiple Receivers for Packet Mirroring ==
  rectangle "Sensor A\n(source)" as A
  rectangle "Sensor B\n(receiver)" as B


  A --> B : mirrored packets
{{Warning|1=Multiple sensors with <code>packetbuffer_sender=yes</code> sending to a '''single receiver instance''' can cause call processing conflicts (calls appear in Active Calls but missing from CDRs).}}
  @enduml
</kroki>


'''Configuration:'''
'''Solution:''' Run separate receiver instances on different hosts, each dedicated to specific sensors:


On source sensor A:
<syntaxhighlight lang="ini">
<syntaxhighlight lang="bash">
# Receiver Instance 1 (Host 1, for Sensor A)
mirror_destination = sensor.b.ip
server_bind_port        = 60024
mirror_destination_port = 5090
id_sensor              = 1
</syntaxhighlight>


On receiving sensor B:
# Receiver Instance 2 (Host 2, for Sensor B)
<syntaxhighlight lang="bash">
server_bind_port        = 60024
mirror_bind = 0.0.0.0
id_sensor              = 2
mirror_bind_port = 5090
</syntaxhighlight>
</syntaxhighlight>


'''Use cases:'''
Alternative: Use '''Local Processing mode''' (<code>packetbuffer_sender=no</code>) which processes calls independently on each sensor.
* Forwarding packets from appliances without VoIPmonitor
* Port mirroring / SPAN to VoIPmonitor instance
* Distributed packet capture with central analysis


===Forwarding from SIP Probe to Central Server===
== Preventing Duplicate CDRs (Local Processing) ==


This pattern is used when SIP signaling and RTP media are captured on separate machines. A SIP-only probe captures SIP packets and forwards them to a central server where RTP packets are also captured, allowing complete CDR generation.
When multiple probes capture the same call in Local Processing mode:


<syntaxhighlight>
<syntaxhighlight lang="ini">
SIP Probe (only SIP) ──(SIP packets)──→ Central Server (SIP + RTP)
# On each probe
cdr_check_exists_callid = yes
</syntaxhighlight>
</syntaxhighlight>


<kroki lang="plantuml">
This checks for existing CDRs before inserting. Requires MySQL UPDATE privileges.
  @startuml
  title SIP Probe → Central Server


  rectangle "SIP Only Probe\n(packetbuffer_sender=yes)" as PROBE
== Critical: SIP and RTP Must Be Captured Together ==
  rectangle "Central Server\n(server_bind=yes)" as SERVER


  PROBE --> SERVER : SIP packets
VoIPmonitor cannot correlate SIP and RTP from different sniffer instances. A '''single sniffer must process both SIP and RTP''' for each call. Parameters like <code>cdr_check_exists_callid</code> do NOT enable split SIP/RTP correlation.


  note right of PROBE
    Captures SIP signaling only
    Forwards packets via server_destination
  end note


  note right of SERVER
    Receives SIP packets
    Captures RTP packets locally
    Merges SIP + RTP → Complete CDR
  end note
  @enduml
</kroki>


'''Use case:'''
==== Split SIP/RTP with Packet Mirroring Mode ====
* Environment where SIP servers and RTP engines are deployed on separate machines
* Need to merge SIP signaling from one location with RTP media from another


'''Configuration on SIP Probe (sending SIP packets):'''
{{Note|1='''Exception for Packet Mirroring Mode:''': The above limitation applies to '''Local Processing mode''' (<code>packetbuffer_sender=no</code>) where each sensor processes calls independently. In '''Packet Mirroring mode''' (<code>packetbuffer_sender=yes</code>), the central server receives raw packets from multiple remote sensors and processes them together. This allows scenarios where SIP and RTP are captured on separate nodes - configure both as packet senders and let the central server correlate them into single unified CDRs.}}


Edit <code>/etc/voipmonitor.conf</code>:
Example scenario: Separate SIP signaling node and RTP handling node:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="ini">
# Enable packet forwarding mode
# SIP Signaling Node (packet sender)
packetbuffer_sender = yes
id_sensor              = 1
packetbuffer_sender     = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password        = your_password


# Send to central server that will merge SIP with RTP
# RTP Handling Node (packet sender)
server_destination = central.server.ip
id_sensor              = 2
packetbuffer_sender    = yes
server_destination     = central.server.ip
server_destination_port = 60024
server_destination_port = 60024
server_password = shared_secret
server_password         = your_password
</syntaxhighlight>


# Do NOT set server_bind, mysqlhost, or other server options
The central server merges packets from both senders by Call-ID, creating unified CDRs with complete SIP and RTP data.
</syntaxhighlight>


'''Configuration on Central Server (receiving SIP, capturing RTP):'''


Edit <code>/etc/voipmonitor.conf</code>:
==== HEP Protocol in Client/Server Mode ====
<syntaxhighlight lang="bash">
# Accept incoming packets from probes
server_bind = 0.0.0.0
server_bind_port = 60024
server_password = shared_secret


# This server should also be capturing RTP locally
VoIPmonitor supports receiving HEP-encapsulated traffic on sniffer clients and forwarding it to a central server. This enables distributed capture from HEP sources (Kamailio, OpenSIPS, rtpproxy, FreeSWITCH) in a client/server architecture.
# Configure interface/port as usual
interface = eth0
# ... other standard configuration
</syntaxhighlight>


'''How it works:'''
'''Scenario:''' SIP proxy and RTP proxy at different locations sending HEP to remote sniffer clients:
# SIP probe captures SIP signaling packets only
# SIP probe forwards raw packets to central server via <code>server_destination</code>
# <code>packetbuffer_sender = yes</code> enables packet forwarding (instead of analyzing locally and sending CDRs)
# Central server receives SIP packets and merges them with locally captured RTP packets
# Central server generates complete CDRs with both signaling and media information


'''Restart services:'''
<syntaxhighlight lang="ini">
<syntaxhighlight lang="bash">
# Remote Sniffer Client A (receives HEP from Kamailio)
# On SIP probe
id_sensor              = 1
systemctl restart voipmonitor
hep                    = yes
hep_bind_port          = 9060
packetbuffer_sender    = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password        = your_password


# On central server
# Remote Sniffer Client B (receives HEP from rtpproxy)
systemctl restart voipmonitor
id_sensor              = 2
hep                    = yes
hep_bind_port          = 9060
packetbuffer_sender    = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password        = your_password
</syntaxhighlight>
</syntaxhighlight>


{{Note|This pattern uses <code>packetbuffer_sender</code> with <code>server_destination</code>/</code>server_bind</code> (client-server mode), which is different from <code>packetbuffer_sender</code> with </code>mirror_destination</code>/</code>mirror_bind</code> (mirror mode).}}
The central server receives packets from both clients and correlates them into unified CDRs using standard SIP Call-ID and IP:port from SDP.


==Hybrid Chain Configuration (Workaround)==
{{Note|1=This also works for IPFIX (Oracle SBCs) and RibbonSBC protocols forwarded via client/server mode.}}


{{Warning|A single sniffer instance '''cannot''' operate in both client and server modes simultaneously using <code>server_bind</code> + <code>server_destination</code>. These options are mutually exclusive.}}
'''Alternative: Direct HEP to single sniffer'''


However, a '''workaround exists''' using mirroring combined with client mode:
If both HEP sources can reach the same sniffer directly, no client/server setup is needed:


<syntaxhighlight>
<syntaxhighlight lang="ini">
A (mirror) ──(packets)──→ B (mirror_bind + server_destination) ──(CDRs/packets)──→ C (server)
# Single sniffer receiving HEP from multiple sources
hep                    = yes
hep_bind_port          = 9060
interface              = eth0  # Can also sniff locally if needed
</syntaxhighlight>
</syntaxhighlight>


<kroki lang="plantuml">
Both Kamailio (SIP) and rtpproxy (RTP) send HEP to this sniffer on port 9060. The sniffer correlates them automatically based on Call-ID and SDP IP:port.
  @startuml
= Sensor Health Monitoring =
  title Hybrid Chain A → B → C
  rectangle "Sensor A\n(mirror_destination)" as A
  rectangle "Sensor B\n(mirror_bind +\nserver_destination)" as B
  rectangle "Server C\n(server_bind)" as C


  A --> B : packets
== Management API ==
  B --> C : CDRs / packets
  @enduml
</kroki>


===Scenario 1: CDR Forwarding===
Query sensor status via TCP port 5029:


In this configuration, the intermediate sniffer (B) analyzes packets and forwards only CDRs to the central server.
'''Sensor A (source):'''
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
mirror_destination = sensor.b.ip
echo 'sniffer_stat' | nc <sensor_ip> 5029
mirror_destination_port = 5090
</syntaxhighlight>
</syntaxhighlight>


'''Sensor B (intermediate):'''
Returns JSON with status, version, active calls, packets per second, etc.
 
== Multi-Sensor Health Check Script ==
 
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
mirror_bind = 0.0.0.0
#!/bin/bash
mirror_bind_port = 5090
SENSORS=("192.168.1.10:5029" "192.168.1.11:5029")
server_destination = central.server.ip
for SENSOR in "${SENSORS[@]}"; do
server_destination_port = 60024
    IP=$(echo $SENSOR | cut -d: -f1)
packetbuffer_sender = no
    PORT=$(echo $SENSOR | cut -d: -f2)
    STATUS=$(echo 'sniffer_stat' | nc -w 2 $IP $PORT 2>/dev/null | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
    echo "$IP: ${STATUS:-FAILED}"
done
</syntaxhighlight>
</syntaxhighlight>


'''Central Server C:'''
= Version Compatibility =
<syntaxhighlight lang="bash">
 
server_bind = 0.0.0.0
{| class="wikitable"
server_bind_port = 60024
|-
! Scenario !! Compatibility !! Notes
|-
| '''GUI ≥ Sniffer''' || ✅ Compatible || Recommended
|-
| '''GUI < Sniffer''' || ⚠️ Risk || Sensor may write to non-existent columns
|}
 
'''Best practice:''' Upgrade GUI first (applies schema changes), then upgrade sensors.
 
For mixed versions temporarily, add to central server:
<syntaxhighlight lang="ini">
server_cp_store_simple_connect_response = yes  # Sniffer 2024.11.0+
</syntaxhighlight>
</syntaxhighlight>


'''Result:'''
= Troubleshooting =
* B analyzes packets from A
* B stores PCAP files locally
* B sends only CDRs to C
* C stores CDRs in MySQL and knows PCAPs are on B


===Scenario 2: Packet Forwarding===
== Quick Diagnosis ==


The intermediate sniffer forwards raw packets instead of CDRs.
{| class="wikitable"
|-
! Symptom !! First Check !! Likely Cause
|-
| Sensor not connecting || <code>journalctl -u voipmonitor -f</code> on sensor || Check <code>server_destination</code>, password, firewall
|-
| Traffic rate <code>[0.0Mb/s]</code> || tcpdump on sensor interface || Network/SPAN issue, not communication
|-
| High memory on central server || Check if <code>sipport</code> includes 60024 || Exclude server port from sipport
|-
| Missing calls || Compare <code>sipport</code> on probe vs central || Must match on both sides
|-
| "Bad password" error || GUI → Settings → Sensors || Delete stale sensor record, restart sensor
|-
| "Connection refused (111)" after migration || Check <code>server_destination</code> in config || Points to old server IP
|-
| RTP streams end prematurely || Check <code>natalias</code> location || Configure only on central server
|-
| Time sync errors || <code>timedatectl status</code> || Fix NTP or increase tolerance
|}
 
== Connection Testing ==


'''Sensor B (intermediate):'''
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
mirror_bind = 0.0.0.0
# Test connectivity from sensor to server
mirror_bind_port = 5090
nc -zv <server_ip> 60024
server_destination = central.server.ip
 
server_destination_port = 60024
# Verify server is listening
packetbuffer_sender = yes
ss -tulpn | grep voipmonitor
 
# Check sensor logs
journalctl -u voipmonitor -n 100 | grep -i "connect"
</syntaxhighlight>
</syntaxhighlight>


'''Result:'''
== Time Synchronization Errors ==
* B forwards raw packets from A+B to C
* C analyzes all packets and stores PCAP files
* C stores CDRs in MySQL


===Compression for Mirroring===
If seeing "different time between server and client" errors:


When using mirror mode, compression can reduce network bandwidth:
'''Immediate workaround:''' Increase tolerance on both sides:
<syntaxhighlight lang="ini">
client_server_connect_maximum_time_diff_s = 30
receive_packetbuffer_maximum_time_diff_s = 30
</syntaxhighlight>


'''Root cause fix:''' Ensure NTP is working:
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
packetbuffer_compress = yes
timedatectl status          # Check sync status
packetbuffer_compress_ratio = 100
chronyc tracking            # Check offset (Chrony)
max_buffer_mem = 2000
ntpq -p                      # Check offset (NTP)
</syntaxhighlight>
</syntaxhighlight>


Adjust <code>packetbuffer_compress_ratio</code> if CPU becomes a bottleneck.
== Network Throughput Testing ==


==GUI Visibility==
If experiencing "packetbuffer: MEMORY IS FULL" errors, test network with iperf3:


'''Automatic visibility:'''
<syntaxhighlight lang="bash">
* Client-server mode: Only the central server appears in GUI
# On central server
* Hybrid chain: Only the final server (C) and intermediate forwarder (B) appear
iperf3 -s


'''Manual sensor registration:'''
# On probe
iperf3 -c <server_ip>
</syntaxhighlight>


If you want sensor A to appear in GUI (for RRD charts, remote upgrades):
{| class="wikitable"
|-
! Result !! Interpretation !! Action
|-
| Expected bandwidth (>900 Mbps on 1Gb) || Network OK || Check local CPU/RAM
|-
| Low throughput || Network bottleneck || Check switches, cabling, consider Local Processing mode
|}


# Go to GUI → Settings → Sensors
== Debugging SIP Traffic ==
# Add sensor A manually with its <code>manager_ip:manager_port</code>
# Ensure <code>manager_aes_key</code> and <code>manager_aes_iv</code> match GUI database values


==Performance Optimization==
<code>sngrep</code> does not work on the central server because traffic is encapsulated in the TCP tunnel.


===Client-Server Mode for Better Performance===
'''Options:'''
* '''Live Sniffer:''' Use GUI → Live Sniffer to view SIP from remote sensors
* '''sngrep on sensor:''' Run <code>sngrep -i eth0</code> directly on the remote sensor


Switching from standalone to client-server architecture can significantly improve MySQL insert performance:
== Stale Sensor Records ==


# '''Centralized writes''': Single server instance handles all MySQL inserts (reduces lock contention)
If a new sensor fails with "bad password" despite correct credentials:
# '''Enable <code>mysql_enable_set_id</code>''': Let application handle ID auto-increment instead of MySQL
# '''Optimize MySQL configuration''': Tune <code>innodb_flush_log_at_trx_commit</code>, <code>innodb_io_capacity</code>, etc.


'''Migration steps:'''
# Delete the sensor record from '''GUI → Settings → Sensors'''
# Configure server: Set <code>server_bind</code>, <code>server_bind_port</code>, <code>server_password</code>
# Restart voipmonitor on the sensor: <code>systemctl restart voipmonitor</code>
# Initially set <code>mysql_enable_set_id = no</code> on server
# The sensor will re-register automatically
# Migrate sniffers one by one: Set <code>server_destination</code>, remove <code>mysqlhost</code>
# After all sniffers migrated: Enable <code>mysql_enable_set_id = yes</code> on server and restart


==SRTP/DTLS Decryption in Mirror Mode==
= Legacy: Mirror Mode =


When using mirror mode, ensure SSL/TLS decryption is configured correctly:
The older <code>mirror_destination</code>/<code>mirror_bind</code> options still work but Client-Server mode is preferred (encryption, simpler management).


'''On source sniffer (with mirror_destination):'''
To migrate from mirror mode:
<syntaxhighlight lang="bash">
# Stop sensors, comment out <code>mirror_*</code> parameters
sipport = 5060,5061
# Configure <code>server_bind</code> on central, <code>server_destination</code> on sensors
# Restart all services
 
For mirror mode <code>id_sensor</code> attribution, use:
<syntaxhighlight lang="ini">
# On central receiver
mirror_bind_sensor_id_by_sender = yes
</syntaxhighlight>
</syntaxhighlight>


This ensures TCP packets (including TLS handshakes) are also mirrored.
= See Also =


'''On receiving sniffer (with mirror_bind):'''
* [[Sniffing_modes|Deployment & Topology Guide]] - Traffic forwarding methods
* [[Sniffer_configuration|Sniffer Configuration]] - All parameters reference
* [[Merging_or_correlating_multiple_call_legs|Call Correlation]] - Multi-leg call handling
* [[FAQ#One_GUI_for_multiple_sniffers|FAQ: One GUI for Multiple Sniffers]]


Configure SSL decryption options here:
== Filtering Options in Packet Mirroring Mode ==
<syntaxhighlight lang="bash">
 
ssl_ipport = ...
{{Note|1='''Important distinction:''' In Packet Mirroring mode (<code>packetbuffer_sender=yes</code>):
ssl_sessionkey = ...
 
* '''Capture rules (GUI-based):''' Applied ONLY on the central server
* '''BPF filters / IP filters:''' CAN be applied on the remote sensor to reduce bandwidth
 
Use the following options on the '''remote sensor''' to filter traffic BEFORE sending to the central server:
 
<syntaxhighlight lang="ini">
# On REMOTE SENSOR (client)
 
# Option 1: BPF filter (tcpdump syntax) - most flexible
filter = not net 192.168.0.0/16 and not net 10.0.0.0/8
 
# Option 2: IP allow-list filter - CPU-efficient, no negation support
interface_ip_filter = 192.168.1.0/24
interface_ip_filter = 10.0.0.0/8
</syntaxhighlight>
</syntaxhighlight>


==Important Limitations==
<b>Benefits of filtering on remote sensor:</b>
* Reduces WAN bandwidth usage between sensor and central server
* Reduces processing load on central server
* Use <code>filter</code> for complex conditions (tcpdump/BPF syntax)
* Use <code>interface_ip_filter</code> for simple IP allow-lists (more efficient)


{{Warning|The hybrid chain workaround is '''not officially supported''' and may not work in future sniffer releases.}}
<b>Filtering approaches:</b>
* For <b>SIP header-based filtering</b>: Apply capture rules on the '''central server''' only
* For <b>IP/subnet filtering</b>: Use <code>filter</code> or <code>interface_ip_filter</code> on '''remote sensor'''}}


'''Key limitations:'''
== Supported Configuration Options in Packet Mirroring Mode ==
# <code>server_bind</code> and <code>server_destination</code> cannot coexist in one instance
# Hybrid chain architecture is unstable across sniffer versions
# No per-client authentication (same password for all clients)
# Recommended: Use standard multiple clients → single server architecture


==Future Enhancement (VS-1605)==
In Packet Mirroring mode (<code>packetbuffer_sender = yes</code>), the remote sensor forwards raw packets without processing them. This means many configuration options that manipulate packet behavior are '''unsupported''' on the remote sensor.


A future release may support native dual-mode operation with these new options:
== Supported Options on Remote Sensor (packetbuffer_sender) ==


<syntaxhighlight lang="bash">
The following options work correctly on the remote sensor in packet mirroring mode:
# Server mode (receive connections)
 
server_bind = 0.0.0.0
{| class="wikitable"
server_bind_port = 60024
! Parameter !! Description
server_bind_password = receive_secret
|-
| <code>id_sensor</code> || Unique sensor identifier
|-
| <code>server_destination</code> || Central server address
|-
| <code>server_destination_port</code> || Central server port (default 60024)
|-
| <code>server_password</code> || Authentication password
|-
| <code>server_destination_timeout</code> || Connection timeout settings
|-
| <code>server_destination_reconnect</code> || Auto-reconnect behavior
|-
| <code>filter</code> || BPF filter to limit capture (use this to capture only SIP)
|-
| <code>interface_ip_filter</code> || IP-based packet filtering
|-
| <code>interface</code> || Capture interface
|-
| <code>sipport</code> || SIP ports to monitor
|-
| <code>promisc</code> || Promiscuous mode
|-
| <code>rrd</code> || RRD statistics
|-
| <code>spooldir</code> || Temporary packet buffer directory
|-
| <code>ringbuffer</code> || Ring buffer size for packet mirroring
|-
| <code>max_buffer_mem</code> || Maximum buffer memory
|-
| <code>packetbuffer_enable</code> || Enable packet buffering
|-
| <code>packetbuffer_compress</code> || Enable compression for forwarded packets
|-
| <code>packetbuffer_compress_ratio</code> || Compression ratio
|}
 
== Unsupported Options on Remote Sensor ==
 
The following options '''do NOT work''' on the remote sensor in packet mirroring mode because the sensor does not parse packets:
 
{| class="wikitable"
! Parameter !! Reason
|-
| <code>natalias</code> || NAT alias handling (configure on central server instead)
|-
| <code>rtp_check_both_sides_by_sdp</code> || RTP correlation requires packet parsing
|-
| <code>disable_process_sdp</code> || SDP processing happens on central server
|-
| <code>save_sdp_ipport</code> || SDP extraction happens on central server
|-
| <code>rtpfromsdp_onlysip</code> || RTP mapping requires packet parsing
|-
| <code>rtpip_find_endpoints</code> || Endpoint discovery requires packet parsing
|}
 
{{Warning|1='''Critical: Storage options''' (<code>savesip</code>, <code>savertp</code>, <code>saveaudio</code>) '''must be configured on the CENTRAL SERVER''' in packet mirroring mode. The remote sensor only forwards packets and does not perform any storage operations.}}
 
== SIP-Only Capture Example ==
 
To capture and forward only SIP packets (excluding RTP/RTCP) for security or compliance:


# Client mode (send to upstream)
<syntaxhighlight lang="ini">
server_destination = upstream.ip
# /etc/voipmonitor.conf - Remote Sensor
server_destination_port = 60025
id_sensor              = 2
server_destination_password = send_secret
server_destination     = central.server.ip
server_destination_port = 60024
server_password        = your_strong_password
packetbuffer_sender    = yes
interface              = eth0
sipport                = 5060,5061


# Enable both modes
# Filter to capture ONLY SIP packets (exclude RTP/RTCP)
server_dual_mode = yes
filter = port 5060 or port 5061
</syntaxhighlight>
</syntaxhighlight>


This would enable clean multi-tier architectures without workarounds.
{{Note|1=The <code>filter</code> parameter using BPF syntax (tcpdump-compatible) is the recommended way to filter packets at the source in packet mirroring mode. This reduces bandwidth by forwarding only SIP packets to the central server.}}
 
 
 
 
 
 
 
 
= AI Summary for RAG =
 
'''Summary:''' VoIPmonitor v20+ Client-Server architecture for distributed deployments using encrypted TCP (default port 60024, zstd compression). Two modes: '''Local Processing''' (<code>packetbuffer_sender=no</code>) analyzes locally and sends CDRs only (1Gb sufficient); '''Packet Mirroring''' (<code>packetbuffer_sender=yes</code>) forwards raw packets to central server. Critical requirements: (1) exclude server_bind_port from sipport on central server (prevents memory issues); (2) sipport must match on probe and central server; (3) single sniffer must process both SIP and RTP for same call; (4) natalias only on central server. Intermediate servers supported for hub-and-spoke topology. Use <code>manager_ip</code> to bind outgoing connections to specific IP on HA setups. Sensor health via management API port 5029: <code>echo 'sniffer_stat' | nc <ip> 5029</code>. Debug SIP using Live Sniffer in GUI or sngrep on remote sensor. Stale sensor records cause "bad password" errors - delete from GUI Settings → Sensors and restart. Time sync errors: fix NTP or increase <code>client_server_connect_maximum_time_diff_s</code>.


'''Keywords:''' distributed architecture, client-server, packetbuffer_sender, local processing, packet mirroring, server_destination, server_bind, sipport exclusion, AWS VPC Traffic Mirroring alternative, intermediate server, sensor health, sniffer_stat, Live Sniffer, natalias, version compatibility, time synchronization, NTP, stale sensor record, mirror mode migration, manager_ip, high availability


== AI Summary for RAG ==
'''Summary:''' This guide explains how to deploy VoIPmonitor in distributed architectures using standalone, client-server, packet mirroring, and hybrid chain topologies. It documents how multiple remote sensors can send data to a central server, how mirror mode forwards raw packets between sniffers, and how a workaround combines mirroring with client mode to build multi-tier chains. The article clarifies where CDRs and PCAPs are stored in each scenario, how sensors appear in the GUI, how to manually register sensors, and how to optimize MySQL and VoIPmonitor configuration when migrating to client-server mode for better performance. It also covers forwarding SIP packets from a SIP-only probe to a central server that merges them with RTP media, using `packetbuffer_sender=yes` with `server_destination`/`server_bind` to create complete CDRs. Additionally, the article covers SRTP/DTLS decryption in mirror mode, current limitations (such as lack of dual-mode server/client in one process), and a proposed future enhancement (VS-1605) that would enable clean multi-hop deployments without workarounds.
'''Keywords:''' distributed architecture, client-server mode, mirror mode, hybrid chain, remote sensor, CDR forwarding, packet mirroring, packetbuffer_sender, SIP probe forwarding, RTP media merging, server_destination, server_bind, compression, MySQL performance, SRTP, DTLS, GUI sensors, manager_ip, scalability, multi-site monitoring
'''Key Questions:'''
'''Key Questions:'''
* How do I connect multiple VoIPmonitor sensors to a single central server using client-server mode?
* How do I connect multiple VoIPmonitor sensors to a central server?
* When should I use packet mirroring instead of sending only CDRs from remote sensors?
* What is the difference between Local Processing and Packet Mirroring mode?
* How are CDRs and PCAP files stored and accessed in client-server versus hybrid chain configurations?
* Why is VoIPmonitor using high memory on the central server?
* What are the limitations of combining <code>server_bind</code> and <code>server_destination</code> in a single sniffer instance?
* Why is a remote probe not detecting all calls on expected ports?
* How can I optimize MySQL and VoIPmonitor settings when migrating from standalone to client-server architecture?
* How do I check VoIPmonitor sensor health status?
* How do I ensure that all sensors are visible in the GUI and correctly registered for remote management?
* Why does a new sensor fail with "bad password" error?
* What are the current constraints and future plans (VS-1605) for native multi-tier VoIPmonitor deployments?
* How do I migrate from mirror mode to client-server mode?
* How do I forward SIP packets from a probe to a central server when SIP signaling and RTP media are captured on separate machines?
* What causes time synchronization errors between client and server?
* How do I configure `packetbuffer_sender=yes` with `server_destination` to merge SIP signaling from one location with RTP media from another?
* Where should natalias be configured in distributed deployments?
* Can VoIPmonitor act as an intermediate server?
* What is an alternative to AWS VPC Traffic Mirroring?

Latest revision as of 20:48, 19 January 2026


This guide covers deploying multiple VoIPmonitor sensors in a distributed architecture using Client-Server mode (v20+).

For deployment options including on-host vs dedicated sensors and traffic forwarding methods (SPAN, GRE, TZSP, VXLAN), see VoIPmonitor Deployment & Topology Guide.

Overview

VoIPmonitor v20+ uses Client-Server architecture for distributed deployments. Remote sensors connect to a central server via encrypted TCP (default port 60024, zstd compression).

Mode packetbuffer_sender What is Sent Processing Location Use Case
Local Processing no (default) CDRs only Remote sensor Multi-site, low bandwidth
Packet Mirroring yes Raw packets Central server Centralized analysis, low-resource remotes

Use Cases

AWS VPC Traffic Mirroring Alternative: If experiencing packet loss with AWS VPC Traffic Mirroring (VXLAN overhead, MTU fragmentation), use client-server mode instead:

  • Install VoIPmonitor on each source EC2 instance
  • Send via encrypted TCP to central server
  • Eliminates VXLAN encapsulation and MTU issues

Configuration

Remote Sensor (Client)

id_sensor               = 2                    # Unique per sensor (1-65535)
server_destination      = central.server.ip
server_destination_port = 60024
server_password         = your_strong_password

# Choose mode:
packetbuffer_sender     = no     # Local Processing: analyze locally, send CDRs
# packetbuffer_sender   = yes    # Packet Mirroring: send raw packets

interface               = eth0
sipport                 = 5060
# No MySQL credentials needed on remote sensors

💡 Tip: For HA setups with floating IPs, use manager_ip = 10.0.0.5 to bind outgoing connections to a static IP address.

Central Server

server_bind             = 0.0.0.0
server_bind_port        = 60024
server_password         = your_strong_password

mysqlhost               = localhost
mysqldb                 = voipmonitor
mysqluser               = voipmonitor
mysqlpassword           = db_password

# If receiving raw packets (packetbuffer_sender=yes on clients):
sipport                 = 5060
savertp                 = yes
savesip                 = yes

⚠️ Warning: Critical: Exclude server_bind_port from sipport on the central server. Including it causes continuously increasing memory usage.

# WRONG - includes sensor communication port:
sipport = 1-65535

# CORRECT - excludes port 60024:
sipport = 1-60023,60025-65535

Key Configuration Rules

Rule Applies To Why
server_bind_port must match server_destination_port Both Connection fails if mismatched
sipport must match on probe and central server Packet Mirroring Missing ports = missing calls
natalias only on central server Packet Mirroring Prevents RTP correlation issues
Each sensor needs unique id_sensor All Required for identification

Local Processing vs Packet Mirroring

Local Processing Packet Mirroring
packetbuffer_sender no (default) yes
Processing location Remote sensor Central server
PCAP storage Remote sensor Central server
WAN bandwidth Low (CDRs only, 1Gb sufficient) High (full packets)
Remote CPU load Higher Minimal
Capture rules applied On sensor On central server only

PCAP Access in Local Processing Mode

PCAPs are stored on remote sensors. The GUI retrieves them through the central server, which proxies the request to the sensor over the existing TCP/60024 connection - the same persistent encrypted channel the sensor uses for sending CDRs. This connection is bidirectional; the central server does not open any separate connection back to the sensor.

Firewall requirements:

Direction Port Purpose
Remote sensors → Central server TCP/60024 Persistent encrypted channel (CDRs from sensor, PCAP requests from server - bidirectional)
GUI → Central server TCP/5029 Manager API (sensor status, active calls, configuration)
GUI → Central server TCP/60024 Server API (list connected sensors, proxy PCAP retrieval)

ℹ️ Note: The central server does not initiate connections to remote sensors. All server↔sensor communication happens over the single TCP/60024 connection that the sensor established.

💡 Tip: Packet Mirroring (packetbuffer_sender=yes) automatically deduplicates calls - the central server merges packets from all probes for the same Call-ID into a single unified CDR. This also ensures one logical call only consumes one license channel.

Advanced Topics

High Availability (Failover)

Remote sensors can specify multiple central servers:

server_destination = 192.168.0.1, 192.168.0.2

If primary is unavailable, the sensor automatically connects to the next server.

Connection Compression

# On both client and server (default: zstd)
server_type_compress = zstd   # Options: zstd, gzip, lzo, none

Intermediate Server (Hub-and-Spoke)

An intermediate server can receive from multiple sensors and forward to a central server:

# On INTERMEDIATE SERVER
id_sensor               = 100

# Receive from remote sensors
server_bind             = 0.0.0.0
server_bind_port        = 60024
server_password         = sensor_password

# Forward to central server
server_destination      = central.server.ip
server_destination_port = 60024

packetbuffer_sender     = no    # or yes, depending on desired mode

ℹ️ Note: This works because the intermediate server does NOT do local packet capture - it only relays. Original remote sensors must be manually added to GUI Settings for visibility.

Multiple Receivers for Packet Mirroring

⚠️ Warning: Multiple sensors with packetbuffer_sender=yes sending to a single receiver instance can cause call processing conflicts (calls appear in Active Calls but missing from CDRs).

Solution: Run separate receiver instances on different hosts, each dedicated to specific sensors:

# Receiver Instance 1 (Host 1, for Sensor A)
server_bind_port        = 60024
id_sensor               = 1

# Receiver Instance 2 (Host 2, for Sensor B)
server_bind_port        = 60024
id_sensor               = 2

Alternative: Use Local Processing mode (packetbuffer_sender=no) which processes calls independently on each sensor.

Preventing Duplicate CDRs (Local Processing)

When multiple probes capture the same call in Local Processing mode:

# On each probe
cdr_check_exists_callid = yes

This checks for existing CDRs before inserting. Requires MySQL UPDATE privileges.

Critical: SIP and RTP Must Be Captured Together

VoIPmonitor cannot correlate SIP and RTP from different sniffer instances. A single sniffer must process both SIP and RTP for each call. Parameters like cdr_check_exists_callid do NOT enable split SIP/RTP correlation.


Split SIP/RTP with Packet Mirroring Mode

ℹ️ Note: Exception for Packet Mirroring Mode:: The above limitation applies to Local Processing mode (packetbuffer_sender=no) where each sensor processes calls independently. In Packet Mirroring mode (packetbuffer_sender=yes), the central server receives raw packets from multiple remote sensors and processes them together. This allows scenarios where SIP and RTP are captured on separate nodes - configure both as packet senders and let the central server correlate them into single unified CDRs.

Example scenario: Separate SIP signaling node and RTP handling node:

# SIP Signaling Node (packet sender)
id_sensor               = 1
packetbuffer_sender     = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password         = your_password

# RTP Handling Node (packet sender)
id_sensor               = 2
packetbuffer_sender     = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password         = your_password

The central server merges packets from both senders by Call-ID, creating unified CDRs with complete SIP and RTP data.


HEP Protocol in Client/Server Mode

VoIPmonitor supports receiving HEP-encapsulated traffic on sniffer clients and forwarding it to a central server. This enables distributed capture from HEP sources (Kamailio, OpenSIPS, rtpproxy, FreeSWITCH) in a client/server architecture.

Scenario: SIP proxy and RTP proxy at different locations sending HEP to remote sniffer clients:

# Remote Sniffer Client A (receives HEP from Kamailio)
id_sensor               = 1
hep                     = yes
hep_bind_port           = 9060
packetbuffer_sender     = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password         = your_password

# Remote Sniffer Client B (receives HEP from rtpproxy)
id_sensor               = 2
hep                     = yes
hep_bind_port           = 9060
packetbuffer_sender     = yes
server_destination      = central.server.ip
server_destination_port = 60024
server_password         = your_password

The central server receives packets from both clients and correlates them into unified CDRs using standard SIP Call-ID and IP:port from SDP.

ℹ️ Note: This also works for IPFIX (Oracle SBCs) and RibbonSBC protocols forwarded via client/server mode.

Alternative: Direct HEP to single sniffer

If both HEP sources can reach the same sniffer directly, no client/server setup is needed:

# Single sniffer receiving HEP from multiple sources
hep                     = yes
hep_bind_port           = 9060
interface               = eth0   # Can also sniff locally if needed

Both Kamailio (SIP) and rtpproxy (RTP) send HEP to this sniffer on port 9060. The sniffer correlates them automatically based on Call-ID and SDP IP:port.

Sensor Health Monitoring

Management API

Query sensor status via TCP port 5029:

echo 'sniffer_stat' | nc <sensor_ip> 5029

Returns JSON with status, version, active calls, packets per second, etc.

Multi-Sensor Health Check Script

#!/bin/bash
SENSORS=("192.168.1.10:5029" "192.168.1.11:5029")
for SENSOR in "${SENSORS[@]}"; do
    IP=$(echo $SENSOR | cut -d: -f1)
    PORT=$(echo $SENSOR | cut -d: -f2)
    STATUS=$(echo 'sniffer_stat' | nc -w 2 $IP $PORT 2>/dev/null | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
    echo "$IP: ${STATUS:-FAILED}"
done

Version Compatibility

Scenario Compatibility Notes
GUI ≥ Sniffer ✅ Compatible Recommended
GUI < Sniffer ⚠️ Risk Sensor may write to non-existent columns

Best practice: Upgrade GUI first (applies schema changes), then upgrade sensors.

For mixed versions temporarily, add to central server:

server_cp_store_simple_connect_response = yes   # Sniffer 2024.11.0+

Troubleshooting

Quick Diagnosis

Symptom First Check Likely Cause
Sensor not connecting journalctl -u voipmonitor -f on sensor Check server_destination, password, firewall
Traffic rate [0.0Mb/s] tcpdump on sensor interface Network/SPAN issue, not communication
High memory on central server Check if sipport includes 60024 Exclude server port from sipport
Missing calls Compare sipport on probe vs central Must match on both sides
"Bad password" error GUI → Settings → Sensors Delete stale sensor record, restart sensor
"Connection refused (111)" after migration Check server_destination in config Points to old server IP
RTP streams end prematurely Check natalias location Configure only on central server
Time sync errors timedatectl status Fix NTP or increase tolerance

Connection Testing

# Test connectivity from sensor to server
nc -zv <server_ip> 60024

# Verify server is listening
ss -tulpn | grep voipmonitor

# Check sensor logs
journalctl -u voipmonitor -n 100 | grep -i "connect"

Time Synchronization Errors

If seeing "different time between server and client" errors:

Immediate workaround: Increase tolerance on both sides:

client_server_connect_maximum_time_diff_s = 30
receive_packetbuffer_maximum_time_diff_s = 30

Root cause fix: Ensure NTP is working:

timedatectl status           # Check sync status
chronyc tracking             # Check offset (Chrony)
ntpq -p                      # Check offset (NTP)

Network Throughput Testing

If experiencing "packetbuffer: MEMORY IS FULL" errors, test network with iperf3:

# On central server
iperf3 -s

# On probe
iperf3 -c <server_ip>
Result Interpretation Action
Expected bandwidth (>900 Mbps on 1Gb) Network OK Check local CPU/RAM
Low throughput Network bottleneck Check switches, cabling, consider Local Processing mode

Debugging SIP Traffic

sngrep does not work on the central server because traffic is encapsulated in the TCP tunnel.

Options:

  • Live Sniffer: Use GUI → Live Sniffer to view SIP from remote sensors
  • sngrep on sensor: Run sngrep -i eth0 directly on the remote sensor

Stale Sensor Records

If a new sensor fails with "bad password" despite correct credentials:

  1. Delete the sensor record from GUI → Settings → Sensors
  2. Restart voipmonitor on the sensor: systemctl restart voipmonitor
  3. The sensor will re-register automatically

Legacy: Mirror Mode

The older mirror_destination/mirror_bind options still work but Client-Server mode is preferred (encryption, simpler management).

To migrate from mirror mode:

  1. Stop sensors, comment out mirror_* parameters
  2. Configure server_bind on central, server_destination on sensors
  3. Restart all services

For mirror mode id_sensor attribution, use:

# On central receiver
mirror_bind_sensor_id_by_sender = yes

See Also

Filtering Options in Packet Mirroring Mode

ℹ️ Note: Important distinction: In Packet Mirroring mode (packetbuffer_sender=yes):

  • Capture rules (GUI-based): Applied ONLY on the central server
  • BPF filters / IP filters: CAN be applied on the remote sensor to reduce bandwidth

Use the following options on the remote sensor to filter traffic BEFORE sending to the central server:

# On REMOTE SENSOR (client)

# Option 1: BPF filter (tcpdump syntax) - most flexible
filter = not net 192.168.0.0/16 and not net 10.0.0.0/8

# Option 2: IP allow-list filter - CPU-efficient, no negation support
interface_ip_filter = 192.168.1.0/24
interface_ip_filter = 10.0.0.0/8

Benefits of filtering on remote sensor:

  • Reduces WAN bandwidth usage between sensor and central server
  • Reduces processing load on central server
  • Use filter for complex conditions (tcpdump/BPF syntax)
  • Use interface_ip_filter for simple IP allow-lists (more efficient)

Filtering approaches:

  • For SIP header-based filtering: Apply capture rules on the central server only
  • For IP/subnet filtering: Use filter or interface_ip_filter on remote sensor

Supported Configuration Options in Packet Mirroring Mode

In Packet Mirroring mode (packetbuffer_sender = yes), the remote sensor forwards raw packets without processing them. This means many configuration options that manipulate packet behavior are unsupported on the remote sensor.

Supported Options on Remote Sensor (packetbuffer_sender)

The following options work correctly on the remote sensor in packet mirroring mode:

Parameter Description
id_sensor Unique sensor identifier
server_destination Central server address
server_destination_port Central server port (default 60024)
server_password Authentication password
server_destination_timeout Connection timeout settings
server_destination_reconnect Auto-reconnect behavior
filter BPF filter to limit capture (use this to capture only SIP)
interface_ip_filter IP-based packet filtering
interface Capture interface
sipport SIP ports to monitor
promisc Promiscuous mode
rrd RRD statistics
spooldir Temporary packet buffer directory
ringbuffer Ring buffer size for packet mirroring
max_buffer_mem Maximum buffer memory
packetbuffer_enable Enable packet buffering
packetbuffer_compress Enable compression for forwarded packets
packetbuffer_compress_ratio Compression ratio

Unsupported Options on Remote Sensor

The following options do NOT work on the remote sensor in packet mirroring mode because the sensor does not parse packets:

Parameter Reason
natalias NAT alias handling (configure on central server instead)
rtp_check_both_sides_by_sdp RTP correlation requires packet parsing
disable_process_sdp SDP processing happens on central server
save_sdp_ipport SDP extraction happens on central server
rtpfromsdp_onlysip RTP mapping requires packet parsing
rtpip_find_endpoints Endpoint discovery requires packet parsing

⚠️ Warning: Critical: Storage options (savesip, savertp, saveaudio) must be configured on the CENTRAL SERVER in packet mirroring mode. The remote sensor only forwards packets and does not perform any storage operations.

SIP-Only Capture Example

To capture and forward only SIP packets (excluding RTP/RTCP) for security or compliance:

# /etc/voipmonitor.conf - Remote Sensor
id_sensor               = 2
server_destination      = central.server.ip
server_destination_port = 60024
server_password         = your_strong_password
packetbuffer_sender     = yes
interface               = eth0
sipport                 = 5060,5061

# Filter to capture ONLY SIP packets (exclude RTP/RTCP)
filter = port 5060 or port 5061

ℹ️ Note: The filter parameter using BPF syntax (tcpdump-compatible) is the recommended way to filter packets at the source in packet mirroring mode. This reduces bandwidth by forwarding only SIP packets to the central server.





AI Summary for RAG

Summary: VoIPmonitor v20+ Client-Server architecture for distributed deployments using encrypted TCP (default port 60024, zstd compression). Two modes: Local Processing (packetbuffer_sender=no) analyzes locally and sends CDRs only (1Gb sufficient); Packet Mirroring (packetbuffer_sender=yes) forwards raw packets to central server. Critical requirements: (1) exclude server_bind_port from sipport on central server (prevents memory issues); (2) sipport must match on probe and central server; (3) single sniffer must process both SIP and RTP for same call; (4) natalias only on central server. Intermediate servers supported for hub-and-spoke topology. Use manager_ip to bind outgoing connections to specific IP on HA setups. Sensor health via management API port 5029: echo 'sniffer_stat' | nc <ip> 5029. Debug SIP using Live Sniffer in GUI or sngrep on remote sensor. Stale sensor records cause "bad password" errors - delete from GUI Settings → Sensors and restart. Time sync errors: fix NTP or increase client_server_connect_maximum_time_diff_s.

Keywords: distributed architecture, client-server, packetbuffer_sender, local processing, packet mirroring, server_destination, server_bind, sipport exclusion, AWS VPC Traffic Mirroring alternative, intermediate server, sensor health, sniffer_stat, Live Sniffer, natalias, version compatibility, time synchronization, NTP, stale sensor record, mirror mode migration, manager_ip, high availability

Key Questions:

  • How do I connect multiple VoIPmonitor sensors to a central server?
  • What is the difference between Local Processing and Packet Mirroring mode?
  • Why is VoIPmonitor using high memory on the central server?
  • Why is a remote probe not detecting all calls on expected ports?
  • How do I check VoIPmonitor sensor health status?
  • Why does a new sensor fail with "bad password" error?
  • How do I migrate from mirror mode to client-server mode?
  • What causes time synchronization errors between client and server?
  • Where should natalias be configured in distributed deployments?
  • Can VoIPmonitor act as an intermediate server?
  • What is an alternative to AWS VPC Traffic Mirroring?