Назад | Перейти на главную страницу

Как я могу определить, какой процесс создает трафик UDP в Linux?

Моя машина постоянно запрашивает трафик udp dns. мне нужно знать PID процесса, генерирующего этот трафик.

Обычный способ TCP-соединения - использовать netstat / lsof и получить процесс, связанный с pid.

Является ли UDP соединением stateles, поэтому, когда я вызываю netastat / lsof, я вижу его, только если UDP-сокет открыт и он отправляет трафик.

Я пробовал с lsof -i UDP и с nestat -anpue, но я не могу найти, какой процесс выполняет этот запрос, потому что мне нужно вызывать lsof / netstat именно тогда, когда отправляется трафик udp, если я вызываю lsof / netstat до / после отправки дейтаграммы udp, невозможно просмотреть открытый UDP разъем.

Вызов netstat / lsof точно при отправке 3/4 пакета udp НЕВОЗМОЖЕН.

Как я могу идентифицировать печально известный процесс? Я уже проверил трафик, чтобы попытаться идентифицировать отправленный PID из содержимого пакета, но не могу определить его из контекста трафика.

Кто-нибудь может мне помочь?

Я root на этой машине FEDORA 12 Linux noise.company.lan 2.6.32.16-141.fc12.x86_64 # 1 SMP среда, 7 июля 04:49:59 UTC 2010 x86_64 x86_64 x86_64 GNU / Linux

Аудит Linux может помочь. Он, по крайней мере, обнаружит пользователей и процессы, устанавливающие сетевые подключения дейтаграмм. Пакеты UDP - это дейтаграммы.

Сначала установите auditd framework на вашей платформе и убедитесь, что auditctl -l что-то возвращает, даже если говорит, что правила не определены.

Затем добавьте правило для просмотра системного вызова socket() и пометьте его, чтобы потом было легко найти (-k). Я должен предположить, что вы используете 64-битную архитектуру, но вы можете заменить b32 вместо b64 если нет.

auditctl -a exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET

Чтобы создать это, вам нужно просмотреть страницы руководства и заголовочные файлы, но, по сути, он захватывает этот системный вызов: socket(PF_INET, SOCK_DGRAM|X, Y), где третий параметр не указан, но часто равен нулю. PF_INET равно 2 и SOCK_DGRAM равно 2. TCP-соединения будут использовать SOCK_STREAM который установил бы a1=1. (SOCK_DGRAM во втором параметре можно объединить ИЛИ с SOCK_NONBLOCK или SOCK_CLOEXEC, следовательно &= сравнение.) -k SOCKET это наше ключевое слово, которое мы хотим использовать при поиске в журналах аудита позже. Это может быть что угодно, но я предпочитаю, чтобы это было просто.

Пройдите несколько минут и просмотрите контрольные журналы. При желании вы можете принудительно отправить пару пакетов, выполнив pinging хоста в сети, что вызовет поиск DNS, который использует UDP, что должно отключить наше контрольное предупреждение.

ausearch -i -ts today -k SOCKET

И появится результат, аналогичный приведенному ниже. Я сокращаю его, чтобы выделить важные части

type=SYSCALL ... arch=x86_64 syscall=socket success=yes exit=1 a0=2 a1=2 ... pid=14510 ... auid=zlagtime uid=zlagtime ... euid=zlagtime ... comm=ping exe=/usr/bin/ping key=SOCKET

В приведенном выше выводе мы видим, что ping команда вызвала открытие сокета. Я мог бы тогда бежать strace -p 14510 о процессе, если он еще работал. В ppid (ID родительского процесса) также отображается в случае, если это сценарий, который часто порождает проблемный дочерний элемент.

Теперь, если у вас много UDP-трафика, этого будет недостаточно, и вам придется прибегнуть к OProfile или SystemTap, оба из которых в настоящее время вне моей компетенции.

Это должно помочь сузить круг вопросов в общем случае.

Когда вы закончите, удалите правило аудита, используя ту же строку, которую вы использовали для его создания, только замените -a с участием -d.

