Tls: Difference between revisions
No edit summary |
|||
(28 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
= generic = | |||
Since version 11 VoIPmonitor sniffer is able to decode and decrypt TLS SIP protocol by providing private key. | |||
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. | |||
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. | |||
TLS feature is still in beta - if you will have any problems which are reproducible we need to see pcap file with the TLS packets (no need for RTP) and of course the private key. | |||
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. | |||
VoIPmonitor is able to decrypt SRTP. | |||
= Configuration = | |||
add to the voipmonitor.conf | |||
ssl = yes | |||
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-----) | |||
= Decryption methods = | = Decryption methods = | ||
== linux == | == linux == | ||
VoIPmonitor version >= 27 can decrypt any application by using ssl key logger which logs keys directly by injecting openssl library (openssl >= 1.1 | 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. | ||
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) | |||
This library is located in voipmonitor source tree: tools/ssl_keylogger/sslkeylog/sslkeylog.c | This library is located in voipmonitor source tree: tools/ssl_keylogger/sslkeylog/sslkeylog.c | ||
=== Installation === | === Installation === | ||
===== Requirements ===== | |||
For compile the keylogger from sources you will need at least the opnessl development libraries installed | |||
Debian/Ubuntu: | |||
apt-get install libssl-dev | |||
Centos/RH: | |||
yum install openssl-devel | |||
==== Compiling sslkeylogger ==== | ==== Compiling sslkeylogger ==== | ||
Line 22: | Line 56: | ||
You should always test if the library / keylogger is working by this command: | You should always test if the library / keylogger is working by this command: | ||
env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/ | env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so" openssl | ||
The output should show similar output: | The output should show similar output: | ||
* SSL KEYLOG : OK detect pointer to function SSL_new : 0x7fe9d6e96540 | * SSL KEYLOG : OK detect pointer to function SSL_new : 0x7fe9d6e96540 | ||
Line 29: | Line 63: | ||
OpenSSL> root@voipmonitor | OpenSSL> root@voipmonitor | ||
If you see SSL KEYLOG messages - the keylog is working | If you see SSL KEYLOG messages - the keylog is working | ||
==== Asterisk ==== | |||
Asterisk binary is directly linking with libssl so we just need to preload our sslkeylog | Asterisk binary is directly linking with libssl so we just need to preload our sslkeylog | ||
Line 40: | Line 74: | ||
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 | 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 ==== | ||
Line 50: | Line 90: | ||
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 | 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 | ||
Line 64: | Line 104: | ||
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" | 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" | ||
==== 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') | |||
[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): | |||
FREESWITCH_PARAMS="-rp -nonat -u freeswitch -g daemon -certs /etc/freeswitch/ssl" | |||
Additionally there is necessary to change DEBUG in keylogger - disable it or redirect to syslog instead of stdout, in eylogger sources add following to redirect to sysog: | |||
#define DEBUG_TO_SYSLOG 1 | |||
or disable debug at all (and recompile the keylogger after changes) | |||
#define DEBUG 0 | |||
==== Fusion PBX ==== | |||
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 ==== | ==== configuring voipmonitor ==== | ||
Line 89: | Line 171: | ||
ssl = yes | ssl = yes | ||
ssl_ipport = 192.168.0.1:5061 | 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) | ||
Generate key: | |||
openssl req -new -x509 -days 365 -nodes -out /etc/asterisk/keys/asterisk.pem -keyout /etc/asterisk/keys/asterisk.pem | |||
sip.conf | |||
== | [general] | ||
context=default | |||
realm=voipmonitor | |||
bindport=5062 | |||
udpbindaddr=0.0.0.0 | |||
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 | |||
start asterisk: | |||
env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD=/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so /usr/sbin/asterisk -vvvgcd | |||
=== pjsua console SIP client === | |||
For easy testing, the fastest way to send REGISTER packet or call is to use pjsip pjsua binary (with compiled openssl support) | |||
pjsua is automatically compiled when compiling pjsip library | |||
10.0.01 is the asterisk IP | |||
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 | |||
=== VoIPmonitor === | |||
for testing purpose there is no need to have voipmonitor.conf - just run the voipmonitort with this: | |||
voipmonitor -c -k -v1,pcap_stat_period=10,ssl_sessionkey,dump_sip_line \ | |||
--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"}]' | |||
ssl_sessionkey,dump_sip_line options will print SSL keys and decrypted SIP packets to the output: | |||
If everything works it should looks like this: | |||
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%] | |||
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 = | |||
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== | |||
BEWARE: when used TCP stack for the keylogger the debuging is not possible - git the decruption working using default UDP first. | |||
make with_tcp | |||
== change the preload command/line when pbx service starts == | |||
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 | |||
== change/set the related options of config voipmonitor.conf for sniffer service == | |||
ssl_sessionkey_udp = no | |||
#ssl_sessionkey_udp_port = | |||
#ssl_sessionkey_udp_ip = | |||
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 = | |||
==Explanation of SRTP Key Assembly from DTLS Packets== | |||
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: | |||
1. Capture DTLS packets. | |||
2. Receive the key from the keylogger. | |||
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. | |||
===Solutions Implemented=== | |||
#DTLS Packet Queue | |||
#Unified DTLS Packet Processing | |||
====1.DTLS Packet Queue==== | |||
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. | |||
DTLS processing is part of RTP processing. The behavior of the DTLS queue is determined by the following parameters: | |||
;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==== | |||
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. | |||
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. | |||
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. | |||
====Combined Methods==== | |||
The combination of these methods is determined by the parameter '''ssl_dtls_handshake_safe''': | |||
;NO (default)`: Only method 1 is used. | |||
;yes : Both methods 1 and 2 are used; method 1 has priority. | |||
;ext : Both methods 1 and 2 are used; method 2 has priority. | |||
;only: Only method 2 is used. | |||
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. | |||
== | ==Parameters== | ||
===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 optimal for this option to be enabled by default. (it is disabled by default in 2024.11.1 version of a sniffer) | |||
===Sniffer Pseudo-Parameter=== | |||
The sniffer has a pseudo-parameter '''ssl_dtls_boost''', which is disabled by default. When enabled, it sets: | |||
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:42, 28 November 2024
generic
Since version 11 VoIPmonitor sniffer is able to decode and decrypt TLS SIP protocol by providing private key.
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.
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.
TLS feature is still in beta - if you will have any problems which are reproducible we need to see pcap file with the TLS packets (no need for RTP) and of course the private key.
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.
VoIPmonitor is able to decrypt SRTP.
Configuration
add to the voipmonitor.conf
ssl = yes 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-----)
Decryption methods
linux
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.
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)
This library is located in voipmonitor source tree: tools/ssl_keylogger/sslkeylog/sslkeylog.c
Installation
Requirements
For compile the keylogger from sources you will need at least the opnessl development libraries installed
Debian/Ubuntu:
apt-get install libssl-dev
Centos/RH:
yum install openssl-devel
Compiling sslkeylogger
cd /usr/local/src git clone https://github.com/voipmonitor/sniffer.git voipmonitor-git cd voipmonitor-git/tools/ssl_keylogger/ make
running keylogger
Testing keylogger
You should always test if the library / keylogger is working by this command:
env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD="/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so" openssl
The output should show similar output:
* SSL KEYLOG : OK detect pointer to function SSL_new : 0x7fe9d6e96540 * SSL KEYLOG : OK detect pointer to function SSL_CTX_set_keylog_callback : 0x7fe9d6e97870 * SSL KEYLOG : log to : 127.0.0.1:1234 OpenSSL> root@voipmonitor
If you see SSL KEYLOG messages - the keylog is working
Asterisk
Asterisk binary is directly linking with libssl so we just need to preload our sslkeylog
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
On debian modify /etc/init.d/kamailio
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"
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')
[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):
FREESWITCH_PARAMS="-rp -nonat -u freeswitch -g daemon -certs /etc/freeswitch/ssl"
Additionally there is necessary to change DEBUG in keylogger - disable it or redirect to syslog instead of stdout, in eylogger sources add following to redirect to sysog:
#define DEBUG_TO_SYSLOG 1
or disable debug at all (and recompile the keylogger after changes)
#define DEBUG 0
Fusion PBX
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)
Generate key:
openssl req -new -x509 -days 365 -nodes -out /etc/asterisk/keys/asterisk.pem -keyout /etc/asterisk/keys/asterisk.pem
sip.conf
[general] context=default realm=voipmonitor bindport=5062 udpbindaddr=0.0.0.0 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
start asterisk:
env SSLKEYLOG_UDP='127.0.0.1:1234' LD_PRELOAD=/usr/local/src/voipmonitor-git/tools/ssl_keylogger/sslkeylog.so /usr/sbin/asterisk -vvvgcd
pjsua console SIP client
For easy testing, the fastest way to send REGISTER packet or call is to use pjsip pjsua binary (with compiled openssl support) pjsua is automatically compiled when compiling pjsip library 10.0.01 is the asterisk IP
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
VoIPmonitor
for testing purpose there is no need to have voipmonitor.conf - just run the voipmonitort with this:
voipmonitor -c -k -v1,pcap_stat_period=10,ssl_sessionkey,dump_sip_line \ --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"}]'
ssl_sessionkey,dump_sip_line options will print SSL keys and decrypted SIP packets to the output:
If everything works it should looks like this:
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%] 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
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
BEWARE: when used TCP stack for the keylogger the debuging is not possible - git the decruption working using default UDP first.
make with_tcp
change the preload command/line when pbx service starts
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
ssl_sessionkey_udp = no #ssl_sessionkey_udp_port = #ssl_sessionkey_udp_ip = 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
Explanation of SRTP Key Assembly from DTLS Packets
To assemble an SRTP key from DTLS packets, it is necessary to:
1. Capture DTLS packets. 2. Receive the key from the keylogger.
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.
Solutions Implemented
- DTLS Packet Queue
- Unified DTLS Packet Processing
1.DTLS Packet Queue
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.
DTLS processing is part of RTP processing. The behavior of the DTLS queue is determined by the following parameters:
- 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
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.
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.
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.
Combined Methods
The combination of these methods is determined by the parameter ssl_dtls_handshake_safe:
- NO (default)`
- Only method 1 is used.
- yes
- Both methods 1 and 2 are used; method 1 has priority.
- ext
- Both methods 1 and 2 are used; method 2 has priority.
- only
- Only method 2 is used.
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.
Parameters
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 optimal for this option to be enabled by default. (it is disabled by default in 2024.11.1 version of a sniffer)
Sniffer Pseudo-Parameter
The sniffer has a pseudo-parameter ssl_dtls_boost, which is disabled by default. When enabled, it sets:
ssl_dtls_queue_expiration = 30 ssl_sessionkey_keep = yes ssl_dtls_queue_keep = yes ssl_dtls_handshake_safe = ext ssl_dtls_rtp_local = yes