Penetration(pen) tester e hacker são termos semelhantes. A diferença é que pen-testers trabalham em uma organização para evitar às investidas de hackers, enquanto que um hacker geralmente trabalha para obter fama, vender vulnerabilidades por dinheiro, ou para explorar vulnerabilidades a fim de adiquirir algumas inimizades.
Hackers bem treinados trabalham no campo de segurança da informação, invadindo um sistema e informando a vítima dos bugs de segurança para que eles possam ser corrigidos.
Um hacker chamado de pentester é aquele que trabalha em uma empresa a fim de protejer seu sistema. Um pentester só inicia suas tentativas de quebrar a rede depois de obter a aprovação legal do cliente e, em seguida, apresenta um relatório de suas descobertas. Para se tornar um especialista em pentesting, uma pessoa deve ter profundo conhecimento dos conceitos de sua tecnologia. Neste capítulo, abordaremos os seguintes tópicos:
-
O escopo do pentesting
-
A necessidade do pentesting
-
Componentes a testar
-
Qualidades de um bom pentester
-
Abordagens do pentesting
-
Compreendendo os testes e ferramentas que você precisará
-
Network sockets
-
Métodos server socket
-
Métodos client socket
-
Métodos general socket
-
Exemplos práticos com socket
-
Socket exceptions
-
Métodos úteis do socket
Em simples palavras, penetration testing é o teste que avalia as políticas de segurança da informação de uma empresa. As medidas de segurança da informação envolvem a rede da empresa, banco de dados, site, servidores públicos e tudo o mais especificado pelo cliente. No final do dia, um pentester deve apresentar um relatório detalhado de suas descobertas, tais como instabilidades, vulnerabilidade na infra-estrutura da empresa, e o nível de risco da vulnerabilidade em particular, e fornecer soluções, se possível.
Existem vários pontos que descrevem o significado do pentesting:
-
O pentesting identifica as ameaças que podem expor a confidencialidade de uma organização
-
Um Expert em pentesting fornece garantia para a organização com uma avaliação completa e detalhada da segurança organizacional
-
O pentesting avalia a eficiência da rede, produzindo uma enorme quantidade de tráfego e examina a segurança de dispositivos como firewalls, roteadores e switches
-
Alterar ou atualizar a infra-estrutura de software existente, hardware ou design de rede pode levar a vulnerabilidades que podem ser detectadas por pentesting
-
No mundo de hoje, as ameaças potenciais estão aumentando significativamente; Pentesting é um exercício proativo para minimizar a chance de ser "exploitado"
-
O Pentesting garante se as políticas de segurança adequadas estão sendo seguidas ou não
Considere um exemplo de um e-commerce de nome que que gera sua renda com um serviço on-line. Um hacker ou grupo de hackers black hat encontram uma vulnerabilidade no site da empresa e a explora. Pode ser devastador a quantidade de prejuízo que eles podem causar.
Uma organização deve realizar uma operação de avaliação de risco antes do pentesting; isso ajudará a identificar as principais ameaças, como a má configuração ou vulnerabilidades em:
-
Roteadores, switches, ou gateways
-
Sistemas voltados para o público; Sites, DMZ, servidores de e-mail e sistemas remotos
-
DNS, firewalls, servidores proxy, FTP, e servidores web
O teste de segurança deve ser executado em todos os componentes de hardware e software de um sistema em rede.
Os pontos a seguir descrevem as qualidades de um bom pentester. Ele deve:
-
Escolher um conjunto adequado de testes e ferramentas que equilibram custos e benefícios
-
Seguir procedimentos adequados com planejamento e documentação adequada
-
Estabelecer o escopo de cada teste, tais como objetivos, limitações e justificativa de procedimentos
-
Estar pronto para mostrar como explorar as vulnerabilidades
-
Indicar claramente os potenciais riscos achados no relatório final e fornecer métodos para a correção dos mesmos, se possível
-
Manter-se sempre atualizado porque a tecnologia está em constante evolução
Um pentester testa a rede usando técnicas manuais ou ferramentas relevantes. Existem muitas ferramentas disponíveis no mercado. Algumas delas são de código aberto; outras muito caras. Com a ajuda da programação, você pode fazer suas próprias ferramentas. Ao criar suas próprias ferramentas, você pode esclarecer seus conceitos e também executar mais "R&D". Se você está interessado em pentesting e quer fazer suas próprias ferramentas, então a linguagem de programação Python é a melhor, pois conta com uma ampla variedade de pacotes para pentesting e é muito simples programar com ela. Esta simplicidade, juntamente com as bibliotecas de terceiros, tais como scapy e mechanize, reduz o tamanho do código. Em Python, para fazer um programa, você não precisa definir classes "gordas" como no Java. É mais produtivo escrever código em Python do que em C, e existem bibliotecas de alto nível para fazer praticamente qualquer tarefa imaginável.
Se você já sabe um pouco sobre programação com Python e está interessado em pentesting este livro é ideal para você.
Antes de entrar na fase do pentesting, o escopo do pentesting deve ser concebido. Os seguintes pontos devem ser considerados enquanto definimos o escopo:
-
Você deve desenvolver o escopo do projeto em consulta com o cliente. Por exemplo, se Bob (o cliente) quiser testar toda a infra-estrutura de rede da organização, então a pentester Alyosha definirá o escopo do pentesting levando essa rede em consideração. Alyosha consultará Bob quando houver alguma área a mais que precisa ser analizada
-
Você deve levar em conta o tempo, as pessoas e o dinheiro.
-
Você deve perfilar os limites do teste com base em um contrato assinado pelo pentester e pelo cliente.
-
As mudanças nas práticas da empresa podem afetar o escopo. Por exemplo, a adição de uma sub-rede, novas instalações de componentes, a adição ou modificação de um servidor web, e assim por diante, pode alterar o escopo do pentesting.
O escopo do pentesting é definido em dois tipos de testes:
-
Teste não destrutivo: Este teste é limitado a encontrar e executar os testes sem riscos potenciais. Ele executa as seguintes ações:
-
Escaneia e identifica potenciais vulnerabilidades no sistema remoto
-
Investiga e verifica as descobertas
-
Mapeia as vulnerabilidades com exploits apropriados
-
Exploita o sistema remoto com o devido cuidado para evitar interrupções
-
Fornece uma prova de conceito
-
Não efetua um ataque de negação de serviço(DoS)
-
-
Teste destrutivo: Este teste pode produzir riscos. Ele executa as seguintes ações:
-
Efetua ataques DoS e buffer overflows, que tem o potêncial de derrubar o sistema
-
Existem três tipos de abordagens para pentesting:
-
Black-box pentesting segue a abordagem não-determinística de testes
-
Você receberá apenas um nome de empresa
-
Você deve agir - entre aspas - como um black hat(sem conhecimento prévio da infra)
-
Não há necessidade de qualquer conhecimento prévio do sistema
-
É demorado
-
-
White-box pentesting segue a abordagem determinista de testes
-
Você receberá o conhecimento completo da infra-estrutura que precisa ser testada
-
Serão fornecidas informações sobre a infra-estrutura da empresa, o tipo de rede, as políticas da empresa, os tópicos a fazer e a não fazer, o endereço IP e o firewall IPS/IDS
-
-
Grey-box pentesting segue uma abordagem híbrida de ambas as abordagens citadas acima:
-
O pentester geralmente tem informações limitadas sobre a rede/sistema que é fornecido pelo cliente para reduzir os custos e diminuir tentativa e erro por parte do pentester
-
Ele realiza a avaliação de segurança e os testes internamente
-
Antes de começar a ler este livro, você deve conhecer os conceitos básicos da programação em Python, como a sintaxe básica, os tipos de variáveis, a estrutura de dado tupla, o dicionário, as funções, as strings, os métodos e assim por diante. Duas versões, 3.4 e 2.7.8, estão disponíveis em python.org/downloads/.
Neste livro, todas as experiências e demonstrações foram feitas em Python versão 2.7.8. Se você usa o sistema operacional Linux como Kali ou BackTrack, então não haverá nenhum problema, porque muitos programas, como snifing wireless, não funcionam na plataforma Windows. O Kali Linux também usa a versão 2.7. Se você gosta de trabalhar no Red Hat ou CentOS, então esta versão é adequada para você
A maioria dos hackers escolhem esta profissão porque eles não querem programar. Eles querem usar ferramentas. No entanto, sem programação, um hacker não pode melhorar suas habilidades. E de tempos em tempos eles procuram novas ferramentas na internet. Acredite em mim, depois de ver a sua simplicidade, você vai adorar esta linguagem.
Como você deve ter visto, este livro é dividido em sete capítulos. Para realizar varreduras e snifing pentesting, você precisará de uma pequena rede de dispositivos conectados. Se você não tem um laboratório, você pode fazer máquinas virtuais em seu computador. Para análise de tráfego sem fio, você deve ter uma rede sem fio. Para realizar um ataque na web, você precisará de um servidor Apache rodando na plataforma Linux. Será uma boa idéia usar CentOS ou Red Hat versão 5 ou 6 para o servidor web, pois contém os RPM’s do Apache e PHP. Para o script Python, vamos usar a ferramenta Wireshark, que é de código aberto e pode ser executado no Windows, bem como plataformas Linux.
Agora vamos começar a falar de pentesting; Espero que você esteja bem familiarizado com fundamentos de rede, como endereços IP, sub-redes classful, sub-redes sem classes, o significado das portas, endereços de rede e endereços de broadcast. Um pentester deve ser perfeito em fundamentos de redes, ou pelo menos entender bem um sistema operacional; Se você está pensando em usar o Linux, então você está no caminho certo. Neste livro, vamos executar nossos programas no Windows, bem como Linux. Neste livro, Windows, CentOS e Kali Linux serão usados.
Um hacker sempre gosta de trabalhar em um sistema Linux. Como é livre e de código aberto, Kali Linux marca o renascimento do BackTrack e vem com um arsenal de ferramentas de hacking. Kali Linux NetHunter é a primeira plataforma de teste de penetração Android de código aberto para dispositivos Nexus. Algumas ferramentas funcionam no Linux e no Windows, mas no Windows, geralmente essas ferramentas não funcionam. Espero que você tenha conhecimento do Linux. Agora, é hora de trabalhar com redes em Python.
Um network socket adress contém um endereço IP e um número de porta. De uma forma muito simples, um socket é uma maneira de falar com outros computadores. Por meio de um socket, um processo pode se comunicar com outro processo através da rede.
Para criar um socket, use a função socket.socket()
que está disponível no módulo socket. A sintaxe geral de uma função socket é a seguinte:
s = socket.socket (socket_family, socket_type, protocol=0)
Aqui está a descrição dos parâmetros:
socket_family: socket.AF_INET, PF_PACKET
AF_INET é a família de endereços para IPv4. PF_PACKET opera na camada de driver de dispositivo. A biblioteca pcap para Linux usa PF_PACKET. Você verá mais detalhes sobre PF_PACKET no Capítulo 3, Snifing e Penetration Testing. Esses argumentos representam as famílias de endereços eo protocolo da camada de transporte:
Socket_type : socket.SOCK_DGRAM, socket.SOCK_RAW,socket.SOCK_STREAM
O argumento socket.SOCK_DGRAM descreve que UDP é confiável e sem conexão, e socket.SOCK_STREAM descreve que o TCP é confiável e é um serviço de conexão bidirecional. Discutiremos socket.SOCK_RAW no Capítulo 3, Snifing e Penetration Testing.
protocol
Geralmente, deixamos esse argumento; recebe 0 se não for especificado. Veremos o uso deste argumento no Capítulo 3, Sniffing and Penetration Testing.
-
socket.bind(address)
: Este método é usado para conectar o endereço(endereço IP, número da porta) ao socket. O socket deve estar aberto antes de se conectar ao endereço. -
socket.listen(q)
: Este método inicia a esculta TCP. O argumento q define o número máximo de conexões line-up. -
socket.accept()
: Usado para aceitar a conexão do cliente. Antes de usar este método, os métodossocket.bind(address)
esocket.listen(q)
devem ser usados. O métodosocket.accept()
retorna dois valores:client_socket
eaddress
, ondeclient_socket
é um novo objeto socket usado para enviar e receber dados através da conexão e o address é o endereço do cliente. Você verá exemplos mais tarde.
O único método dedicado ao cliente é o:
-
socket.connect(address)
: Este método conecta o cliente ao servidor. O argumentoaddress
é o endereço do servidor.
-
socket.recv(bufsize)
: Esse método recebe uma mensagem TCP do socket. O argumentobufsize
define o máximo de dados que ele pode receber. -
socket.recvfrom(bufsize)
: Esse método recebe dados do socket. O método retorna um par de valores: o primeiro valor são dados recebidos, e o segundo valor é o endereço so socket que envia os dados. -
socket.recv_into(buffer)
: Este método recebe dados menores ou iguais abuffer
. O parâmetrobuffer
é criado pelo métodobytearray()
. Discutiremos isso em um exemplo mais adiante. -
socket.recvfrom_into(buffer)
: Esse método obtém dados do socket e os gravam no buffer. É retornado dois valores(nbytes, address), ondenbytes
é o número de bytes recebidos eaddress
é o endereço do socket que envia os dados -
socket.send(bytes)
: Este método é usado para enviar dados para o socket. Antes de enviar os dados, verifique se o socket está conectado a uma máquina remota. Retorna o número de bytes enviados. -
socket.sendto(data, address)
: Este método é utilizado para enviar dados(parâmetro data) para o socket. Geralmente, usamos esse método em UDP. UDP é um protocolo sem conexão; Portanto, o socket não deve ser conectado a uma máquina remota, e no argumento address especifique o endereço da máquina remota. O valor de retorno fornece o número de bytes enviados. -
socket.sendall(data)
: Como o nome indica, este método envia todos os dados para o socket. Antes de enviar os dados, verifique se o socket está conectado a uma máquina remota. Esse método transfere incessantemente dados até que um erro seja encontrado. Se um erro for encontrado, uma exceção é lançada, esocket.close()
fecha o socket.
Então vamos a prática!
Primeiro, vamos fazer um programa server-side que oferece uma conexão com o cliente e envia uma mensagem para o mesmo. Crie o arquivo server1.py
e adicione o seguinte código:
import socket
host = "192.168.1.2" #Server address
port = 12345 #Port of Server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port)) #bind server
s.listen(2)
conn, addr = s.accept()
print(addr, "Now Connected")
conn.send("BSD is Life")
conn.close()
O código precedente é muito simples; É o código mínimo no lado do servidor.
Primeiro, importe o módulo socket e defina o host e o número da porta: 192.168.1.2 é o endereço IP do servidor. socket.AF_INET
define a família do protocolo IPv4. Socket.SOCK_STREAM
define a conexão TCP. A instrução s.bindhost, port
leva apenas um argumento. Liga(bind) o socket ao host e número de porta. A instrução s.listen(2)
escuta a conexão e aguarda o cliente. A instrução conn, addr = s.accept()
retorna dois valores: conn e addr. O socket conn é o socket cliente, como discutimos anteriormente. A função conn.send()
envia a mensagem para o cliente. Finalmente, conn.close()
fecha o socket. A partir dos exemplos a seguir com capturas de tela, você entenderá melhor o conn
.
Saída do programa server1.py:
`$ python server1.py `
Agora o servidor está em listening(modo de escuta) aguardando o cliente:
Dê uma olhada no código do client-side. Crie o arquivo client1.py e adicione as seguintes linhas:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.2" # server address
port =12345 #server port
s.connect((host,port))
print s.recv(1024)
s.send("Hello Server")
s.close()
No código anterior, vimos dois métodos novos: s.connecthost, port
, que conecta o cliente ao servidor, e s.recv(1024)
, que recebe as strings enviadas pelo servidor.
A saída do client.py
e a resposta do servidor são mostradados na seguinte captura de tela:
A saída mostra que o servidor aceitou a conexão de 192.168.1.5
. Não se confunda com a porta 42000; É a porta aleatória do cliente. Quando o servidor envia uma mensagem para o cliente, ele usa o socket conn, como mencionado anteriormente, e este socket contém o endereço IP do cliente e o número da porta.
Como vimos na imagem acima, o servidor está no modo de escuta e o cliente se conecta ao servidor. Quando você executar o servidor/cliente novamente, a porta aleatória será alterada. Para o cliente, a porta do servidor 12345 é a porta de destino, e para o servidor, a porta aleatória do cliente 42000 é a porta de destino.
Você pode estender a funcionalidade do servidor usando o loop while, conforme mostrado no seguinte programa. Execute o programa server2.py
:
import socket
host = "192.168.1.2"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(2)
while True:
conn, addr = s.accept()
print(addr, "Conexão bem sucedida")
conn.send("BSD é VIDA!")
conn.close()
O código anterior é o mesmo que o primeiro que vimos, apenas adicionamos um loop while
infinito.
Execute o programa server2.py
em um host(no meu caso um FreeBSD), e o client1.py
em outro host(no meu caso o Fedora).
Observe o output(saída) do server2.py:
Um servidor pode responder muitos clientes. O loop while mantém o programa do servidor vivo e não permite que o código pare de rodar. Você pode definir um limite de conexão para o loop while; Por exemplo, defina while i > 10
e incremente 1 em i(i += 1) a cada conexão.
Antes de prosseguir para o próximo exemplo, o conceito de bytearray
deve ser entendido. O array bytearray
é uma sequência mutável de inteiros unsigned no intervalo de 0 a 255. Você pode excluir, inserir ou substituir valores ou pedaços isolados. Os objetos do array bytearray
podem ser criados chamando a matriz interna bytearray
.
A sintaxe geral de bytearray é:
bytearray([source[, encoding[, errors]]])
Vejamos um exemplo:
>>> m = bytearray("Heise Berg")
>>> m[1]
101
>>> m[0]
72
>>> m[:5] = "Ollar"
>>> m
bytearray(b'Ollar Berg')
>>>
Isto é um exemplo de slicing no bytearray()
.
Agora, vejamos a operação splitting no bytearray():
>>> m = bytearray("Hello Heise")
>>> m
bytearray(b'Hello Heise')
>>> m.split()
[bytearray(b'Hello'), bytearray(b'Heise')]
Em seguida temos a operação append no bytearray():
>>> m.append(33)
>>> m
bytearray(b'Hello Heise!')
>>>
No próximo exemplo utilizaremos s.recv_into(buff)
. Neste exemplo, usaremos bytearray()
para criar um buffer de armazenamento de dados.
Primeiro, execute o código server-side. segue abaixo o código do server3.py
:
import socket
host = "192.168.1.2"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
print("conectado em", addr)
conn.send("Thanks")
conn.close()
O programa anterior é o mesmo que vimos anteriormente. Neste programa, o servidor envia Thanks, seis caracteres.
Agora execute o seguinte programa client-side:
import socket
host = "192.168.1.2"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
buf = bytearray("-" * 30) # buffer criado
print("Numero de bytes ",s.recv_into(buf))
print(buf)
s.close
No programa anterior, um parâmetro buf
é criado usando bytearray()
. A instrução s.recv_into(buf)
fornece o número de bytes recebidos. O parâmetro buf
nos dá a string recebida.
Veja as imagens do exemplo apresentado:
Nosso client recebeu com sucesso uma string de 6 bytes, Thanks
. Agora, você já tem uma noção sobre bytearray()
. Espero que você se lembre.
Desta vez vou criar um socket UDP
Execute udp1.py
, e em seguida vamos discutir o código linha por linha:
import socket
host = "192.168.1.2"
port = 12346
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
data, addr = s.recvfrom(1024)
print("received from ",addr)
print("obtained ", data)
s.close()
socket.SOCK_DGRAM
cria um socket UDP, e data, addr = s.recvfrom(1024)
retornam duas coisas: primeiro são os dados e a segunda é o endereço da fonte.
Agora, veja o client-side. Execute udp2.py
:
import socket
host = "192.168.1.2"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print(s.sendto("hello all",(host,port)))
s.close()
Aqui, eu usei o socket UDP e o método s.sendto()
, como você pode ver na definição do socket.sendto()
. Você sabe muito bem que UDP é um protocolo sem conexão, então não há necessidade de estabelecer uma conexão aqui.
A seguinte captura de tela mostra a saída de udp1.py(o servidor UDP) e udp2.py(o cliente UDP):
O server recebeu os dados com êxito.
Vamos supor que um servidor está em execução e não há nenhuma conexão inicial com o cliente, pelo menos que ele tenha ouvido. Para evitar essa situação, use o socket.timeout(value)
.
Geralmente, passamos um valor inteiro; Se eu passo 5 como o valor, significa que ele vai esperar por 5 segundos. Se a operação não for concluída dentro de 5 segundos, será lançada uma exceção de tempo limite. Você também pode fornecer um valor do tipo float não-negativo.
Por exemplo, vamos olhar para o seguinte código:
import socket
host = "192.168.1.2"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host,port))
s.settimeout(5)
data, addr = s.recvfrom(1024)
print("recevied from ",addr)
print("obtained ", data)
s.close()
Eu adicionei uma linha extra, ou seja, s.settimeout(5)
. O programa espera por 5 segundos; caso não haja conexões nesse intervalo, ele lança um erro. Execute udptime1.py.
A saída é mostrada na seguinte imagem:
O programa mostra um erro; tudo indica que ele não é um bom programa, pois seu erro é obscuro. O programa deve ser capaz manipular as exceções.
Para lidar com exceções, usaremos os blocos try
e except
. O próximo exemplo lhe dirá como lidar com as exceções. Execute udptime2.py
:
import socket
host = "192.168.1.3"
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.bind((host,port))
s.settimeout(5)
data, addr = s.recvfrom(1024)
print("recevied from ",addr)
print("obtained ", data)
s.close()
except socket.timeout :
print("Client not connected")
s.close()
A saída é mostrada na seguinte imagem:
No bloco try, eu coloco o meu código; no except, uma mensagem personalizada para ser exibida caso ocorra alguma exception.
Diferentes tipos de exceções são definidos na biblioteca sockets do Python para diferentes erros. Vejamos algumas:
-
exception socket.herror
: Este bloco detecta erros relacionados à endereços. -
exception socket.timeout
: Este bloco captura uma exceção quando o tempo limite de esculta do socket expirar. No exemplo anterior você pode ver que usamossocket.timeout
. -
exception socket.gaierror
: Este bloco captura qualquer exceção que é gerada devido agetaddrinfo()
egetnameinfo()
. -
exception socket.error
: Este bloco detecta quaisquer erros relacionados a socket. Se você não tiver certeza sobre qualquer exceção lançar, você pode usá-lo. Em outras palavras, você pode dizer que é um bloco genérico que pega qualquer tipo de exceção.
Você ganhou conhecimento sobre socket e sobre a arquitetura cliente-servidor. E você já é capaz de fazer um pequeno software networking. No entanto, o objetivo deste livro é testar e coletar informações em alguma rede. Python pode fazer isso de maneira elegante, ele possuí métodos úteis para coleta informações. Primeiro, import socket
e use os seguintes métodos:
-
socket.gethostbyname(hostname)
: Este método recebe um hostname como parâmetro e retorna um endereço IPv4. O endereço IPv4 é retornado na forma de string. Aqui está um exemplo:
>>> import socket
>>> socket.gethostbyname('thapar.edu')
'220.227.15.55'
>>>
>>> socket.gethostbyname('google.com')
'173.194.126.64'
>>>
Eu sei que você está pensando sobre o comando nslookup. Mais tarde, você verá mais bruxarias.
-
socket.gethostbyname_ex (name)
: Este método converte um nome de host para um endereço IPv4 padrão. No entanto, a vantagem sobre o método anterior é que ele dá todos os endereços IP do nome de domínio. Ele retorna uma tupla (hostname, canonical name, and IP_addrlist) onde hostmane é dado por nós, canonical name é uma lista(possivelmente vazia) de nomes de host canônicos do servidor para o mesmo endereço e IP_addrlist é uma lista de todos os IPs disponíveis no mesmo hostname. Muitas vezes, um nome de domínio é hospedado em muitos endereços IP para equilibrar a carga do servidor. Infelizmente, este método não funciona para IPv6. Espero que você esteja bem familiarizado com tuplas, listas e dicionários. Vejamos um exemplo:
>>> import socket
>>> socket.gethostbyname_ex('pt.org.br')
('pt.org.br', [], ['199.83.132.133', '199.83.128.133'])
>>>
>>> socket.gethostbyname_ex('google.com')
('google.com', [], ['172.217.29.78'])
>>>
>>> socket.gethostbyname_ex('facebook.com')
('facebook.com', [], ['31.13.85.36'])
>>>
Ele retorna muitos endereços IP (ou não) de um único nome de domínio. Isso significa que um domínio como pt.org.br
é executado em dois IPs.
-
socket.gethostname()
: Isso retorna o hostname do sistema onde o interpretador Python está sendo executado atualmente:
>>> socket.gethostname()
'dhcppc0'
>>>
Para obter o endereço IP da máquina atual usando o módulo socket, você pode usar o seguinte truque executando socket.gethostbyname(socket.gethostname())
:
>>> socket.gethostbyname(socket.gethostname())
'200.148.457.114'
>>>
Você sabe que o nosso computador tem muitas interfaces. Se você quiser saber o endereço IP de todas as interfaces, use a interface estendida:
>>> socket.gethostbyname_ex(socket.gethostname())
('gvt.com.br', ['dhcppc0.gvt.com.br'], ['134.456.457.171'])
>>>
Ele retorna uma tupla contendo três elementos: primeiro é o nome da máquina, segundo é uma lista de aliases para o nome do host e terceiro é a lista de endereços IP das interfaces(no meu caso só tenho uma).
-
socket.getfqdn([name])
: Isso é usado para encontrar o fully qualified name, se estiver disponível. O fully qualified name consiste em um host e um nome de domínio; Por exemplo, beta pode ser o nome do host, e example.com pode ser o nome do domínio. O fully qualified domain name(FQDN) torna-se beta. example.com:
>>> socket.getfqdn('facebook.com')
'edge-star-mini6-shv-01-gru2.facebook.com'
>>>
No exemplo anterior, edge-star-mini6-shv-01-gru2 é o nome do host, e facebook.com é o nome do domínio. No exemplo a seguir, FQDN não está disponível para thapar.edu:
>>> socket.getfqdn('thapar.com')
'thapar.com'
>>>
Se o argumento name estiver em branco, ele retornará o nome da máquina atual:
>>> socket.getfqdn()
'gvt.com.br'
-
socket.gethostbyaddr(ip_address)
: Isso é como um "reverse" lookup para o nome. Ele retorna uma tupla (hostname, canonical name, and IP_addrlist) onde hostname é o nome do host que responde ao dado ip_address, o canonical name é uma lista (possivelmente vazia) de nomes canônicos do mesmo endereço e IP_addrlist é uma lista de endereços IP para a mesma interface de rede no mesmo host:
>>> socket.gethostbyaddr('31.13.85.36')
('edge-star-mini-shv-01-gru2.facebook.com', [], ['31.13.85.36'])
>>>
>>> socket.gethostbyaddr('119.18.50.66')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
socket.herror: [Errno 1] Unknown host
>>>
Ele mostra um erro na última consulta porque o DNS lookup não está presente.
-
socket.getservbyname(servicename[, protocol_name])
: Isso converte qualquer protocol name para o número da porta correspondente. O nome do protocolo é opcional, TCP ou UDP. Por exemplo, o serviço DNS usa TCP, bem como conexões UDP. Se o nome do protocolo não for fornecido, qualquer protocolo pode corresponder:
>>> socket.getservbyname('http')
80
>>> socket.getservbyname('smtp','tcp')
25
>>>
-
socket.getservbyport(port[, protocol_name])
: Isso converte um número de porta de um protocolo para o nome do serviço correspondente. O nome do protocolo é opcional, TCP ou UDP:
>>> socket.getservbyport(80)
'http'
>>> socket.getservbyport(23)
'telnet'
>>> socket.getservbyport(445)
'microsoft-ds'
>>>
-
socket.connect_ex(address)
: Esse método retorna um indicador de erro. Se obter êxito. Eleretorna 0
; Caso contrário, ele retorna a variávelerrno
. Você pode aproveitar esta função para escanear as portas. Execute o programaconnet_ex.py
:
import socket
rmip ='127.0.0.1'
portlist = [22,23,80,912,135,445,20]
for port in portlist:
sock= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
result = sock.connect_ex((rmip,port))
print(port,":", result)
sock.close()
A saída é mostrada na seguinte imagem:
A saída do programa anterior mostra que somente a porta 22 está aberta. Este é um scanner de porta rudimentar. Caso não encontre portas abertas, execute isso em outro dispositivo com uma grande lista de portas. Desta vez você terá que usar socket.settimeout(value)
:
socket.getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]])
Este método socket converte os argumentos host e port em uma seqüência de cinco tuplas.
Dê uma olhada no exemplo:
>>> socket.getaddrinfo('www.thapar.edu', 'http')
[(2, 1, 6, '', ('220.227.15.49', 80)), (2, 2, 17, '', ('220.227.15.49', 80))]
>>>
O 2 representa a família, 1 representa o tipo de socket, 6 representa o protocolo, ' ' representa o canonical name e ('220.227.15.49', 80) representa o endereço dos dois sockets. No entanto, este número é difícil de compreender. Navegue para onde estão seus arquivos de exemplos.
Use o código a seguir para obter um resultado mais legível. getadd1.py
:
import socket
def get_protnumber(prefix):
return dict( (getattr(socket, a), a)
for a in dir(socket)
if a.startswith(prefix))
proto_fam = get_protnumber('AF_')
types = get_protnumber('SOCK_')
protocols = get_protnumber('IPPROTO_')
for res in socket.getaddrinfo('www.thapar.edu', 'http'):
family, socktype, proto, canonname, sockaddr = res
print('Family :', proto_fam[family])
print('Type :', types[socktype])
print('Protocol :', protocols[proto])
print('Canonical name :', canonname)
print('Socket address :', sockaddr)
print('--------------------------------------------')
A primeira parte do código faz um dicionário usando AF_, SOCK_
e IPPROTO_prefixes
que mapeia o número do protocolo para seus respectivos nomes. Este dicionário é formado pela técnica he list comprehension.
O código dentro da função(get_protnumber(prefix)) do código acima pode parecer um pouco confusa, mas podemos executá-la separadamente da seguinte maneira:
>>> dict(( getattr(socket,n),n) for n in dir(socket) if n.startswith('AF_'))
{0: 'AF_UNSPEC', 2: 'AF_INET', 6: 'AF_IPX', 11: 'AF_SNA', 12: 'AF_
DECnet', 16: 'AF_APPLETALK', 23: 'AF_INET6', 26: 'AF_IRDA'}
Agora ficou mais simples de entender. Esse código é geralmente usado para obter o número do protocolo:
for res in socket.getaddrinfo('www.thapar.edu', 'http'):
A linha de código anterior retorna os cinco valores, conforme discutido na definição. Esses valores são então combinados com seu dicionário correspondente.