nc: ligação falhou: Endereço já em uso

5

Estou tentando executar o comando nc a partir de um script, meu script está executando o comando nc em diferentes portas de destino usando a mesma porta de origem.

por exemplo:

nc -p 8140 -z -v -n 10.X.X.9 9090
nc -p 8140 -z -v -n 10.X.X.9 9091
nc -p 8140 -z -v -n 10.X.X.9 9092
nc -p 8140 -z -v -n 10.X.X.9 9093
and so on ...

Após a execução do primeiro nc, para o restante de todas as linhas, recebo a mensagem de erro abaixo mencionada.

nc: bind failed: Address already in use
nc: bind failed: Address already in use
nc: bind failed: Address already in use

Existe alguma maneira de evitar essa situação?

    
por saurav 24.03.2014 / 22:27

2 respostas

10

Antecedentes

Quando você está tentando usar nc desta maneira, ele continua mantendo a porta TCP aberta, esperando que o destino confirme o recebimento da solicitação concluída. Isso é destacado no artigo do TCP na Wikipedia .

TIME-WAIT

(either server or client) represents waiting for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request. [According to RFC 793 a connection can stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).]

Você pode ver os efeitos disso quando eu uso nc da mesma forma:

$ nc -p 8140 -v -n 192.168.1.105 80

Olhando para o estado da porta 8140:

$ netstat -anpt | grep 8140
tcp        0      0 192.168.1.3:8140       192.168.1.105:80         TIME_WAIT   -

Na verdade, na maioria dos sistemas Linux, esse TIME_WAIT está definido para 60 segundos.

$ cat /proc/sys/net/ipv4/tcp_fin_timeout
60

Se você quiser ver o efeito você mesmo, você pode usar este snippet para assistir quando a porta for liberada.

$ date; nc -p 8140 -v -n 192.168.1.105 80 -w 1; date; \
    while netstat -anpt | grep 8140; do date; sleep 10; done; date
