bash script: capturar o tráfego tcp em um servidor remoto às vezes funciona, às vezes falha. Sem erros

3

Plano de fundo

Estou executando o BusyBox no servidor remoto.

Eu tenho um script bash que faz duas coisas:
1. via ssh, inicia um subprocesso para monitorar o tráfego tcp usando o comando tcpdump. Salve os resultados em um arquivo - na máquina remota ou na máquina local. Tentei ambos.
2. inicia um segundo subprocesso para gerar tráfego tcp.

Snippet de código:

#html_tcpdumpfile="$(ssh remotemachine.mydomain.net \"mktemp\")"
html_tcpdumpfile=$(mktemp)

test_steps=(
    #"{ ssh remotemachine.mydomain.net \"timeout -t 20 tcpdump -nvi eth0 port 5060 > "$html_tcpdumpfile" \" ; }" 
    "{ ssh remotemachine.mydomain.net \"timeout -t 20 tcpdump -i eth0 port 5060 \"> $html_tcpdumpfile; }"   
    "{ ssh remotemachine.mydomain.net \"timeout -t 15 cat /tmp/htmlemail.txt | /etc/postfix/process_email.py \"; }"
 )
pids=()
for index in ${!test_steps[@]}; do       
      (echo "${test_steps[$index]}" | bash) &
      pids[${index}]=$!
      echo "$pids[${index}] is the pid"
done

#shouldn't really need this because of the timers but... just in case...
for pid in ${pids[*]}; 
do   
  wait $pid; 
done;
# ============ ANALYZE TEST RESULTS
echo "========== html_tcpdumpfile CONTENTS ============="
cat $html_tcpdumpfile
echo "========== html_tcpdumpfile CONTENTS ============="

Problema

Às vezes, o comando tcpdump não captura nada, e outras vezes acontece. Não há mensagens de erro quando não consegue capturar.

O que eu tentei até agora

  1. Como você pode ver, tentei alterar a localização do arquivo de despejo entre a máquina remota e a local. Isso não parece fazer diferença.

  2. Eu provei que o tráfego TCP SEMPRE é gerado ... cada vez que executo o script porque tenho outra sessão ssh aberta e consigo ver o tráfego sendo gerado. É só que o meu script falha intermitentemente em capturá-lo.

  3. Eu tentei aumentar o valor de tempo limite na sessão tcp para algo enorme, para ter certeza de dar tempo suficiente. Mas não acho que seja esse o problema.

Qualquer sugestão seria apreciada. Obrigado.

EDIT 1

Eu tentei introduzir um sono entre o lançamento de cada subprocesso:

pids=()
for index in ${!test_steps[@]}; do       
      (echo "${test_steps[$index]}" | bash) &
      sleep 5
      pids[${index}]=$!
      echo "$pids[${index}] is the pid"
done

Mas isso também não faz diferença.

EDIT 2

Eu mudei o comando tcpdump para ficar assim:

test_steps=(     
    "{ ssh remotemachine.mydomain.net \"timeout -t 30 tcpdump -nlc 100 -i eth0 port 5060 \"> $rtf_tcpdumpfile; }" 
    "{ ssh remotemachine.mydomain.net \"timeout -t 20 tail -f /var/log/messages \" > $syslog; }"    
    "{ ssh remotemachine.mydomain.net \"timeout -t 15 cat /tmp/htmlemail.txt | /etc/postfix/process_email.py \"; }"
 )

O tcpdump ainda não consegue capturar de forma intermitente, mas ... o interessante é que o syslog é sempre capturado com sucesso. (o script python realmente grava no syslog quando é invocado e assim posso ver / provar que o script está funcionando)

    
por dot 15.02.2018 / 15:28

1 resposta

2

Primeiramente, se você está lidando com um appliance / iOT com um espaço limitado, eu lidaria com a saída no lado de chamada, ou seja, usando o > depois dos comandos ssh como em

ssh "command" > output.txt

Quanto a tcpdump , eu não o mataria como uma política o tempo todo, arriscando perder buffers. Você pode não ter saído talvez por causa disso.

Eu colocaria um limite nos pacotes capturados. Eu também tentaria não resolver o DNS. Como em, para capturar 100 pacotes:

tcpdump -nc 100 -i eth0 port 5600

Quando você está armazenando o arquivo de captura no sistema local, só deve executar cat localmente e não remotamente e localmente.

Da mesma forma, quando você está executando os níveis tcpdump e cat remotamente, você está lançando os dois ao mesmo tempo e tanto ocat local quanto o remoto não terão nada para mostrar.

Seguindo a sugestão de @MarkPlotnick, também adicionei -l a tcpdump para torná-la em buffer. Isso pode evitar a necessidade da opção -c . Eu usaria ambos.

Então, eu mudaria esse script para:

#!/bin/bash
html_tcpdumpfile=$(mktemp)

ssh remotemachine.mydomain.net "timeout -t 20 tcpdump -nlc 100 -i eth0  port 5060 " > $html_tcpdumpfile

cat $html_tcpdumpfile

rm $html_tcpdumpfile

Ou talvez nem precisemos criar explicitamente um arquivo temporário:

#!/bin/bash

ssh remotemachine.mydomain.net "timeout -t 20 tcpdump -nlc 100 -i eth0  port 5060 " \
| less

Por fim, aconselho a exclusão de todos os arquivos temporários criados, especialmente no lado remoto.

PS: o OP mencionado nos comentários do sistema remoto é BusyBox e, como tal, as opções timeout são diferentes do pacote coretutils . Eu também edito a pergunta para ela mencionar o BusyBox.

    
por 15.02.2018 / 17:46