Tls: Difference between revisions

From VoIPmonitor.org
(Add critical info for FreeSWITCH DTLS+SRTP decryption: User=root required in systemd service with -u/-g flags in ExecStart)
 
(33 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= generic =
{{DISPLAYTITLE:TLS and SRTP Decryption}}
[[Category:Configuration]]


Since version 11 VoIPmonitor sniffer is able to decode and decrypt TLS SIP protocol by providing private key.  
'''This guide covers how to decrypt encrypted SIP (TLS) and media (SRTP/DTLS-SRTP) traffic in VoIPmonitor.'''


Please note that the sniffer only supports TLS layer and SSLv3 (not SSLv1 or SSLv2) layer which you can verify in CLIENT HELLO packet in wireshark where you can see SSL or TLS in header.
= Understanding TLS Decryption =


Decrypted SIP packets are converted to virtual UDP packets with the same ethernet headers replacing the IP TCP layer with UDP so you will not see the TCP stream in stored pcap files.  
VoIPmonitor can decrypt TLS-encrypted SIP signaling and SRTP media. The method you choose depends on your TLS configuration.


Please note that TLS where cipher suite is set to Diffie–Hellman key exchange is not possible to decrypt by using only private key. In this case you have to use the above method with ssl key logger or change the cipher suite to use anything else than diffie hellman cipher suites.
== Cipher Suite Impact ==


VoIPmonitor is able to decrypt SRTP.
{| class="wikitable"
! TLS Version / Cipher !! Private Key Decryption !! SSL Key Logger
|-
| TLS 1.2 with RSA (no DH) || {{Yes}} Works || {{Yes}} Works
|-
| TLS 1.2 with DHE/ECDHE || {{No}} Impossible || {{Yes}} Required
|-
| TLS 1.3 (any cipher) || {{No}} Impossible || {{Yes}} Required
|}


= Configuration =
{{Warning|1=Modern VoIP services use TLS 1.3 or PFS ciphers. The SSL Key Logger (Method 2) is the '''only viable method''' for most deployments.}}


add to the voipmonitor.conf
To check your cipher suite, capture the TLS handshake in Wireshark and look for "DHE" or "ECDHE" in the cipher negotiation.


ssl = yes
== Method Overview ==
ssl_ipport = 10.0.0.1 : 5061 /etc/private.key


where 10.0.0.1 is server with TLS port 5061. Private key is in /etc/private.key and it is in PEM format (starting with -----BEGIN RSA PRIVATE KEY-----)
<kroki lang="mermaid">
%%{init: {'flowchart': {'nodeSpacing': 15, 'rankSpacing': 30}}}%%
flowchart TD
    Q1{Can you control<br>PBX/SBC?} -->|Yes| Q2{Using DHE/ECDHE<br>or TLS 1.3?}
    Q1 -->|No - Cloud/Hosted| M4[Method 4: Vendor Tunneling<br>or Method 5: External Key Provider]
    Q2 -->|No - RSA only| M1[Method 1: Private Key]
    Q2 -->|Yes| M2[Method 2: SSL Key Logger]
    M2 -->|Distributed arch| M3[Method 3: Distributed Mode]
</kroki>


= Decryption methods =
'''Quick Reference:'''
* '''Method 1''' - Private Key: Simple, but only works for non-PFS ciphers
* '''Method 2''' - SSL Key Logger: Universal, works for all ciphers (recommended)
* '''Method 3''' - Distributed Mode: For client-server architecture with <code>packetbuffer_sender=yes</code>
* '''Method 4''' - SBC/PBX Tunneling: Ribbon, AudioCodes, or other vendor solutions
* '''Method 5''' - External Key Provider: Hosted platforms (NetSapiens, etc.)
* '''Method 6''' - HEP Protocol: Alternative when SSL Key Logger isn't feasible


== linux ==  
== Cloud Service Limitations ==


VoIPmonitor version >= 27 can decrypt any application by using ssl key logger which logs keys directly by injecting openssl library (tested with openssl >= 1.0.1, on fusionpbx, kamailio, freeswitch and asterisk). Ssl key logger is a small sslkeylog.so library which uses LD_PRELOAD to intercept session keys. Those keys are then sent over UDP to the voipmonitor sniffer. The behaviour of applications (like asterisk / kamailio / freeswitch and all software using openssl) is not affected or changed - it only logs keys.
{| class="wikitable"
! Scenario !! Decryption Possible?
|-
| Hardware phone → Cloud (Teams, Webex) || {{No}} Not possible (no access to cloud keys)
|-
| Softphone on controlled host → Cloud || {{Yes}} Use SSL Key Logger on the host
|-
| Phone → Local SBC → Cloud || {{Yes}} Use SBC tunneling (Method 4)
|}


VoIPmonitor receiving those keys can receive keys from multiple sources at once (in case you are running more servers or multiple SIP proxies on one or more hosts)
= Method 1: Private Key Decryption =


This library is located in voipmonitor source tree: tools/ssl_keylogger/sslkeylog/sslkeylog.c
Works only for TLS 1.2 or older '''without''' Diffie-Hellman ciphers.


=== Installation ===
== Configuration ==


===== Requirements =====
<syntaxhighlight lang="ini">
For compile the keylogger from sources you will need at least the opnessl development libraries installed
# /etc/voipmonitor.conf
ssl = yes
ssl_ipport = 10.0.0.1:5061 /etc/pki/tls/private/server.key
</syntaxhighlight>


Debian/Ubuntu:
'''Multiple servers:'''
apt-get install libssl-dev
<syntaxhighlight lang="ini">
ssl_ipport = 10.0.0.1:5061 /path/to/server1.key
ssl_ipport = 10.0.0.2:5061 /path/to/server2.key
</syntaxhighlight>


Centos/RH:
== GUI Configuration ==
yum install openssl-devel


==== Compiling sslkeylogger ====
Navigate to '''Settings > Sensors > wrench icon''' and search for <code>ssl_</code>:
* <code>ssl = yes</code>
* <code>ssl_ipport = IP:PORT /path/to/key</code>


cd /usr/local/src
= Method 2: SSL Key Logger (Recommended) =
git clone https://github.com/voipmonitor/sniffer.git voipmonitor-git
cd voipmonitor-git/tools/ssl_keylogger/
make


==== running keylogger ====
Works for '''all''' cipher suites including PFS. Captures session keys from your PBX/SBC using <code>LD_PRELOAD</code>.


===== Testing keylogger =====
== Step 1: Compile the Library ==


You should always test if the library / keylogger is working by this command:
<syntaxhighlight lang="bash">
# Install prerequisites
apt-get install libssl-dev build-essential git  # Debian/Ubuntu
yum install openssl-devel make gcc git          # RHEL/CentOS


env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so" openssl
# Compile
The output should show similar output:
cd /usr/local/src
* SSL KEYLOG : OK detect pointer to function SSL_new : 0x7fe9d6e96540
git clone https://github.com/voipmonitor/sniffer.git voipmonitor-git
* SSL KEYLOG : OK detect pointer to function SSL_CTX_set_keylog_callback : 0x7fe9d6e97870
cd voipmonitor-git/tools/ssl_keylogger/
* SSL KEYLOG : log to : 127.0.0.1:1234
make
OpenSSL> root@voipmonitor
</syntaxhighlight>


If you see SSL KEYLOG messages - the keylog is working
{{Tip|For WolfSSL: <code>make ssl=wolf CXXFLAGS="-DHAVE_WOLFSSL" LDFLAGS="-lwolfssl"</code>}}


==== Asterisk ====
== Step 2: Configure Your PBX ==


Asterisk binary is directly linking with libssl so we just need to preload our sslkeylog
=== Asterisk ===
 
env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so" asterisk -vvvgcd
 
 
edit your /etc/init.d/asterisk and put the  env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so" appropriately so the asterisk will start with the preloaded key logger
 
SSLKEYLOG_UDP parameter tells to what IP and port keys should be sent (this is voipmonitor IP and port) - in this example it runs on the same host as asterisk (127.0.0.1:1234)
 
===== how to put preload variables into sysctl/env file =====
Add following line into asterisk.service file
EnvironmentFile=/etc/systemd/system/asterisk.env
 
into asterisk.env put the environment variables ( for the sslkeylog preload ):
SSLKEYLOG_UDP='1.2.3.4:1234'
LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so'
 
==== Kamailio ====
 
 
Kamailio uses tls.so module (which is linked to openssl.so) thus the LD_PRELOAD needs to load openssl.so first
 
 
env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so /usr/local/lib64/libssl.so.1.1" kamailio
 
 
In this example, our system uses compiled openssl from sources, thus the path to the libssl is /usr/local/lib64/libssl.so.1.1 (on debian stock library is located in /usr/lib/x86_64-linux-gnu/libssl.so
 
 
You need to modify your kamailio start scripts


<syntaxhighlight lang="bash">
# Create environment file
cat > /etc/default/asterisk-ssl << 'EOF'
SSLKEYLOG_UDP='127.0.0.1:1234'
LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so'
EOF


On debian modify /etc/init.d/kamailio
# Add to service
systemctl edit asterisk.service
</syntaxhighlight>


Add:
<syntaxhighlight lang="ini">
[Service]
EnvironmentFile=/etc/default/asterisk-ssl
</syntaxhighlight>


env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so /usr/local/lib64/libssl.so.1.1" start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $OPTIONS || log_failure_msg " already running"
Restart: <code>systemctl daemon-reload && systemctl restart asterisk</code>


==== Freeswitch ====
=== FreeSWITCH ===


We experienced non-working keylogger with default systemd's service file settings. Please change following systemd options (and then reload the systemd with 'systemctl daemon-reload')
Edit <code>/lib/systemd/system/freeswitch.service</code>:
[Service]
Type=simple
ExecStart=env SSLKEYLOG_UDP='10.0.0.1:1234' LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so'  /usr/bin/freeswitch $FREESWITCH_PARAMS


Then in the /etc/sysconfig/freeswitch change the params (and restart the freeswitch service):
{{Warning|1='''Critical for DTLS+SRTP decryption:''' systemd must start the service as <code>root</code> so <code>LD_PRELOAD</code> can inject the keylogger before FreeSWITCH drops privileges. Set <code>User=root</code> in the service file and use <code>-u</code>/<code>-g</code> flags in <code>ExecStart</code> for FreeSWITCH to drop privileges internally.}}
FREESWITCH_PARAMS="-rp -nonat -u freeswitch -g daemon -certs /etc/freeswitch/ssl"


<syntaxhighlight lang="ini">
[Service]
User=root
Group=root
ExecStart=env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so' /usr/bin/freeswitch -u freeswitch -g freeswitch -nonat
</syntaxhighlight>


Additionally there is necessary to change DEBUG in keylogger - disable it or redirect to syslog instead of stdout, in keylogger's sources add following to redirect to sysog:
Then reload and restart:
#define DEBUG_TO_SYSLOG 1
<syntaxhighlight lang="bash">
or disable debug at all (and recompile the keylogger after changes)
systemctl daemon-reload
#define DEBUG 0
systemctl restart freeswitch
</syntaxhighlight>


==== Fusion PBX ====
=== Kamailio ===
Example service file for systemd and freeswitch from fusionpbx
 
[Unit]
Description=freeswitch
After=syslog.target network.target local-fs.target postgresql.service
[Service]
Type=simple
PIDFile=/run/freeswitch/freeswitch.pid
Environment="DAEMON_OPTS=-nonat -rp -nf"
ExecStartPre=/bin/mkdir -p /var/run/freeswitch/
ExecStartPre=/bin/chown -R www-data:www-data /var/run/freeswitch/
ExecStart=env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD='/usr/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so' /usr/bin/freeswitch -u www-data -g www-data $DAEMON_OPTS
TimeoutSec=45s
Restart=on-failure
User=root
Group=daemon
IOSchedulingClass=realtime
IOSchedulingPriority=2
CPUSchedulingPolicy=rr
CPUSchedulingPriority=89
UMask=0007
[Install]
WantedBy=multi-user.target
 
==== configuring voipmonitor ====
 
 
Lets assume that SIP proxy is running on 192.168.0.1:5061
 
 
edit : /etc/voipmonitor.conf
 
 
enabling ssl_sessionkey UDP receiver
 
 
ssl_sessionkey_udp = yes
ssl_sessionkey_udp_port = 1234
ssl_sessionkey_udp_ip = 192.168.178.0/24  (this is not mandatory)
ssl_sessionkey_udp_maxwait_ms = 10000
 
 
 
enabling ssl decryption
 
 
ssl = yes
ssl_ipport = 192.168.0.1:5061
ssl_ipport = 192.168.0.1:5062
 
ssl_ipport can be specified multiple times in case voipmonitor should decrypt multiple SIP proxies - for example if you have more tcp tls servers and voipmonitor instance should decrypt more of them
 
 
 
Run the voipmonitor in usual way.
 
 
= Testing TLS decryption =
 
=== Asterisk ===


(tested with 16.xx)
{{Warning|1=Kamailio requires '''all three libraries''' in LD_PRELOAD to avoid crashes:}}


Generate key:
<syntaxhighlight lang="bash">
# Find library paths
find /usr/lib -name "libssl.so*" -o -name "libjson-c.so*"
</syntaxhighlight>


openssl req -new -x509 -days 365 -nodes -out /etc/asterisk/keys/asterisk.pem -keyout /etc/asterisk/keys/asterisk.pem
Edit service file:
<syntaxhighlight lang="ini">
ExecStart=env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so:/usr/lib/x86_64-linux-gnu/libssl.so.3:/usr/lib/x86_64-linux-gnu/libjson-c.so.5' /usr/sbin/kamailio ...
</syntaxhighlight>


sip.conf
== Step 3: Configure VoIPmonitor ==


[general]
<syntaxhighlight lang="ini">
context=default
# /etc/voipmonitor.conf
realm=voipmonitor
ssl = yes
bindport=5062
ssl_sessionkey_udp = yes
udpbindaddr=0.0.0.0
ssl_sessionkey_udp_port = 1234
tlsenable=yes
tlsbindaddr=0.0.0.0
tlscertfile=/etc/asterisk/keys/asterisk.pem
tlscafile=/etc/asterisk/keys/ca.crt
tlscipher=ALL
tlsclientmethod=TLSv1_3
tlsbindport=5061
tcpenable=yes
tcpbindaddr=0.0.0.0
transport=udp,tcp
[500]
type=friend
language=en
defaultuser=500
secret=asdko0R9onX
transport=udp,tls
tlsenable=yes
insecure=no
callerid="500" <500>
host=dynamic
nat=force_rport,comedia
canreinvite=no
dtmfmode=rfc2833
encryption=no
disallow=all
allow=alaw
context=in_extensions_11
prematuremedia=no


# CRITICAL: No key file path when using SSL Key Logger!
ssl_ipport = 192.168.0.1:5061


start asterisk:
# Include loopback if sending keys to 127.0.0.1
interface = eth0,lo
</syntaxhighlight>


{{Warning|1='''WRONG:''' <code>ssl_ipport = IP:PORT /path/to/key</code> — This forces Method 1 and ignores the key logger!<br>'''CORRECT:''' <code>ssl_ipport = IP:PORT</code> — No key file path.}}


env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD=/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so /usr/sbin/asterisk -vvvgcd
== Secure Key Transport (TCP Mode) ==


=== pjsua console SIP client ===
For production environments, use TCP instead of UDP:


<syntaxhighlight lang="bash">
# Recompile with TCP support
cd /usr/local/src/voipmonitor-git/tools/ssl_keylogger/
make clean && make with_tcp
</syntaxhighlight>


For easy testing, the fastest way to send REGISTER packet or call is to use pjsip pjsua binary (with compiled openssl support)
On PBX: Change <code>SSLKEYLOG_UDP</code> to <code>SSLKEYLOG_TCP</code>
pjsua is automatically compiled when compiling pjsip library
10.0.01 is the asterisk IP


On VoIPmonitor:
<syntaxhighlight lang="ini">
ssl_sessionkey_udp = no
ssl_sessionkey_bind = 0.0.0.0
ssl_sessionkey_bind_port = 1234
</syntaxhighlight>


pjsua --id "sip:500@10.0.0.1;transport=tls" --registrar "sip:10.0.0.1:5061;transport=tls" --username "500" --password "ko0R9onX" --realm "*" "sip:1234@10.0.0.1"  --use-tls --no-udp
= Method 3: Distributed Mode =


When using <code>packetbuffer_sender=yes</code>, session keys '''must''' go to the central server.


<kroki lang="plantuml">
@startuml
skinparam shadowing false
rectangle "PBX" as PBX
rectangle "Client Sensor" as Client
rectangle "Central Server" as Central


=== VoIPmonitor ===
PBX --> Central : Session Keys (direct)
Client --> Central : Raw Packets
note right of PBX: SSLKEYLOG_UDP must\\npoint to Central IP
@enduml
</kroki>


'''On PBX:'''
<syntaxhighlight lang="ini">
# Send keys to CENTRAL SERVER, not localhost!
SSLKEYLOG_UDP='192.168.1.100:1234'  # Central server IP
</syntaxhighlight>


for testing purpose there is no need to have voipmonitor.conf - just run the voipmonitort with this:  
'''On Central Server:'''
<syntaxhighlight lang="ini">
ssl = yes
ssl_sessionkey_udp = yes
ssl_sessionkey_udp_port = 1234
ssl_ipport = 192.168.1.50:5061  # PBX IP (no key file)
</syntaxhighlight>


= Method 4: SBC/PBX Tunneling =


voipmonitor  -c -k -v1,pcap_stat_period=10,ssl_sessionkey,dump_sip_line \
Some SBCs decrypt internally and forward unencrypted traffic via tunneling protocols.
  --json_config='[{"sipport":"5062"},{"ssl":"yes"},{"ssl_ipport":"185.14.253.108:5061"},{"ssl_sessionkey_udp":"yes"},{"ssl_sessionkey_udp_port":1234},{"ssl_sessionkey_udp_maxwait_ms":10000},{"interface":"any"},{"sip-register":"yes"}]'


{| class="wikitable"
! Vendor !! Protocol !! Documentation
|-
| Ribbon/Oracle || Monitoring Profile || [[Ribbon7k_monitoring_profiles]]
|-
| AudioCodes || Proprietary tunnel || [[Audiocodes_tunneling]]
|-
| Generic || IPinIP || Auto-decoded by VoIPmonitor
|}


{{Note|1=When using vendor tunneling, '''no SSL configuration''' is needed in VoIPmonitor—traffic arrives unencrypted.}}


ssl_sessionkey,dump_sip_line options will print SSL keys and decrypted SIP packets to the output:  
= Method 5: External Key Providers =


Some hosted platforms (e.g., NetSapiens) can export TLS session keys to VoIPmonitor. Configure VoIPmonitor to receive keys via UDP/TCP as in Method 2.


= Method 6: HEP Protocol =


If everything works it should looks like this:
Alternative when SSL Key Logger doesn't work. The SIP proxy decrypts traffic and sends it via HEP.


<syntaxhighlight lang="ini">
# /etc/voipmonitor.conf
receiver_mode = yes
hep = yes
hep_bind_ip = 0.0.0.0
hep_bind_port = 9060
</syntaxhighlight>


voipmonitor-static[639]: calls[0,r:0][0,r:0] PS[C:-/- r:-/- S:-/- SR:- SM:- R:-/- A:61] SQLq[C:0] heap[0|0|0] [0.1Mb/s] tarQ[0] t0CPU[1.9%] t1CPU[0.4%] t2CPU[pb:0.4/S:-0.6%]
{{Note|1=HEP is just transport. Your SIP proxy must decrypt TLS '''before''' encapsulating in HEP. See [[Sniffing_modes#HEP_(Homer_Encapsulation_Protocol)|HEP documentation]].}}
set clientrandom with type SERVER_HANDSHAKE_TRAFFIC_SECRET
| dd 1d 0e 0a 26 2f af bd 3d 85 83 f0 cd 3b a3 ff | |....&/..=....;..|
| bf 39 b3 df 05 36 8f 45 c2 b4 e4 c8 fb 86 11 7d | |.9...6.E.......}|
key
| a7 de ed 6e a8 b5 c0 b9 e4 94 43 2e 99 66 3d 5a | |...n......C..f=Z|
| 14 c8 8f 57 01 4a 2c 2c b8 3c e6 7b 1f e8 e7 b8 | |...W.J,,.<.{....|
| 94 7e c4 29 ab e7 99 eb b3 fc 77 ab 2a c6 9f e8 | |.~.)......w.*...|
set clientrandom with type CLIENT_HANDSHAKE_TRAFFIC_SECRET
| dd 1d 0e 0a 26 2f af bd 3d 85 83 f0 cd 3b a3 ff | |....&/..=....;..|
| bf 39 b3 df 05 36 8f 45 c2 b4 e4 c8 fb 86 11 7d | |.9...6.E.......}|
key
| 64 7e 7f 93 31 e3 8d 7d 6c 69 a2 73 7b ef ee d3 | |d~..1..}li.s{...|
| a7 ff 54 1b 45 1a b9 fa dd f5 31 31 7e 06 3f 3d | |..T.E.....11~.?=|
| 2e fc da c9 05 bf e8 53 12 37 b8 2b 68 ad da 14 | |.......S.7.+h...|
set clientrandom with type EXPORTER_SECRET
| dd 1d 0e 0a 26 2f af bd 3d 85 83 f0 cd 3b a3 ff | |....&/..=....;..|
| bf 39 b3 df 05 36 8f 45 c2 b4 e4 c8 fb 86 11 7d | |.9...6.E.......}|
key
| 6e 88 72 28 5c 52 50 ff c9 31 ca d9 37 76 83 4c | |n.r(\RP..1..7v.L|
| a8 32 00 d3 59 c5 dc b9 94 ac 07 ea 91 42 b3 39 | |.2..Y........B.9|
| 28 37 8c 03 3a 03 21 9f ed 9f 79 0e 10 90 45 11 | |(7..:.!...y...E.|
set clientrandom with type SERVER_TRAFFIC_SECRET_0
| dd 1d 0e 0a 26 2f af bd 3d 85 83 f0 cd 3b a3 ff | |....&/..=....;..|
| bf 39 b3 df 05 36 8f 45 c2 b4 e4 c8 fb 86 11 7d | |.9...6.E.......}|
key
| 06 2d 04 60 b4 e2 a4 8b 2f 32 d2 8d a0 b5 06 e6 | |.-.`..../2......|
| 33 5a e3 af 53 c8 52 6d 7f ad 0d 63 f9 28 20 e9 | |3Z..S.Rm...c.( .|
| a5 47 2a ff b2 e4 e5 5f 1d 28 c2 c2 21 f9 26 05 | |.G*...._.(..!.&.|
set clientrandom with type CLIENT_TRAFFIC_SECRET_0
| dd 1d 0e 0a 26 2f af bd 3d 85 83 f0 cd 3b a3 ff | |....&/..=....;..|
| bf 39 b3 df 05 36 8f 45 c2 b4 e4 c8 fb 86 11 7d | |.9...6.E.......}|
key
| b2 61 3c 2f 85 b4 06 27 3f bd be b5 6c c5 b6 69 | |.a</...'?...l..i|
| b7 78 7d 0c e6 b5 5f a7 ea 77 08 f6 c6 3e 06 95 | |.x}..._..w...>..|
| bc 78 68 0f 3b 17 ec 7b 4d 2d 68 dc f6 e4 6d de | |.xh.;..{M-h...m.|
find clientrandom for all type
| dd 1d 0e 0a 26 2f af bd 3d 85 83 f0 cd 3b a3 ff | |....&/..=....;..|
| bf 39 b3 df 05 36 8f 45 c2 b4 e4 c8 fb 86 11 7d | |.9...6.E.......}|
* clientrandom found
1 192.168.0.254:40969 -> 10.1.1.1:5061
REGISTER sip:voipmonitor.org:5061;transport=tls SIP/2.0....


= Security instructions for sending keys from keylogger via public network =
= SRTP/DTLS Decryption =
The keylogger by default sends the observed keys in a plaintext using UDP packets to voipmonitor instance which is responsible for parsing storing/decrypting the calls.
In case that the keylogger and the sniffer are not in same host, the keys/packets from keylogger can be intercepted and keys revealed.
Therefor you can make the keylogger with **make with_tcp** option which will set to use TCP and encrypte the keys exchange between keylogger and the voipmonitor sniffer making it impossible to reveal the key.


== build the keylogger with TCP/encryption support==
== Recommended Configuration ==
BEWARE: when used TCP stack for the keylogger the debuging is not possible - git the decruption working using default UDP first.


make with_tcp
<syntaxhighlight lang="ini">
# Enables best-practice DTLS settings
ssl_dtls_boost = yes
</syntaxhighlight>


== change the preload command/line when pbx service starts ==
== RTP Proxy Issues (rtpengine) ==
Instead of UDP use preload with TCP (SSL_KEYLOG_UDP changed to _TCP)


env SSLKEYLOG_TCP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so /usr/local/lib64/libssl.so.1.1" kamailio
If SRTP decryption fails with SDES keys visible in SDP, your RTP proxy may be stripping keys.


== change/set the related options of config voipmonitor.conf for sniffer service ==
'''Fix for rtpengine (Kamailio):'''
ssl_sessionkey_udp = no
<syntaxhighlight lang="javascript">
#ssl_sessionkey_udp_port =
rtpengine_manage("replace-origin DTLS=no SDES-nonew SDES-pad");
#ssl_sessionkey_udp_ip =
</syntaxhighlight>
ssl_sessionkey_bind = 127.0.0.1
ssl_sessionkey_bind_port = 1234
Note: change the bind IP and port to what IP:port is reachable from the keylogger host.


=Decryption options for DTLS SRTP detailed =
== Garbled Audio ==
==Explanation of SRTP Key Assembly from DTLS Packets==


Garbled/distorted audio usually means SRTP is encrypted but not decrypted—'''not''' a codec issue.


To assemble an [https://datatracker.ietf.org/doc/html/rfc5764 SRTP] key from [https://datatracker.ietf.org/doc/html/rfc5764 DTLS] packets, it is necessary to:
'''Solution:''' Configure SSL Key Logger as described in Method 2, then verify keys are being received:
  1. Capture DTLS packets.
<syntaxhighlight lang="bash">
2. Receive the key from the keylogger.
tcpdump -i any -n port 1234 # Check for UDP key packets
</syntaxhighlight>


The problem is that DTLS packets are at the very beginning of the RTP stream (or rather, just before it). So, before the SIP/SDP evaluation (and thus the assignment of IP/ports to RTP streams) occurs, DTLS packets may pass through processing without being assigned to a call. Additionally, if SIP is encrypted over TLS, there may be a delay while waiting for the key from the keylogger.
= Troubleshooting =


===Solutions Implemented===
== Decryption Not Working ==
#DTLS Packet Queue
#Unified DTLS Packet Processing


'''Step 1: Verify packets are captured'''
* Check <code>sip:history (+)</code> in CDR detail
* Packets visible but encrypted → decryption issue
* Packets missing → capture issue (check interface config)


====1.DTLS Packet Queue====
'''Step 2: Check configuration'''


If a DTLS packet is not assigned to any call, it goes into a queue. This queue is divided into streams based on IP/ports. If an encrypted RTP packet arrives, it checks whether there are DTLS packets in the queue. If so, they are processed.
{| class="wikitable"
! Issue !! Solution
|-
| Keys sent to localhost but not captured || Add <code>lo</code> to interface: <code>interface = eth0,lo</code>
|-
| TCP/TLS packets not captured || Remove/fix BPF filter: <code>filter = udp or tcp or (vlan and (udp or tcp))</code>
|-
| <code>ssl_ipport</code> has key file path || Remove key path when using SSL Key Logger
|-
| <code>packetbuffer_sender=yes</code> fails || Send keys to central server IP, not localhost
|-
| FreeSWITCH not capturing DTLS+SRTP keys || Set <code>User=root</code> in systemd service file, use <code>-u</code>/<code>-g</code> flags in <code>ExecStart</code>
|}


DTLS processing is part of RTP processing. The behavior of the DTLS queue is determined by the following parameters:
== Compilation/Startup Issues ==
;ssl_dtls_queue = YES (default)/no
:Enables the queue; if the queue is not enabled, DTLS packets may be lost, and decryption may fail.
;ssl_dtls_queue_expiration = 10s (default)
:The time after which DTLS packets in the queue expire and are discarded.
;ssl_dtls_queue_keep = yes / NO (default)
:Allows DTLS packets to remain in the queue after their first successful use, expiring only after the set time. This is particularly useful if `srtp_rtp_local_instances = yes` is enabled (see below).


====2.Unified DTLS Packet Processing====
{| class="wikitable"
! Error !! Platform !! Solution
|-
| <code>undefined symbol: dlsym</code> || RHEL/CentOS/VitalPBX || Recompile: <code>g++ -shared -o sslkeylog.so sslkeylog.o -ldl</code> (library flags after objects)
|-
| FreeSWITCH stuck in "activating" || Any || Recompile without TCP: <code>make clean && make</code>; set <code>DEBUG 0</code> and <code>WRITE_THREAD 0</code>
|-
| Kamailio <code>receive_fd(): EOF</code> || Debian 12 || Add libjson-c.so to LD_PRELOAD (see Kamailio section)
|-
| Environment variables not loaded || Any || Use <code>asterisk -r</code> then <code>core stop now</code> instead of systemctl restart
|}


All DTLS packets go into a shared processing stream. In this process, DTLS packets are analyzed to extract the necessary information, such as '''client_random''' and '''server_random'''. These details are organized by IP/ports.
== High Traffic Issues ==


When an encrypted RTP packet arrives for RTP processing, it checks whether the '''client_random''' and '''server_random''' details exist and if the key has been received from the keylogger. If so, SRTP keys are computed, and decryption can occur.
'''Symptom:''' Packet drops, TLS calls not decrypted under load


Capturing DTLS packets in this method is handled by a thread marked as '''r''' in the log, which is minimally loaded as it only passes RTP packets to further processing.
'''Solution 1:''' Increase wait time:
<syntaxhighlight lang="ini">
ssl_sessionkey_maxwait_ms = 5000
</syntaxhighlight>


====Combined Methods====
'''Solution 2:''' Switch to TCP mode (see "Secure Key Transport" above)


The combination of these methods is determined by the parameter '''ssl_dtls_handshake_safe''':
== Capture for Support ==


;NO (default)`: Only method 1 is used.
<syntaxhighlight lang="bash">
;yes : Both methods 1 and 2 are used; method 1 has priority.
# Capture TLS traffic + keylogger packets
;ext : Both methods 1 and 2 are used; method 2 has priority.
tcpdump -i eth0,lo -w /tmp/debug.pcap \
;only: Only method 2 is used.
  "((host PBX_IP and port 5061) or (port 1234))"
</syntaxhighlight>


We concluded that method 2 could fully replace method 1, additionally placing less load on the CPU. However, this conclusion has not been applied to the sniffer.
Provide to support:
* CDR ID
* <code>voipmonitor --version</code>
* Config snippet (ssl*, interface, packetbuffer_sender)
* The PCAP file


==Parameters==
= See Also =
===Updates===
The parameter '''ssl_dtls_rtp_local''' is replaced by '''srtp_rtp_local_instances'''. When enabled, each RTP stream creates its own instance for decryption. Otherwise, a decryption instance is created jointly for SIP/SDP details of IP/port (in the sniffer for the index in the '''ip_port''' table).


The parameter '''ssl_sessionkey_keep''' is not just related to DTLS. It ensures that the received keylogger key remains in processing until it expires, rather than being discarded after its first successful use. It is enabled by default since develop version 2025.03.1 (it is disabled by default in previous versions of the sniffer)
* [[Audiocodes_tunneling]] - AudioCodes SBC tunneling
* [[Ribbon7k_monitoring_profiles]] - Ribbon/Oracle SBC monitoring
* [[WebRTC]] - WebRTC/WSS decryption
* [[Sniffer_configuration]] - Full configuration reference
* [[Sniffer_distributed_architecture]] - Client-server architecture


===Sniffer Pseudo-Parameter===
= AI Summary for RAG =


The sniffer has a pseudo-parameter '''ssl_dtls_boost''', which is enabled by default since develop version 2025.03.1 (it is disabled by default in previous versions of the sniffer)
'''Summary:''' Guide to decrypting TLS-encrypted SIP and SRTP media in VoIPmonitor. Six methods: (1) Private Key - only for TLS 1.2 without DHE/ECDHE, configure <code>ssl_ipport=IP:PORT /path/to/key</code>; (2) SSL Key Logger (recommended) - universal for all ciphers, inject <code>sslkeylog.so</code> via LD_PRELOAD into Asterisk/Kamailio/FreeSWITCH, keys sent via UDP or TCP; (3) Distributed Mode - with <code>packetbuffer_sender=yes</code>, send keys to central server IP not localhost; (4) SBC Tunneling - Ribbon/AudioCodes decrypt internally; (5) External Key Providers - hosted platforms export keys; (6) HEP - SIP proxy decrypts then sends via HEP. Critical: when using SSL Key Logger, <code>ssl_ipport</code> must NOT include key file path. For localhost keys, add <code>lo</code> to interface. Kamailio requires three libraries in LD_PRELOAD. FreeSWITCH requires <code>User=root</code> in systemd service file with <code>-u</code>/<code>-g</code> flags in ExecStart for DTLS+SRTP decryption to work. High traffic: use TCP mode or increase <code>ssl_sessionkey_maxwait_ms</code>. Garbled audio = SRTP encryption not codec issue.


When enabled, it sets:
'''Keywords:''' tls, ssl, srtp, dtls, decryption, sslkeylog, ld_preload, session key, asterisk, kamailio, freeswitch, ssl_ipport, ssl_sessionkey_udp, packetbuffer_sender, distributed mode, ribbon sbc, audiocodes, hep, rtpengine, pfs, perfect forward secrecy, garbled audio, dlsym error
ssl_dtls_queue_expiration = 30
ssl_sessionkey_keep = yes
ssl_dtls_queue_keep = yes
ssl_dtls_handshake_safe = ext
ssl_dtls_rtp_local = yes

Latest revision as of 10:43, 9 January 2026


This guide covers how to decrypt encrypted SIP (TLS) and media (SRTP/DTLS-SRTP) traffic in VoIPmonitor.

Understanding TLS Decryption

VoIPmonitor can decrypt TLS-encrypted SIP signaling and SRTP media. The method you choose depends on your TLS configuration.

Cipher Suite Impact

TLS Version / Cipher Private Key Decryption SSL Key Logger
TLS 1.2 with RSA (no DH) ✓ Yes Works ✓ Yes Works
TLS 1.2 with DHE/ECDHE ✗ No Impossible ✓ Yes Required
TLS 1.3 (any cipher) ✗ No Impossible ✓ Yes Required

⚠️ Warning: Modern VoIP services use TLS 1.3 or PFS ciphers. The SSL Key Logger (Method 2) is the only viable method for most deployments.

To check your cipher suite, capture the TLS handshake in Wireshark and look for "DHE" or "ECDHE" in the cipher negotiation.

Method Overview

Quick Reference:

  • Method 1 - Private Key: Simple, but only works for non-PFS ciphers
  • Method 2 - SSL Key Logger: Universal, works for all ciphers (recommended)
  • Method 3 - Distributed Mode: For client-server architecture with packetbuffer_sender=yes
  • Method 4 - SBC/PBX Tunneling: Ribbon, AudioCodes, or other vendor solutions
  • Method 5 - External Key Provider: Hosted platforms (NetSapiens, etc.)
  • Method 6 - HEP Protocol: Alternative when SSL Key Logger isn't feasible

Cloud Service Limitations

Scenario Decryption Possible?
Hardware phone → Cloud (Teams, Webex) ✗ No Not possible (no access to cloud keys)
Softphone on controlled host → Cloud ✓ Yes Use SSL Key Logger on the host
Phone → Local SBC → Cloud ✓ Yes Use SBC tunneling (Method 4)

Method 1: Private Key Decryption

Works only for TLS 1.2 or older without Diffie-Hellman ciphers.

Configuration

# /etc/voipmonitor.conf
ssl = yes
ssl_ipport = 10.0.0.1:5061 /etc/pki/tls/private/server.key

Multiple servers:

ssl_ipport = 10.0.0.1:5061 /path/to/server1.key
ssl_ipport = 10.0.0.2:5061 /path/to/server2.key

GUI Configuration

Navigate to Settings > Sensors > wrench icon and search for ssl_:

  • ssl = yes
  • ssl_ipport = IP:PORT /path/to/key

Method 2: SSL Key Logger (Recommended)

Works for all cipher suites including PFS. Captures session keys from your PBX/SBC using LD_PRELOAD.

Step 1: Compile the Library

# Install prerequisites
apt-get install libssl-dev build-essential git   # Debian/Ubuntu
yum install openssl-devel make gcc git           # RHEL/CentOS

# Compile
cd /usr/local/src
git clone https://github.com/voipmonitor/sniffer.git voipmonitor-git
cd voipmonitor-git/tools/ssl_keylogger/
make

💡 Tip:

Step 2: Configure Your PBX

Asterisk

# Create environment file
cat > /etc/default/asterisk-ssl << 'EOF'
SSLKEYLOG_UDP='127.0.0.1:1234'
LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so'
EOF

# Add to service
systemctl edit asterisk.service

Add:

[Service]
EnvironmentFile=/etc/default/asterisk-ssl

Restart: systemctl daemon-reload && systemctl restart asterisk

FreeSWITCH

Edit /lib/systemd/system/freeswitch.service:

⚠️ Warning: Critical for DTLS+SRTP decryption: systemd must start the service as root so LD_PRELOAD can inject the keylogger before FreeSWITCH drops privileges. Set User=root in the service file and use -u/-g flags in ExecStart for FreeSWITCH to drop privileges internally.

[Service]
User=root
Group=root
ExecStart=env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so' /usr/bin/freeswitch -u freeswitch -g freeswitch -nonat

Then reload and restart:

systemctl daemon-reload
systemctl restart freeswitch

Kamailio

⚠️ Warning: Kamailio requires all three libraries in LD_PRELOAD to avoid crashes:

# Find library paths
find /usr/lib -name "libssl.so*" -o -name "libjson-c.so*"

Edit service file:

ExecStart=env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD='/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so:/usr/lib/x86_64-linux-gnu/libssl.so.3:/usr/lib/x86_64-linux-gnu/libjson-c.so.5' /usr/sbin/kamailio ...

Step 3: Configure VoIPmonitor

# /etc/voipmonitor.conf
ssl = yes
ssl_sessionkey_udp = yes
ssl_sessionkey_udp_port = 1234

# CRITICAL: No key file path when using SSL Key Logger!
ssl_ipport = 192.168.0.1:5061

# Include loopback if sending keys to 127.0.0.1
interface = eth0,lo

⚠️ Warning: WRONG: ssl_ipport = IP:PORT /path/to/key — This forces Method 1 and ignores the key logger!
CORRECT: ssl_ipport = IP:PORT — No key file path.

Secure Key Transport (TCP Mode)

For production environments, use TCP instead of UDP:

# Recompile with TCP support
cd /usr/local/src/voipmonitor-git/tools/ssl_keylogger/
make clean && make with_tcp

On PBX: Change SSLKEYLOG_UDP to SSLKEYLOG_TCP

On VoIPmonitor:

ssl_sessionkey_udp = no
ssl_sessionkey_bind = 0.0.0.0
ssl_sessionkey_bind_port = 1234

Method 3: Distributed Mode

When using packetbuffer_sender=yes, session keys must go to the central server.

On PBX:

# Send keys to CENTRAL SERVER, not localhost!
SSLKEYLOG_UDP='192.168.1.100:1234'  # Central server IP

On Central Server:

ssl = yes
ssl_sessionkey_udp = yes
ssl_sessionkey_udp_port = 1234
ssl_ipport = 192.168.1.50:5061  # PBX IP (no key file)

Method 4: SBC/PBX Tunneling

Some SBCs decrypt internally and forward unencrypted traffic via tunneling protocols.

Vendor Protocol Documentation
Ribbon/Oracle Monitoring Profile Ribbon7k_monitoring_profiles
AudioCodes Proprietary tunnel Audiocodes_tunneling
Generic IPinIP Auto-decoded by VoIPmonitor

ℹ️ Note: When using vendor tunneling, no SSL configuration is needed in VoIPmonitor—traffic arrives unencrypted.

Method 5: External Key Providers

Some hosted platforms (e.g., NetSapiens) can export TLS session keys to VoIPmonitor. Configure VoIPmonitor to receive keys via UDP/TCP as in Method 2.

Method 6: HEP Protocol

Alternative when SSL Key Logger doesn't work. The SIP proxy decrypts traffic and sends it via HEP.

# /etc/voipmonitor.conf
receiver_mode = yes
hep = yes
hep_bind_ip = 0.0.0.0
hep_bind_port = 9060

ℹ️ Note: HEP is just transport. Your SIP proxy must decrypt TLS before encapsulating in HEP. See HEP documentation.

SRTP/DTLS Decryption

Recommended Configuration

# Enables best-practice DTLS settings
ssl_dtls_boost = yes

RTP Proxy Issues (rtpengine)

If SRTP decryption fails with SDES keys visible in SDP, your RTP proxy may be stripping keys.

Fix for rtpengine (Kamailio):

rtpengine_manage("replace-origin DTLS=no SDES-nonew SDES-pad");

Garbled Audio

Garbled/distorted audio usually means SRTP is encrypted but not decrypted—not a codec issue.

Solution: Configure SSL Key Logger as described in Method 2, then verify keys are being received:

tcpdump -i any -n port 1234  # Check for UDP key packets

Troubleshooting

Decryption Not Working

Step 1: Verify packets are captured

  • Check sip:history (+) in CDR detail
  • Packets visible but encrypted → decryption issue
  • Packets missing → capture issue (check interface config)

Step 2: Check configuration

Issue Solution
Keys sent to localhost but not captured Add lo to interface: interface = eth0,lo
TCP/TLS packets not captured Remove/fix BPF filter: filter = udp or tcp or (vlan and (udp or tcp))
ssl_ipport has key file path Remove key path when using SSL Key Logger
packetbuffer_sender=yes fails Send keys to central server IP, not localhost
FreeSWITCH not capturing DTLS+SRTP keys Set User=root in systemd service file, use -u/-g flags in ExecStart

Compilation/Startup Issues

Error Platform Solution
undefined symbol: dlsym RHEL/CentOS/VitalPBX Recompile: g++ -shared -o sslkeylog.so sslkeylog.o -ldl (library flags after objects)
FreeSWITCH stuck in "activating" Any Recompile without TCP: make clean && make; set DEBUG 0 and WRITE_THREAD 0
Kamailio receive_fd(): EOF Debian 12 Add libjson-c.so to LD_PRELOAD (see Kamailio section)
Environment variables not loaded Any Use asterisk -r then core stop now instead of systemctl restart

High Traffic Issues

Symptom: Packet drops, TLS calls not decrypted under load

Solution 1: Increase wait time:

ssl_sessionkey_maxwait_ms = 5000

Solution 2: Switch to TCP mode (see "Secure Key Transport" above)

Capture for Support

# Capture TLS traffic + keylogger packets
tcpdump -i eth0,lo -w /tmp/debug.pcap \
  "((host PBX_IP and port 5061) or (port 1234))"

Provide to support:

  • CDR ID
  • voipmonitor --version
  • Config snippet (ssl*, interface, packetbuffer_sender)
  • The PCAP file

See Also

AI Summary for RAG

Summary: Guide to decrypting TLS-encrypted SIP and SRTP media in VoIPmonitor. Six methods: (1) Private Key - only for TLS 1.2 without DHE/ECDHE, configure ssl_ipport=IP:PORT /path/to/key; (2) SSL Key Logger (recommended) - universal for all ciphers, inject sslkeylog.so via LD_PRELOAD into Asterisk/Kamailio/FreeSWITCH, keys sent via UDP or TCP; (3) Distributed Mode - with packetbuffer_sender=yes, send keys to central server IP not localhost; (4) SBC Tunneling - Ribbon/AudioCodes decrypt internally; (5) External Key Providers - hosted platforms export keys; (6) HEP - SIP proxy decrypts then sends via HEP. Critical: when using SSL Key Logger, ssl_ipport must NOT include key file path. For localhost keys, add lo to interface. Kamailio requires three libraries in LD_PRELOAD. FreeSWITCH requires User=root in systemd service file with -u/-g flags in ExecStart for DTLS+SRTP decryption to work. High traffic: use TCP mode or increase ssl_sessionkey_maxwait_ms. Garbled audio = SRTP encryption not codec issue.

Keywords: tls, ssl, srtp, dtls, decryption, sslkeylog, ld_preload, session key, asterisk, kamailio, freeswitch, ssl_ipport, ssl_sessionkey_udp, packetbuffer_sender, distributed mode, ribbon sbc, audiocodes, hep, rtpengine, pfs, perfect forward secrecy, garbled audio, dlsym error