Introdução
Neste projeto, desenvolveremos um scanner de portas de servidor utilizando Python para detectar portas abertas em um alvo específico. Esta ferramenta é indispensável tanto para administradores de sistemas, que precisam validar políticas de segurança, quanto para profissionais de segurança que buscam mapear serviços operacionais em um host. Ao longo deste guia, exploraremos os fundamentos do escaneamento de portas, sua metodologia e aplicações práticas. Criaremos um scanner funcional e eficiente, utilizando o poder do Python e implementando threads para otimizar o tempo de execução.
O escaneamento de portas (port scanning) consiste no envio de requisições a uma série de portas de um servidor para determinar quais estão acessíveis. Este processo é vital para a manutenção da segurança e para a identificação de serviços vulneráveis. Começaremos explorando os conceitos básicos e o impacto dessa técnica.
Conceitos-Chave:
- Scanners de portas auxiliam na detecção de portas abertas em um servidor ou host.
- São utilizados em auditorias de segurança e para identificar serviços ativos que possam estar expostos.
- A forma mais simples de escaneamento envolve a tentativa de estabelecer conexões TCP em um intervalo de portas.
👀 Prévia
Aqui está uma demonstração da ferramenta que vamos construir:
python port_scanner.py 127.0.0.1 5000-9000
Saída esperada:
Opened Port: 8081
Scanning completed.
🎯 Tarefas
Neste projeto, você aprenderá:
- Como utilizar as capacidades de programação de sockets do Python para interagir com portas de rede.
- Como implementar uma abordagem multi-threaded em Python para acelerar tarefas de varredura de rede.
- Como desenvolver uma ferramenta de linha de comando em Python que aceita entradas do usuário para um escaneamento flexível.
🏆 Conquistas
Após concluir este projeto, você será capaz de:
- Usar a biblioteca
socketdo Python para criar conexões de rede, testar a disponibilidade de portas e tratar exceções de rede. - Compreender e aplicar multi-threading em Python para executar tarefas concorrentes, melhorando significativamente o desempenho em operações intensivas de rede.
- Construir um scanner de portas prático via linha de comando, aprimorando suas habilidades de scripting e manipulação de argumentos.
Estabelecendo Testes de Conexão TCP
Nosso primeiro passo consiste em escrever uma função para testar se uma porta TCP está aberta no IP de destino. Esta função tentará se conectar a uma porta específica e determinará seu status.
Abra o arquivo chamado port_scanner.py no diretório /home/labex/project e adicione a seguinte função Python:
import argparse
from queue import Queue
from socket import AF_INET, gethostbyname, socket, SOCK_STREAM
import threading
def tcp_test(port: int, target_ip: str) -> None:
with socket(AF_INET, SOCK_STREAM) as sock:
sock.settimeout(1)
result = sock.connect_ex((target_ip, port))
if result == 0:
print(f"Opened Port: {port}")
Este código define a função tcp_test, que tenta estabelecer uma conexão TCP com uma porta específica no endereço IP alvo. Definimos um tempo limite (timeout) para evitar esperas prolongadas em cada porta e utilizamos o método connect_ex para realizar a tentativa.
Se o connect_ex retornar 0, isso indica que a conexão foi bem-sucedida, o que significa que a porta está aberta. Nesse caso, a função exibe uma mensagem informando a porta encontrada.
Configurando Verificações de Portas Concorrentes
Em seguida, criaremos uma função worker que será utilizada por cada thread para processar as portas de uma fila (queue) e utilizar a função tcp_test para verificar o status de cada uma.
Adicione o seguinte código ao seu arquivo port_scanner.py:
def worker(target_ip: str, queue: Queue) -> None:
while not queue.empty():
port = queue.get()
tcp_test(port, target_ip)
queue.task_done()
A função worker foi projetada para ser executada por múltiplas threads simultaneamente. Ela recupera continuamente números de portas de uma fila e utiliza a função tcp_test definida anteriormente para checar se essas portas estão abertas no IP alvo.
Após testar uma porta, ela marca a tarefa como concluída na fila. Esta função permite o escaneamento concorrente, o que acelera drasticamente o processo de varredura.
Orquestrando o Processo de Escaneamento
A função main orquestra todo o processo, configurando a fila, inicializando as threads de trabalho e gerenciando a operação de varredura sobre o intervalo de portas especificado.
Continue adicionando a função main ao seu port_scanner.py:
def main(host: str, start_port: int, end_port: int) -> None:
target_ip = gethostbyname(host)
queue = Queue()
for port in range(start_port, end_port + 1):
queue.put(port)
for _ in range(100): ## Ajuste o número de threads se necessário
t = threading.Thread(target=worker, args=(target_ip, queue,))
t.daemon = True
t.start()
queue.join()
print("Scanning completed.")
A função main é o coração do script.
Primeiro, ela resolve o nome do host para um endereço IP e cria uma fila para as portas que serão escaneadas. Ela preenche essa fila com todas as portas do intervalo definido e inicia múltiplas threads (100 neste exemplo) que processam a fila de forma concorrente. A função aguarda até que todas as portas tenham sido processadas (queue.join()) e então exibe uma mensagem indicando a conclusão do trabalho.
Executando o Scanner de Portas
Finalmente, é hora de colocar nosso scanner para funcionar. Vamos varrer um intervalo de portas no localhost para testar a ferramenta.
Adicione as seguintes linhas ao final do seu arquivo port_scanner.py para tornar o script executável via terminal:
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='TCP Port Scanner')
parser.add_argument('host', help='Host to scan')
parser.add_argument('ports', help='Port range to scan, formatted as start-end')
args = parser.parse_args()
start_port, end_port = map(int, args.ports.split('-'))
main(args.host, start_port, end_port)
Este trecho utiliza a biblioteca argparse para lidar com argumentos de linha de comando, tornando o script versátil e fácil de usar.
- O argumento
hostdefine o endereço ou nome do host alvo. - O argumento
portsespera uma string no formato "início-fim" (ex: "5000-8000"), que o script divide emstart_porteend_portusando o delimitador-e converte para inteiros.
Agora, execute o scanner rodando o seguinte comando no terminal:
python port_scanner.py 127.0.0.1 5000-9000
Saída:
Opened Port: 8081
Scanning completed.
Agora que você identificou uma porta aberta (8081), indicando que há um servidor web rodando nela, você pode explorar o que está sendo hospedado.
Para fazer isso, primeiro clique no botão de adicionar e selecione a opção "Web Service".

Em seguida, digite a porta 8081 e clique no botão "Access".

Você verá o servidor web em execução no seu sistema, escutando na porta 8081.

Resumo
Neste projeto, construímos um scanner de portas básico com Python, partindo da função fundamental tcp_test até uma implementação multi-threaded robusta. Dividimos o processo em etapas gerenciáveis, resultando em uma ferramenta funcional capaz de identificar portas abertas em um servidor. Através desta experiência prática, não apenas aprofundamos nosso conhecimento em segurança de rede, mas também aprimoramos nossas habilidades em programação Python e gerenciamento de concorrência.