Tue Mar 25 09:46:59 EDT 2014
Connection to 192.168.1.105 80 port [tcp/*] succeeded!
Tue Mar 25 09:47:00 EDT 2014
tcp        0      0 192.168.1.3:8140       192.168.1.105:80        TIME_WAIT   -
Tue Mar 25 09:47:00 EDT 2014
tcp        0      0 192.168.1.3:8140       192.168.1.105:80        TIME_WAIT   -
Tue Mar 25 09:47:10 EDT 2014
tcp        0      0 192.168.1.3:8140       192.168.1.105:80        TIME_WAIT   -
Tue Mar 25 09:47:20 EDT 2014
tcp        0      0 192.168.1.3:8140       192.168.1.105:80        TIME_WAIT   -
Tue Mar 25 09:47:30 EDT 2014
tcp        0      0 192.168.1.3:8140       192.168.1.105:80        TIME_WAIT   -
Tue Mar 25 09:47:40 EDT 2014
tcp        0      0 192.168.1.3:8140       192.168.1.105:80        TIME_WAIT   -
Tue Mar 25 09:47:50 EDT 2014
Tue Mar 25 09:48:00 EDT 2014
$

Método 1 - usando nc

A liberação da porta 8140 leva algum tempo para ocorrer. Você precisará aguardar até que seja totalmente liberado (colocar algumas horas de descanso seria uma maneira fácil) ou usar uma porta diferente.

Se você quer apenas ver se o port @ host está aberto ou não, você pode simplesmente descartar o -p 8140 .

$ nc -zv -n 10.X.X.9 9090-9093

Exemplo

$ nc -zv -n 192.168.1.200 2024-50000 |& grep -v refu
Connection to 192.168.1.200 5672 port [tcp/*] succeeded!
Connection to 192.168.1.200 35766 port [tcp/*] succeeded!

OBSERVAÇÃO: Você pode se sentir tentado a adicionar a opção -w a nc , que o instrui a aguardar apenas um determinado período de tempo. Por padrão, nc esperará para sempre. Então seu comando seria algo assim:

$ nc -p 8140 -zv -n 10.X.X.9 9090 -w 1

No entanto, nos meus testes em um sistema CentOS 5.9 usando 1.84, ele continuou a manter a porta em uso posteriormente, então o melhor que você pode fazer é usar -w 60 , já que é o menor tempo até TIME_WAIT entra em vigor.

Método 2 - usando o nmap

Se você quiser usar um aplicativo mais apropriado para verificar um conjunto de portas, sugiro usar nmap .

$ sudo nmap -sS --source-port 8140 -p 9090-9093 10.X.X.9

Exemplo

$ sudo nmap -sS --source-port 8140 -p 80-85 homer

Starting Nmap 6.40 ( http://nmap.org ) at 2014-03-24 21:22 EDT
Nmap scan report for homer (192.168.1.105)
Host is up (0.0059s latency).
PORT   STATE  SERVICE
80/tcp open   http
81/tcp closed hosts2-ns
82/tcp closed xfer
83/tcp closed mit-ml-dev
84/tcp closed ctf
85/tcp closed mit-ml-dev
MAC Address: 00:18:51:43:84:87 (SWsoft)

Nmap done: 1 IP address (1 host up) scanned in 11.36 seconds

Aqui eu configurei um filtro usando iptraf para provar que o tráfego está saindo para essas portas usando a porta de origem do 8140.

OBSERVAÇÃO: Preste atenção especial a # 1 no diagrama, que mostra a porta de origem 8140, enquanto # 2 mostra um par de minhas portas de destino que eu selecionei, principalmente 80 & 83.

Referências

por 24.03.2014 / 22:57
1

Acho que também pode ser uma resposta, pelo menos é legível:

i=0 ; until { 
    nc -p 8140 -av -n 10.X.X.9 909${i} &&
        [ $((i=i+1)) -gt 4 ]
} 2>&- 
    do sleep 1 
done

A verdade é que @ slm tem um ponto sobre nmap - lidar com sua rede e testar a caneta é uma ferramenta indispensável e definitivamente vale a pena se familiarizar com ela. Mas para testar a conectividade entre apenas duas máquinas em um ambiente 5: 1 configuração de porta, pode ser um pouco demais. Então, novamente, talvez esta seja uma oportunidade perfeita para aprender a usá-lo.

De qualquer forma, se você não tem isso à sua disposição, netcat é extremamente flexível. E, talvez mais importante, nc não exige su root para fazer 0 i / o ops como nmap .

Na resposta acima, basta usar $i para substituir o último dígito de sua porta de destino por 0 em sua primeira rodada e $i 's valor incrementado depois disso. Porque, como eu acredito, nc deve retornar um true desde que ele possa vincular sua porta local, a variável $i só aumentará se 8140 estiver aberto e nc puder usá-lo para discar.

$i é incrementado em um teste para garantir que você não ultrapasse o intervalo de portas 9094 que você especificou, quando finalmente ele será retornar true satisfazendo until e encerrando o loop.

Falando nisso, until você pode bind o local 8140 -p ort seu loop sleep 1 segundo (como @slm recomenda) antes de tentar novamente.

Eu acabei de soltar stderr com 2>&- para que você não precise ver não foi possível vincular ... mensagens spamming seu terminal. Como está escrito, isso pode nunca ser necessário, pois sleep é chamado a cada vez que $i é incrementado também - exceto o último quando o loop quebra de qualquer maneira - então a pausa de 1 segundo entre as iterações talvez seja suficiente para eliminar a porta local vinculada e abri-la novamente para uso na próxima iteração.

Se, de alguma forma, eu tiver confundido o valor de retorno nc e returns false mesmo que possa proteger 8140 localmente, mas o A porta de destino está fechada, que é facilmente tratada com um uso um pouco mais específico de $? - é só me avisar.

    
por 25.03.2014 / 04:59