quarta-feira, 17 de julho de 2013

Gerando IPs aleatórios

Pessoal,

Depois de vários anos sem nenhum post no blog resolvi voltar a ativa e publicar algumas dicas que, espero, sejam úteis para alguém.

Esta semana precisei executar uma varredura de portas TCP utilizando a ferramenta Nmap numa subrede muito grande para a qual não havia tempo hábil para varrer todos os IPs. Tive então que optar por trabalhar com amostragem e a escolha aleatória de endereços IP seria muito útil.

No entanto havia um problema: o Nmap não tem uma opção para escolher aleatoriamente um número finito de IPs dentro de um critério de uma subrede específica (o que ele gera com a opção -iR é um IP a partir de todo o endereçamento IP disponível na Internet). Ou seja, mãos a obra!

Aí desenvolvi um script para atender a minha necessidade baseado num artigo que vi no blog do Chad Bibler intitulado Generating a Random, Valid IP Address in Subnet in Python (http://dregsoft.com/blog/?p=24). Meu script randomip.py ficou assim:

#!/usr/bin/env python
import socket
import struct
import random
import math
import sys

def get_max_ips( netmask_length, random_ips ):
    # define maximum number of IP addresses to be generated
    netmask_ips = int( math.pow( 2, 32-netmask_length ) )
    if ( netmask_ips < random_ips ):
        winner = int( math.pow( 2, 32-netmask_length ) )
    else:
        winner = random_ips
    return winner

def get_random_ip_in_subnet( ip, netmask_length ):
    # thanks to Chad Bibler, http://dregsoft.com/blog/?p=24
    # change the IP address into its bytes so we can add a number to it
    n = socket.inet_aton( ip )
    ip_bytes = struct.unpack( '!i', n )[0]
    # we use the netmask_length to get a range of numbers we can add to the IP address
    max_to_add = int( math.pow( 2, 32-netmask_length ) )
    to_add = random.randrange( 0, max_to_add )
    ip_bytes += to_add
    # pack it back up
    and_back = struct.pack( '!i', ip_bytes )
    new_ip = socket.inet_ntoa( and_back )
    return new_ip

if ( len(sys.argv) != 4 ):
    print "Command syntax: "
    print "   python randomip.py   <# of random IPs from subnet>"
    print ""
    print "   example: python randomip.py 192.168.0.0 20 100"
else:
    iplist={}
    max_ips=get_max_ips(int(sys.argv[2]),int(sys.argv[3]))
    for x in range(0, max_ips):
        ip=get_random_ip_in_subnet( sys.argv[1], int(sys.argv[2]))
        while(iplist.has_key(ip)):
            ip=get_random_ip_in_subnet( sys.argv[1], int(sys.argv[2]))
        iplist[ip]=1
        print ip

Na prática o meu a minha varredura TCP para escolher 1000 endereços IP dentro da subrede 172.16.0.0/12 ficou assim:

python randomip.py 172.16.0.0 12 1000 | nmap -v -n --open -sS -iL - -oA nmap_out

Podem utilizar o script livremente e sugiro para quem quiser se aventurar no desenvolvimento do script três melhorias:
  1. Fazer com que o script em randomip.py aceite um arquivo de entrada com vários blocos IP (para o caso de subredes descontínuas)
  2. Fazer com que o script aceite como parâmetro um ASN (autonomous system). Neste caso ele sortearia os IP baseados neste ASN ou lista de ASNs (os blocos IP deste ASN poderiam ser recuperados a partir de site da ripe.net ou de alguma informação de BGP externa).
  3. Fazer com que o script aceite como parâmetro a sigla de um país (por exemplo sortear IPs que sejam somente da China). A lista poderia ser recuperada de sites como ipdeny.com 
Abraços e boa sorte a todos!