Znalezienie krótkotrwałego procesu właściciela połączenia TCP

15

Działając tcpdumpna lokalnych połączeniach z serwerem Apache, zauważyłem, że połączenia TCP są nawiązywane i zamykane natychmiast co 2 sekundy. Jak znaleźć proces, który jest za nie odpowiedzialny? netstat -ctpnie pomogło, połączenia były zbyt szybkie i identyfikator procesu nie jest wyświetlany dla TIME_WAIT.

Okazały się sondami haproksy, które mogłem zweryfikować strace, ale nadal nie wiem, jak to dokładnie określić.

pmezard
źródło

Odpowiedzi:

20

Możesz użyć kontrolowanego frameworka do tego typu rzeczy. Nie są zbyt „przyjazne dla użytkownika” ani intuicyjne, więc wymagają trochę pogrzebania z twojej strony.

Najpierw upewnij się, że masz zainstalowany audyt, działasz i że jądro go obsługuje.
W systemie Ubuntu możesz apt-get install auditdna przykład go zainstalować .

Następnie dodajesz connectzasadę audytu, aby monitorować wszystkie takie wywołania systemowe:

auditctl -a exit,always -F arch=b64 -S connect -k MYCONNECT

Jeśli używasz 32-bitowej instalacji systemu Linux, musisz zmienić b64 na b32.

To polecenie wstawi zasady do struktury kontroli, a wszystkie wywołania systemowe connect () będą teraz logowane do twoich plików dziennika kontroli (zwykle /var/log/audit/audit.log), abyś mógł je obejrzeć.

Na przykład połączenie z netcat do portu 80 news.ycombinator.com spowoduje coś takiego:

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

Tutaj możesz zobaczyć, że aplikacja /bin/nc.openbsd zainicjowała wywołanie connect (), jeśli otrzymujesz wiele wywołań połączenia i chcesz tylko wyodrębnić określony adres IP lub port, musisz wykonać konwersję. Linia SOCKADDR zawiera argument saddr, zaczyna się od 0200, po którym następuje numer portu w systemie szesnastkowym (0050), co oznacza 80, a następnie adres IP w systemie szesnastkowym (AE84E16A), który jest adresem IP news.ycombinator.com na poziomie 174.132.225.106.

Struktura audytu może generować wiele dzienników, więc pamiętaj, aby ją wyłączyć po zakończeniu misji. Aby wyłączyć powyższe zasady, po prostu zamień -a na -d jako takie:

auditctl -d exit,always -F arch=b64 -S connect -k MYCONNECT

Dobra dokumentacja ram audytu:
http://doc.opensuse.org/products/draft/SLES/SLES-security_sd_draft/part.audit.html

Konwertuj adresy IP na / z hex, dec, binarne itp. Na:
http://www.kloth.net/services/iplocate.php

Ogólny konwerter hex / dec:
http://www.statman.info/conversions/hexadecimal.html

Krótkie wprowadzenie do audytu z IT Security Stack Exchange. http://security.blogoverflow.com/2013/01/a-brief-introduction-to-auditd/

Edycja 1 :
Innym szybkim i trzydziestym (szwedzkim: fulhack) sposobem jest utworzenie szybkiej pętli, która zrzuca dane połączenia do Ciebie, w następujący sposób:

while true;do
  ss -ntap -o state established '( dport = :80 )'
  sleep 1
done

To polecenie używa sspolecenia (statystyki gniazda), aby zrzucić bieżące ustanowione połączenia z portem 80, w tym proces zainicjowany. Jeśli jest to dużo danych, które możesz dodać | tee /tmp/outputpo zakończeniu, aby zarówno wyświetlić dane wyjściowe na ekranie, jak i zapisać je w katalogu / tmp / output w celu późniejszego przetwarzania / kopania. Jeśli nie uda się złapać szybkiego połączenia haproxy, spróbuj usunąć, sleep 1ale zachowaj ostrożność przy rozległym logowaniu, jeśli jest to mocno używana maszyna. Zmodyfikuj w razie potrzeby!

Mattias Ahnberg
źródło
Dziękuję za szczegółową odpowiedź. Uwierzę ci za sprawdzone rozwiązanie, ponieważ jądro hosta go nie obsługuje i nie mam teraz czasu na znalezienie odpowiedniego do eksperymentowania, ale będę o tym pamiętać. Jeśli chodzi o rozwiązanie ankietowania, zacząłem robić coś podobnego z lsof, ale przestałem dość szybko, ponieważ nie było ... satysfakcjonujące.
pmezard
2
Możesz także użyć ausearch -ido saddrautomatycznego dekodowania tych ciągów heksadecymalnych.
sch
ss jest bardziej satysfakcjonujący niż lsof, ponieważ jest szybszy i ma dobre reguły filtrowania - nie ma potrzeby grep. Rozumiem problemy ze wsparciem: Systemtap to kolejne doskonałe narzędzie, ale uruchomienie go na serwerze produkcyjnym może być ... niezadowalające.
Max Murphy
1

Możesz także grep ogromne logi, które otrzymujesz z "ausearch -i", aby zobaczyć tylko te gniazda, które pomyślnie nawiązały połączenie z innym hostem w Internecie. Napisałem uproszczony skrypt, aby pobrać każdy proces i polecenie, które utworzyło gniazdo do połączenia z hostem w Internecie wraz z adresem połączenia tego hosta docelowego i bieżącym czasem, w którym gniazdo zostało „utworzone”. Oto on:

#!/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
Marcelo Silva
źródło