Декодирование ipsec в Linux

в 8:50, , рубрики: ipsec, linux, PSK, wireshark, Серверное администрирование, системное администрирование, метки: , ,

Иногда возникает необходимость снять дамп трафика внутри ipsec тоннеля. Я расскажу как это сделать в случае ipsec, поднятом на Linux сервере с PSK аутентификацией при помощи wireshark.

Для успешного декодирования трафика необходимо начать снимать дамп сразу после поднятия ipsec.
Для захвата трафика используем tcpdump, например так:


# tcpdump -i any -s 0 -w ipsec.pcap esp

Затем поднимаем ipsec:


# /etc/init.d/ipsec start

Так как ipsec настроен с использованием PSK (pre shared key) аутентификации, то для успешного декодирования необходимо узнать сессионный ключ. Это можно сделать с помощью команды setkey.
Данная команда, в случае debian, входит в пакет ipsec-tools. Запускать нужно с правами root.

# setkey -D
10.1.1.1  10.2.2.2
	esp mode=tunnel spi=2548102798(0x97e0f68e) reqid=16389(0x00004005)
	E: aes-cbc  2a787e41 bbdc2f94 9ced721c 7fcf934e
	A: hmac-sha1  6af6847a 477bea9f 5c9a8d13 7ea9a5b5 9a318d29
	seq=0x00000000 replay=32 flags=0x00000000 state=mature 
	created: Oct 16 10:37:52 2012	current: Oct 16 11:04:26 2012
	diff: 1594(s)	hard: 0(s)	soft: 0(s)
	last:                     	hard: 0(s)	soft: 0(s)
	current: 0(bytes)	hard: 0(bytes)	soft: 0(bytes)
	allocated: 0	hard: 0	soft: 0
	sadb_seq=1 pid=9195 refcnt=0

Нам потребуется:
1) ip-адреса
2) spi — security parameter index
3) строка «E:» (алгоритм шифрации и сессионный ключ), для данного примера алгоритм шифрации aes-cbc, и 128-битный AES ключ «2a787e41 bbdc2f94 9ced721c 7fcf934e»
4) строка «A:» (алгоритм аутентификации и его ключ), для данного примера это hmac-sha1 и ключ «6af6847a 477bea9f 5c9a8d13 7ea9a5b5 9a318d29»

Т.к. у нас используется AES-CBC, то именно поэтому (из-за приставки -CBC) потребуется весь трафик с момента поднятия ipsec тоннеля (CBC — cipher block chaining). Возможно, с другими алгоритмами не потребуется иметь весь трафик, этого я не знаю, но думаю, что скорее всего будет требоваться весь трафик с момента поднятия ipsec туннеля.

Для декодирования и просмотра используем wireshark (1.8.2, можно и более раннюю версию, но там будет немного иначе).

Данные параметры нужно вбить в wireshark. Нужно открыть окно настроек «Edit->Preferences», там выбрать «Protocols->ESP», где установить галочки «Attempt to detect/decode NULL encrypted ESP payloads», «Attempt to detect/decode encrypted ESP payloads» и «Attempt to Check ESP Authentication».

Декодирование ipsec в Linux

Затем нажать кнопку «Edit» («Edit» -> «Создать») и вбить ip-адреса, spi и ключи полученные с помощью setkey:

Декодирование ipsec в Linux

После сохранения введенных изменений, мы должны получить декодированный трафик:

Декодирование ipsec в Linux

Для облегчения настройки wireshark я написал небольшую утилиту на perl, которая запускает setkey -D и форматирует вывод в формат настроек wireshark:

#!/usr/bin/perl -w

%ealg = (
	'aes-cbc' => 'AES-CBC [RFC3602]',
	'3des-cbc' => 'TripleDES-CBC [RFC2451]',
	'aes-ctr' => 'AES-CTR [RFC3686]',
	'todo' => 'DES-CBC [RFC2405]',
	'todo' => 'CAST5-CBC [RFC2144]',
	'blowfish-cbc' => 'BLOWFISH-CBC [RFC2451]',
	'twofish-cbc' => 'TWOFISH-CBC'
);
%aalg = (
	'hmac-sha1' => 'HMAC-SHA-1-96 [RFC2404]',
	'hmac-sha256' => 'HMAC-SHA-256-96 [draft-ietf-ipsec-ciph-sha-256-00]',
	'todo' => 'HMAC-SHA-256-128 [RFC4868]',
	'todo' => 'HMAC-MD5-96 [RFC2403]',
	'todo' => 'MAC-RIPEMD-160-96 [RFC2857]',
	'todo' => 'ANY 96 bit authentication [no checking]',
	'todo' => 'ANY 128 bit authentication [no checking]',
	'todo' => 'ANY 192 bit authentication [no checking]',
	'todo' => 'ANY 256 bit authentication [no checking]'
);

open KEYS, "setkey -D |";
while (defined($l = <KEYS>)) {
	if ($l =~ /^d/) {
		($ip_src, $ip_dst) = (split(/s+/, $l))[0,1];
	} elsif ($l =~ /^s+esp mode=.*? spi=d+((0x.*?))/) {
		$spi = $1;
	} elsif ($l =~ /^s+E: ([^s]+)s+(.*)$/) {
		($ealg, $ekey) = ($1, $2);

		$ealg = ($ealg{$ealg} or die "Unknown encr alg: '$ealg'");
		$ekey =~ s/s+//g;
	} elsif ($l =~ /^s+A: ([^s]+)s+(.*)$/) {
		($aalg, $akey) = ($1, $2);
		$aalg = ($aalg{$aalg} or die "Unknown auth alg: '$aalg'");
		$akey =~ s/s+//g;

		print qq#"IPv4","$ip_src","$ip_dst","$spi",$ealg,"0x$ekey","$aalg","0x$akey"n#;
		($ip_src, $ip_dst, $spi, $ealg, $ekey, $aalg, $akey) = ();
	}
}
close KEYS

Результат нужно записать в файл ~/.wireshark/esp_sa. После чего перезапустить wireshark.

Если скрипт у вас не заработает, и выдаст ошибку «Unknown encr alg» или «Unknown auth alg», нужно будет вбить в скрипт в хеш-таблицы %ealg или %aalg соответствие этого алгоритма в утилите setkey и соответствующего значения для wireshark. Мной тестировалось только с aes-cbc и hmac-sha1.

Дополнительная информация (немного устаревшая) на сайте wireshark.

Автор: ivnik


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js