Бег tcpdump
при локальных подключениях к серверу apache я обнаружил, что TCP-соединения устанавливаются и закрываются немедленно каждые 2 секунды. Как мне узнать, какой процесс за это отвечает? netstat -ctp
не помогло, соединения были слишком быстрыми и идентификатор процесса не отображается для TIME_WAIT.
Оказалось, что это были прокси-зонды, которые я мог проверить с помощью strace
, но я до сих пор не знаю, как определить haproxy.
Для такого рода вещей вы можете использовать структуру auditd. Они не очень "удобны для пользователя" или интуитивно понятны, поэтому с вашей стороны нужно немного покопаться.
Сначала убедитесь, что у вас установлен, запущен auditd и что ваше ядро поддерживает его.
Для Ubuntu вы можете установить его с помощью apt-get install auditd
например.
Затем вы добавляете политику аудита, чтобы контролировать все connect
такие системные вызовы:
auditctl -a exit,always -F arch=b64 -S connect -k MYCONNECT
Если вы используете 32-битную установку Linux, вам необходимо изменить b64 на b32.
Эта команда вставит политику в структуру аудита, и все системные вызовы connect () теперь будут регистрироваться в ваших файлах журнала аудита (обычно /var/log/audit/audit.log
), чтобы вы могли посмотреть.
Например, подключение netcat к порту 80 news.ycombinator.com приведет к примерно следующему:
type=SYSCALL msg=audit(1326872512.453:12752): arch=c000003e syscall=42 success=no exit=-115 a0=3 a1=24e8fa0 a2=10 a3=7fff07a44cd0 items=0 ppid=5675 pid=7270 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts4 ses=4294967295 comm="nc" exe="/bin/nc.openbsd" key="MYCONNECT"
type=SOCKADDR msg=audit(1326872512.453:12752): saddr=02000050AE84E16A0000000000000000
Здесь вы можете видеть, что приложение /bin/nc.openbsd инициировало вызов connect (), если вы получаете много вызовов connect и хотите только grep получить определенный IP-адрес или порт, вам нужно выполнить некоторое преобразование. Строка SOCKADDR содержит аргумент saddr, он начинается с 0200, за которым следует шестнадцатеричный номер порта (0050), что означает 80, а затем шестнадцатеричный IP-адрес (AE84E16A), который является IP-адресом news.ycombinator.com 174.132.225.106.
Структура аудита может генерировать много журналов, поэтому не забудьте отключить его, когда выполнили свою миссию. Чтобы отключить указанную выше политику, просто замените -a на -d как таковую:
auditctl -d exit,always -F arch=b64 -S connect -k MYCONNECT
Хорошая документация по фреймворку auditd:
http://doc.opensuse.org/products/draft/SLES/SLES-security_sd_draft/part.audit.html
Преобразование IP-адресов в / из шестнадцатеричного, десятичного, двоичного и т. Д. По адресу:
http://www.kloth.net/services/iplocate.php
Общий шестнадцатеричный / десятичный преобразователь:
http://www.statman.info/conversions/hexadecimal.html
Краткое введение в auditd от IT Security Stack Exchange. http://security.blogoverflow.com/2013/01/a-brief-introduction-to-auditd/
Редактировать 1:
Еще один быстрый (шведский: fulhack) способ сделать это - создать быстрый цикл, который выдает вам данные подключения, например:
while true;do
ss -ntap -o state established '( dport = :80 )'
sleep 1
done
Эта команда использует ss
команда (статистика сокетов) для сброса текущих установленных соединений на порт 80, включая то, какой процесс их инициировал. Если данных много, вы можете добавить | tee /tmp/output
после того, как это сделано, чтобы показать результат на экране, а также записать его в / tmp / output для последующей обработки / копания. Если он не улавливает быстрое соединение haproxy, попробуйте удалить sleep 1
но будьте осторожны с обширными лесозаготовками, если это сильно загруженная машина. При необходимости измените!
На самом деле многое изменилось с тех пор, как был задан этот вопрос. Большинство современных Linux-систем имеют расширенные возможности трассировки, которые можно использовать для этой цели.
Например: скрытая копия (некоторые дистрибутивы называют это bpfcc-tools
) иметь tcpconnect утилита, которая делает именно это. Вот отрывок из официального пример:
TIME(s) PID COMM IP SADDR DADDR DPORT
31.871 2482 local_agent 4 10.103.219.236 10.251.148.38 7001
31.874 2482 local_agent 4 10.103.219.236 10.101.3.132 7001
31.878 2482 local_agent 4 10.103.219.236 10.171.133.98 7101
90.917 2482 local_agent 4 10.103.219.236 10.251.148.38 7001
90.928 2482 local_agent 4 10.103.219.236 10.102.64.230 7001
90.938 2482 local_agent 4 10.103.219.236 10.115.167.169 7101
Другая возможность - это bpftrace утилиты, у которых есть похожие tcpconnect инструмент.
Или вы даже можете использовать простой ftrace (но в этом случае вам нужно будет написать скрипт, который будет декодировать структуру sockaddr, или делать это вручную). Например:
# Enable probe
echo 'p:tcp/connect tcp_connect sock=+0(%di):x8[32] prog=$comm' > /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/tcp/connect/enable
# Wait time till connect would be called by apps and check trace buffer
cat /sys/kernel/debug/tracing/trace # note sockaddr data will be encoded here
# disable tracepoint when it's done
echo 0 > /sys/kernel/debug/tracing/events/tcp/connect/enable
echo '-:tcp/connect' > /sys/kernel/debug/tracing/kprobe_events
Заметка: в некоторых случаях вам может потребоваться смонтировать debugfs / tracefs.
Вы также можете использовать grep для огромных журналов, которые вы получаете от "ausearch -i", чтобы увидеть только те сокеты, которые успешно подключились к другому хосту в Интернете. Я написал упрощенный скрипт для получения каждого процесса и команды, которые создали сокет для подключения к хосту в Интернете, вместе с адресом подключения этого целевого хоста и текущим временем, когда сокет был «создан». Вот:
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "You must run this script as root boy!"
exit 1
fi
> proccessConnections.dat
connections=`ausearch -i | grep host: | awk -F "msg=audit" '{print $2}' | awk -F ": saddr" '{print $1}'`
connectionsNumber=`echo "$connections" | wc -l`
echo "Number of connections: $connectionsNumber"
echo "$connections" > conTemp.dat
let counter=1
while read connectInfo; do
success=`ausearch -i | grep "$connectInfo" | grep "type=SYSCALL" | grep success=yes`
addressInfo=`ausearch -i | grep "$connectInfo" | grep type=SOCKADDR | awk -F ': ' '{print $2}'`
processInfo=`ausearch -i | grep "$connectInfo" | grep "type=SYSCALL" | awk -F 'comm=' '{print $2}' | awk -F 'key' '{print $1}'`
if [[ $success != "" ]]
then
echo "[$counter - $connectionsNumber] (success) comm=$processInfo - $addressInfo - $connectInfo"
echo "[$counter - $connectionsNumber] (success) comm=$processInfo - $addressInfo - $connectInfo" >> proccessConnections.dat
else
echo "[$counter - $connectionsNumber] (no success) comm=$processInfo - $addressInfo - $connectInfo"
echo "[$counter - $connectionsNumber] (no success) comm=$processInfo - $addressInfo - $connectInfo" >> proccessConnections.dat
fi
let counter++
done < conTemp.dat