Você já deve ter ouvido falar do Nmap e de escaneamento de portas em servidores, bem, nesse script feito em Python vamos fazer algo bem semelhante, vamos verificar as portas abertas em websites. Vamos explorar um pouco de maneira simples e fácil de entender
Introdução
Portas abertas em um servidor são como portas de entrada para diferentes serviços. Saber quais portas estão abertas pode ajudar você a entender melhor a segurança do seu site ou simplesmente satisfazer sua curiosidade sobre o funcionamento interno de um site. Vamos mergulhar em um script que escaneia essas portas usando Python.
Código completo
import socket
import argparse
from concurrent.futures import ThreadPoolExecutor
# Função para verificar uma única porta
def scan_port(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1) # Define um timeout de 1 segundo
try:
sock.connect((host, port))
return port, True
except (socket.timeout, socket.error):
return port, False
finally:
sock.close()
# Função para escanear uma lista de portas
def scan_ports(host, ports, max_workers=100):
open_ports = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(scan_port, host, port) for port in ports]
for future in futures:
port, is_open = future.result()
if is_open:
open_ports.append(port)
return open_ports
# Mapear portas para serviços comuns
port_service_map = {
21: 'ftp', 22: 'ssh', 23: 'telnet', 25: 'smtp', 53: 'domain', 80: 'http',
110: 'pop3', 123: 'ntp', 135: 'msrpc', 139: 'netbios-ssn', 143: 'imap',
161: 'snmp', 194: 'irc', 389: 'ldap', 443: 'https', 445: 'microsoft-ds',
465: 'smtps', 512: 'exec', 513: 'login', 514: 'shell', 587: 'submission',
636: 'ldaps', 873: 'rsync', 990: 'ftps', 993: 'imaps', 995: 'pop3s',
1080: 'socks', 1194: 'openvpn', 1433: 'ms-sql-s', 1434: 'ms-sql-m',
1521: 'oracle', 1723: 'pptp', 3306: 'mysql', 3389: 'ms-wbt-server',
5060: 'sip', 5432: 'postgresql', 5900: 'vnc', 5984: 'couchdb', 6379: 'redis',
6667: 'irc', 8000: 'http-alt', 8080: 'http-proxy', 8443: 'https-alt',
8888: 'sun-answerbook', 9000: 'cslistener', 9200: 'wap-wsp', 10000: 'webmin',
11211: 'memcached', 27017: 'mongodb'
}
def main():
# Configurar o parser de argumentos
parser = argparse.ArgumentParser(description="Scan ports on a specified website")
parser.add_argument("website", help="The website to scan, e.g., www.example.com")
args = parser.parse_args()
# Obter o site a partir dos argumentos
website = args.website
# Definir as portas a serem escaneadas (ports mais comuns escaneadas pelo nmap)
ports_to_scan = list(port_service_map.keys())
# Obter o endereço IP do site
try:
host = socket.gethostbyname(website)
except socket.gaierror:
print(f"Não foi possível resolver o hostname: {website}")
return
print(f"Iniciando escaneamento de {website} ({host})...")
# Escanear as portas e exibir as portas abertas
open_ports = scan_ports(host, ports_to_scan)
print(f"PORTA ESTADO SERVIÇO")
for port in ports_to_scan:
state = "aberta" if port in open_ports else "fechada"
service = port_service_map.get(port, "unknown")
print(f"{port:<9} {state:<12} {service}")
print("Escaneamento concluído.")
if __name__ == "__main__":
main()
Explicação do Script
Nosso script utiliza algumas bibliotecas essenciais do Python: socket
, argparse
e concurrent.futures.ThreadPoolExecutor
. Aqui está um passo a passo do que cada parte do script faz:
Importações e Configurações Iniciais
import socket
import argparse
from concurrent.futures import ThreadPoolExecutor
Esses comandos importam os módulos necessários para o nosso script. socket
é usado para criar conexões de rede, argparse
para lidar com argumentos de linha de comando, e concurrent.futures.ThreadPoolExecutor
para executar tarefas em paralelo, aumentando a eficiência do nosso escaneamento de portas.
Função para Verificar uma Porta
def scan_port(host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1) # Define um timeout de 1 segundo
try:
sock.connect((host, port))
return port, True
except (socket.timeout, socket.error):
return port, False
finally:
sock.close()
A função scan_port
tenta conectar a uma porta específica em um host. Se a conexão for bem-sucedida, a porta está aberta; caso contrário, está fechada. O timeout de 1 segundo garante que a tentativa de conexão não demore muito.
Função para Escanear Múltiplas Portas
def scan_ports(host, ports, max_workers=100):
open_ports = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(scan_port, host, port) for port in ports]
for future in futures:
port, is_open = future.result()
if is_open:
open_ports.append(port)
return open_ports
A função scan_ports
utiliza ThreadPoolExecutor
para escanear várias portas ao mesmo tempo. Ela cria uma lista de tarefas, cada uma verificando uma porta diferente, e armazena as portas abertas em uma lista.
Mapeamento de Portas para Serviços Comuns
port_service_map = {
21: 'ftp', 22: 'ssh', 23: 'telnet', 25: 'smtp', 53: 'domain', 80: 'http',
110: 'pop3', 123: 'ntp', 135: 'msrpc', 139: 'netbios-ssn', 143: 'imap',
161: 'snmp', 194: 'irc', 389: 'ldap', 443: 'https', 445: 'microsoft-ds',
465: 'smtps', 512: 'exec', 513: 'login', 514: 'shell', 587: 'submission',
636: 'ldaps', 873: 'rsync', 990: 'ftps', 993: 'imaps', 995: 'pop3s',
1080: 'socks', 1194: 'openvpn', 1433: 'ms-sql-s', 1434: 'ms-sql-m',
1521: 'oracle', 1723: 'pptp', 3306: 'mysql', 3389: 'ms-wbt-server',
5060: 'sip', 5432: 'postgresql', 5900: 'vnc', 5984: 'couchdb', 6379: 'redis',
6667: 'irc', 8000: 'http-alt', 8080: 'http-proxy', 8443: 'https-alt',
8888: 'sun-answerbook', 9000: 'cslistener', 9200: 'wap-wsp', 10000: 'webmin',
11211: 'memcached', 27017: 'mongodb'
}
Aqui, temos um dicionário que mapeia números de portas para seus serviços comuns, como FTP, SSH e HTTP. Isso ajuda a identificar rapidamente quais serviços estão rodando nas portas abertas.
Função Principal
def main():
# Configurar o parser de argumentos
parser = argparse.ArgumentParser(description="Scan ports on a specified website")
parser.add_argument("website", help="The website to scan, e.g., www.example.com")
args = parser.parse_args()
# Obter o site a partir dos argumentos
website = args.website
# Definir as portas a serem escaneadas (ports mais comuns escaneadas pelo nmap)
ports_to_scan = list(port_service_map.keys())
# Obter o endereço IP do site
try:
host = socket.gethostbyname(website)
except socket.gaierror:
print(f"Não foi possível resolver o hostname: {website}")
return
print(f"Iniciando escaneamento de {website} ({host})...")
# Escanear as portas e exibir as portas abertas
open_ports = scan_ports(host, ports_to_scan)
print(f"PORTA ESTADO SERVIÇO")
for port in ports_to_scan:
state = "aberta" if port in open_ports else "fechada"
service = port_service_map.get(port, "unknown")
print(f"{port:<9} {state:<12} {service}")
print("Escaneamento concluído.")
if __name__ == "__main__":
main()
A função main
faz todo o trabalho de configurar o escaneamento. Primeiro, ela define os argumentos de linha de comando e obtém o website a ser escaneado. Depois, ela resolve o nome do host para um endereço IP e começa a escanear as portas mais comuns. Finalmente, ela exibe o estado de cada porta (aberta ou fechada) junto com o serviço correspondente.
Exemplo:
[user@hostname ]$ python scan.py www.google.com
Iniciando escaneamento de www.google.com (142.250.79.4)...
PORTA ESTADO SERVIÇO
21 fechada ftp
22 fechada ssh
23 fechada telnet
25 fechada smtp
53 fechada domain
80 aberta http
110 fechada pop3
123 fechada ntp
135 fechada msrpc
139 fechada netbios-ssn
143 fechada imap
161 fechada snmp
194 fechada irc
389 fechada ldap
443 aberta https
445 fechada microsoft-ds
465 fechada smtps
512 fechada exec
513 fechada login
514 fechada shell
587 fechada submission
636 fechada ldaps
873 fechada rsync
990 fechada ftps
993 fechada imaps
995 fechada pop3s
1080 fechada socks
1194 fechada openvpn
1433 fechada ms-sql-s
1434 fechada ms-sql-m
1521 fechada oracle
1723 fechada pptp
3306 fechada mysql
3389 fechada ms-wbt-server
5060 fechada sip
5432 fechada postgresql
5900 fechada vnc
5984 fechada couchdb
6379 fechada redis
6667 fechada irc
8000 fechada http-alt
8080 fechada http-proxy
8443 fechada https-alt
8888 fechada sun-answerbook
9000 fechada cslistener
9200 fechada wap-wsp
10000 fechada webmin
11211 fechada memcached
27017 fechada mongodb
Escaneamento concluído.
[user@hostname ]$
Considerações finais
Este script em Python é uma maneira simples e prática de verificar quais portas estão abertas em um site, o que pode ser útil para fins de segurança ou simples curiosidade.. Sinta-se à vontade para personalizar e expandir este script conforme suas necessidades e busque aprender mais sobre o mundo da programação de redes.
Top comments (0)