Comando Linux obter porta não utilizada


20

Estou procurando um comando ou script que retorne uma porta não utilizada no meu sistema Linux Ubuntu. Eu procurei na internet e a única coisa que encontro é sobre a porta usada / Listen com o comando nestat. Aparentemente, algo com o comando netstat funcionará, mas não sabe exatamente o que. Alguma idéia de como?

Obrigado.



1
Por que você precisa fazer exatamente isso? Se você estiver desenvolvendo um servidor, poderá vincular à porta 0 e o sistema operacional alocará uma porta gratuita para você, não há nada a pesquisar. Caso contrário, procurar e vincular é propenso a condições de corrida. Veja, por exemplo, stackoverflow.com/questions/1365265/… ou stackoverflow.com/questions/1075399/…
Patrick Mevzek

Respostas:


14

netstat -latfornece a lista completa de portas de escuta e estabelecidas .

Quando uma porta não está em nenhum desses estados, não existe para o sistema, portanto, você não encontrará um comando que mostre a lista de portas não utilizadas.

Lembre-se de que existem 65535 portas; portanto, qualquer coisa que não netstat -latesteja ativada é uma porta não utilizada.

O script bash a seguir fará uma varredura simples das portas tcp e informará quais estão abertas e quais estão fechadas :

#!/bin/bash
IP=$1
first_port=$2
last_port=$3
function scanner

{
for ((port=$first_port; port<=$last_port; port++))
        do
                (echo >/dev/tcp/$IP/$port)> /dev/null 2>&1 && echo $port open || echo "$port closed"
        done
}

scanner

Se você salvá-lo como portscan.sh , ele deve ser executado como ./portscan.sh IP first_port last_port , por exemplo: ./portscan 127.0.0.1 20 135varrerá o equipamento local das portas 20 a 135


7

Ruby 2.x (uma linha):

ruby -e 'require "socket"; puts Addrinfo.tcp("", 0).bind {|s| s.local_address.ip_port }'

Na minha máquina agora que imprimia:

42644

Uma chamada subsequente impressa:

36168

Essa técnica faz com que o usuário atual solicite uma porta não utilizada (vincule à porta "0") e imprima o número da porta que o sistema operacional forneceu. E como o usuário atual é quem pergunta, as portas abaixo de 1024 não serão retornadas (a menos que o usuário atual seja root).

Crédito onde o crédito é devido - esta solução vem de um comentário de Franklin Yu em unix.stackexchange.com's Qual é a maneira mais fácil de encontrar uma porta local não utilizada?


Como eu poderia atribuir o resultado disso a uma variável em um script bash?
Neil Stevens

export PORT = $ (ruby -e 'require "socket"; coloca Addrinfo.tcp ("", 0) .bind {| s | s.local_address.ip_port}')
G. Sylvie Davies

3

Script bash curto que gera aleatoriamente um número entre 1025 e 60000 e faz loops até que esse número não seja encontrado na lista de portas usadas. Esta é uma solução rápida e suja, com viés para portas maiores:

CHECK="do while"

while [[ ! -z $CHECK ]]; do
    PORT=$(( ( RANDOM % 60000 )  + 1025 ))
    CHECK=$(sudo netstat -ap | grep $PORT)
done

echo $PORT

Verifique se o seu comando grep, veja comentário sobre adarshr resposta
Nick

2

One-liner

Eu montei um belo one-liner que serve rapidamente a esse objetivo, permitindo pegar um número arbitrário de portas em um intervalo arbitrário (aqui está dividido em 4 linhas para facilitar a leitura):

comm -23 \
<(seq "$FROM" "$TO") \
<(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep '[0-9]\{1,5\}' | sort -n | uniq) \
| shuf | head -n "$HOWMANY"

Linha por linha

commé um utilitário que compara linhas classificadas em dois arquivos. Ele produz três colunas: linhas que aparecem apenas no primeiro arquivo, linhas que aparecem apenas no segundo arquivo e linhas comuns. Ao especificar -23, suprimimos as últimas colunas e mantemos apenas a primeira. Podemos usar isso para obter a diferença de dois conjuntos, expressos como uma sequência de linhas de texto. Eu aprendi sobre comm aqui .

O primeiro arquivo é o intervalo de portas que podemos selecionar. seqproduz uma sequência classificada de números de $FROMa $TO. O resultado é canalizado para commo primeiro arquivo usando a substituição do processo .