auditctl -d exit,always -F arch=b64 -F a0=2 -F a1\&=2 -S socket -k SOCKET

Вы можете использовать netstat, но вам нужны правильные флаги, и он работает, только если процесс, отправляющий данные, все еще жив. Он не найдет следов чего-то, что ненадолго ожило, отправило UDP-трафик, а затем исчезло. Также требуются локальные привилегии root. При этом сказано:

Вот я запускаю ncat на моем локальном хосте, отправляя UDP-трафик на порт 2345 на (несуществующей) машине 10.11.12.13:

[madhatta@risby]$ ncat -u 10.11.12.13 2345 < /dev/urandom

Вот некоторые результаты tcpdump, подтверждающие, что трафик идет:

[root@risby ~]# tcpdump -n -n port 2345
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:41:32.391750 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.399723 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.401817 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.407051 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.413492 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192
12:41:32.417417 IP 192.168.3.11.57550 > 10.11.12.13.2345: UDP, length 8192

Вот полезный момент, используя netstat с флагом -a (чтобы увидеть детали порта) и флагом -p, чтобы увидеть детали идентификатора процесса. Это флаг -p, требующий привилегий root:

[root@risby ~]# netstat -apn|grep -w 2345
udp        0      0 192.168.3.11:57550          10.11.12.13:2345            ESTABLISHED 9152/ncat     

Как видите, pid 9152 воспринимается как открытое соединение с портом 2345 на указанном удаленном хосте. Netstat также помогает запустить это через ps и сообщает мне, что имя процесса ncat.

Надеюсь, это будет полезно.

У меня была точно такая же проблема и, к сожалению, auditd мало что сделал для меня.

У меня был трафик с некоторых моих серверов на DNS-адреса Google, 8.8.8.8 и 8.8.4.4. Теперь у моего сетевого администратора умеренное ОКР, и он хотел очистить весь ненужный трафик, поскольку у нас есть внутренние кеши DNS. Он хотел отключить исходящий порт 53 для всех, кроме этих кеш-серверов.

Итак, после неудачи с auditctlЯ копаюсь в systemtap. Я придумываю следующий сценарий:

# cat >> udp_detect_domain.stp <<EOF
probe udp.sendmsg {
  if ( dport == 53 && daddr == "8.8.8.8" ) {
    printf ("PID %5d (%s) sent UDP to %15s 53\n", pid(), execname(), daddr)
  }
}
EOF

Затем просто запустите:

stap -v udp_detect_domain.stp

Вот результат, который я получил:

PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3501 (python) sent UDP to  8.8.8.8 53
PID  3506 (python) sent UDP to  8.8.8.8 53

Это оно! После изменения resolv.conf эти PID не приняли изменений.


Надеюсь это поможет :)

Вот опция systemtap, использующая зонды netfilter, доступные в stap версии 1.8 и новее. Смотрите также man probe::netfilter.ip.local_out.

# stap -e 'probe netfilter.ip.local_out {
  if (dport == 53) # or parametrize
      printf("%s[%d] %s:%d\n", execname(), pid(), daddr, dport)
}'
ping[24738] 192.168.1.10:53
ping[24738] 192.168.1.10:53
^C

Я бы использовал сетевой сниффер, например tcpdump или wirehark, для просмотра DNS-запросов. Содержание запроса может дать представление о том, какая программа их выдает.

Имейте в виду, что при использовании autitctl, например, nscd использует немного другой параметр в системном вызове сокета при выполнении DNS-запроса:

socket(AF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP)

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

auditctl -a exit,always -F arch=b64 -F a0=2  -F a1=2050 -S socket -k SOCKET

Здесь 2050 - побитовое ИЛИ SOCK_DGRAM (2) и SOCK_NONBLOCK (2048).

Тогда поиск найдет оба этих фильтра с одним и тем же ключом, SOCKET:

ausearch -i -ts today -k SOCKET

Шестнадцатеричные значения констант сокета, которые я нашел здесь: https://golang.org/pkg/syscall/#pkg-constants

Поскольку у меня нет репутации для комментариев, я добавил это.