O segundo arquivo é a lista ordenada de portas, que obtemos chamando o sscomando (com -tas portas TCP intencionados, -aque significa que todos - estabelecida e ouvir - e -nnumérico - não tentar resolver, por exemplo, 22a ssh). Em seguida, escolhemos apenas a quarta coluna com awk, que contém o endereço local e a porta. Usamos cutpara dividir endereço e porta com o :delimitador e manter apenas o último ( -f2). ssTambém produzimos um cabeçalho, do qual nos livramos de grepping para seqüências não vazias de números que não são maiores que 5. Em seguida, cumprimos commo requisito de sortdigitando numerically ( -n) e eliminando duplicatas uniq.

Agora temos uma lista ordenada de portas abertas, que podemos shuffle para, em seguida, pegar o primeiro "$HOWMANY"aqueles com head -n.

Exemplo

Pegue as três portas abertas aleatórias no intervalo privado (49152-65535)

comm -23 <(seq 49152 65535) <(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep "[0-9]\{1,5\}" | sort | uniq) | shuf | head -n 3

poderia retornar por exemplo

54930
57937
51399

Notas

  • mudar -tcom -uno sspara obter as portas UDP gratuitos vez.
  • cair shufse você não estiver interessado em pegar uma porta aleatória

1
Eu gosto do seu one-liner, esta versão analisa corretamente o IPv6, por exemplo, [:: 1]: 52792 e use a opção --no-header em vez de grep. gist.github.com/fstefanov/ff4dcec7ded59514421bf944d1bb9a6f
Filip Stefanov

1

Eu precisava encontrar apenas uma única porta não utilizada aleatória e não imprimir uma lista delas. Aqui está a minha solução bash.

#/bin/bash

function random_unused_port {
    local port=$(shuf -i 2000-65000 -n 1)
    netstat -lat | grep $port > /dev/null
    if [[ $? == 1 ]] ; then
        export RANDOM_PORT=$port
    else
        random_unused_port
    fi
}

random_unused_port

E use-o fornecendo-o

$ . ./random_unused_port.sh; echo $RANDOM_PORT

Eu gosto da idéia aqui, no entanto, seu comando grep não retornará o que você pretende. O bom é que será conservador, mas se a próxima porta aleatória for 2000 e a porta 2000 estiver aberta, mas a porta 20000 estiver em uso, ela continuará procurando, portanto o resultado não será o conjunto completo de portas disponíveis.
Nick

1

Talvez outra solução baseada na lista de portas usadas:

function random_unused_port {
   (netstat --listening --all --tcp --numeric | 
    sed '1,2d; s/[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*:\([0-9]*\)[[:space:]]*.*/\1/g' |
    sort -n | uniq; seq 1 1000; seq 1 65535
    ) | sort -n | uniq -u | shuf -n 1
}

RANDOM_PORT=$(random_unused_port)

O netstatcomando gera uma lista de todas as portas abertas. O sedcomando extrai os números de porta que estão em uso e a construção sort/ uniqretorna uma lista uniq de portas abertas. O segundo passo é gerar uma lista de números de portas começando em 1 e terminando em 1000 (portas reservadas) e uma lista adicional de todos os números de portas que começam em 1 até 65535. A lista final contém todas as portas disponíveis apenas uma vez e as uniq -uextrairá . Por último, o shuf -n 1selecionará uma porta aleatória da lista completa de portas disponíveis. No entanto, haverá uma condição de corrida, antes que se consiga reservar o porto.


1

Eu precisava encontrar a próxima porta aberta a partir de um número de porta; Aqui está minha tentativa de usar a solução @Taras.

_check="placeholder"
START_FROM=1900
PORT=$(( ( "$RANDOM" % 1000 ) + $START_FROM ))
while [[ ! -z "${_check}" ]]; do
    ((PORT++))
    _check=$(ss -tulpn | grep ":${PORT}")
done

0

Se 54321 é sua porta, execute:

sudo netstat -ap |grep 54321

Algumas variações do uso do netstat podem ser encontradas aqui .


Este comando só vai me mostrar se a porta 54321 está em uso ou não. O que eu quero é encontrar uma porta não utilizada.
user2429082

Não utilizado é ambíguo. Deseja verificar qual porta está disponível para ouvir? Ou qual porta está disponível para conexão? Qualquer um que não esteja em uso estará disponível. Como usuário, você pode usar os acima de 1024, como root, você pode usar também os sob 1024.
Overmind
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.