Simple switch Ryu + snort + mininet

Se va a configurar un escenario como el siguiente en mininet:

  10.0.0.1          10.0.0.2       10.0.0.3            10.0.0.4
 +---------+       +--------+      +--------+         +--------+
 |   h1    |       |   h2   |      |   h3   |         |   h4   |
 +---------+       +--------+      +--------+         +--------+
      |                 |               |                 |
      |                 |               |                 |
      |1                | 2             | 3               |4
   +----------------------------------------------------------+
   |                             s1                           |
   +----------------------------------------------------------+

La topología de mininet está definida en el siguiente fichero:

#!/usr/bin/python 
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel

class SingleSwitchTopo(Topo):
    "Single switch connected to n hosts."
    def build(self, n=4):
        switch = self.addSwitch('s1')
        # Python's range(N) generates 0..N-1
        for h in range(n):
            host = self.addHost('h%s' % (h + 1))
            self.addLink(host, switch)


# Allows the file to be imported using `mn --custom <filename> --topo dcbasic`
topos = {
    'dcconfig': SingleSwitchTopo
}

Para arrancar esta topología:

sudo mn --custom singleSwitchTopo.py --topo dcconfig --mac --controller remote

Vamos a usar el controlador simple_switch_snort.py para describir el comportamiento de s1. Este controlador además de definir el comportamiento del switch, se comunica con snort a través de unun socket unix (SOCKFILE = "/tmp/snort_alert", definido en la librería de Ryu: SnortLib) para recibir las alertas que haya definidas en snort. Cuando recibe una alerta imprime un mensaje. El controlador tiene definido el puerto 3 como puerto mirror, es decir, hace una copia de todos los paquetes en el puerto 3. Esto permite que snort pueda analizar todos los paquetes del switch s1. En el controlador simple_switch_snort.py encontramos el siguiente código:

   def __init__(self, *args, **kwargs):
        super(SimpleSwitchSnort, self).__init__(*args, **kwargs)
        # crea el objeto para el manejo de las alertas de snort
        self.snort = kwargs['snortlib']
        # define el puerto mirror donde está arrancado snort
        self.snort_port = 3
        self.mac_to_port = {}

        # se comunica con snort a través de un socket unix
        socket_config = {'unixsock': True}

        self.snort.set_config(socket_config)
        self.snort.start_socket_server()

Lanzamos el controlador:

sudo ryu-manager ryu/ryu/app/simple_switch_snort.py

El puerto 3, donde está conectado h3 funciona como mirror, es decir, se pueden capturar todos los paquetes que reciba s1. Para probarlo, lanzamos un ping en h1 hacia h4 (10.0.0.4) y se puede observar como h2 sólo recibe la consulta de ARP y h3 recibe todos los paquetes, siendo que no van dirigidos a h3

MirrorPort

El controlador simple_switch_snort.py tiene programado que al instalar un flujo en el switch, además de realizar la copia al puerto de salida correspondiente, copia ese paquete en el puerto en el que está haciendo mirror:

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
       ...
       actions = [parser.OFPActionOutput(out_port),
                  parser.OFPActionOutput(self.snort_port)]

       # instalar el flujo
       match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
       self.add_flow(datapath, 1, match, actions)

       # enviar packetOut
       out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
                                 in_port=in_port, actions=actions, data=data)
       datapath.send_msg(out)

Alerta por tráfico ICMP

Vamos a añadir una regla a snort para que siempre que detecte tráfico ICMP (en particular ocurrirá cuando ejecutemos ping, ICMP Echo Request/Reply) se envíe una alerta.

  • En el fichero /etc/snort/snort.conf añadimos la siguiente línea al final del fichero. Esto permite definir nuestro propio fichero de reglas que se cargarán al iniciar snort:
  • include $RULE_PATH/myRules.rules

    • Crearemos el fichero /etc/snort/rules/myRules.rules con las alertas que queramos definir:

    alert icmp any any -> any any (msg:"ICMP traffic...";sid:1000004)

Ya tenemos snort preparado para que cuando detecte tráfico ICMP, se muestre esta alerta. Arrancamos snort: para que procese los paquetes donde el switch está haciendo mirror (desde la máquina real, esta interfaz es s1-eth3), use un socket unix y la carpeta para almacenar los logs es /tmp: sudo snort -i s1-eth3 -A unsock -l /tmp -c /etc/snort/snort.conf

Provocamos tráfico para que se active la alerta. Por ejemplo, en h1 volvemos a ejecutar ping a 10.0.0.4 (h4), al detectar tráfico ICMP Echo Request y Echo Reply, snort generará una alerta que el controlador recibirá a través del socket unix e imprimirá los siguientes mensajes:

  • Alerta por el paquete ICMP Echo Request mostrada en el controlador:

    alertmsg: ICMP traffic... 
    icmp(code=0,csum=24244,data=echo(data=array('B', [60, 216, 138, 89, 0, 0, 0, 0, 189, 63, 4, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55]),id=20998,seq=1),type=8)
    ipv4(csum=33563,dst='10.0.0.4',flags=2,header_length=5,identification=41865,offset=0,option=None,proto=1,src='10.0.0.1',tos=0,total_length=84,ttl=64,version=4)
    ethernet(dst='00:00:00:00:00:04',ethertype=2048,src='00:00:00:00:00:01')
    

    EchoReq

  • Alerta por el paquete ICMP Echo Reply mostrada en el controlador:

    alertmsg: ICMP traffic... 
    icmp(code=0,csum=26292,data=echo(data=array('B', [60, 216, 138, 89, 0, 0, 0, 0, 189, 63, 4, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55]),id=20998,seq=1),type=0)
    ipv4(csum=17598,dst='10.0.0.1',flags=0,header_length=5,identification=8679,offset=0,option=None,proto=1,src='10.0.0.4',tos=0,total_length=84,ttl=64,version=4)
    ethernet(dst='00:00:00:00:00:01',ethertype=2048,src='00:00:00:00:00:04')
    

    EchoReq

Alerta por ataque XMAS

Snort por defecto tiene configurada la siguiente regla en el fichero scan.rules:

alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"SCAN nmap XMAS"; flow:stateless; flags:FPU,12; reference:arachnids,30; classtype:attempted-recon; sid:1228; rev:7;)

Vamos a provocar que se active esta alerta cuando hacemos un escaneo con nmap desde la máquina h1 hacia a h4. Para ello, primero vamos a activar el servicio sshd en h4 para ver el comportamiento diferente de un escaneo con un puerto abierto o un puerto cerrado. En h4 lanzamos:

/usr/sbin/sshd

Comprobamos que está lanzado escuchando en el puerto 22:

netstat -ant
Conexiones activas de Internet (servidores y establecidos)
Proto    Recib    Enviad    Dirección local        Dirección remota    Estado
tcp        0        0        0.0.0.0:22            0.0.0.0:*            ESCUCHAR
tcp6       0        0        :::22                :::*                ESCUCHAR

Desde h1 ejecutamos el sondeo de los puertos 21 y 22 con ataque XMAS (flags URG, PSH y FIN):

nmap -Pn -sX -p 21-22 -v 10.0.0.4

Con este comando, h1 mandará a los puertos 21 y 22 un segmento TCP con los flags activados: URG, PSH y FIN. El envío de este mensaje SYN al puerto 21, donde no hay servidor, provoca una respuesta de TCP con RST activado. El envío del mensaje SYN al puerto 22 no obtiene respuesta (en este caso hay un servidor de ssh que no responde a este mensaje) y nmap repite de nuevo la misma sonda. Observamos las alertas en el controlador, la primera se corresponde con el mensaje al puerto 21 y las dos siguientes con los dos mensajes al puerto 22:

alertmsg: SCAN nmap XMAS
ipv4(csum=50625,dst='10.0.0.4',flags=0,header_length=5,identification=46858,offset=0,option=None,proto=6,src='10.0.0.1',tos=0,total_length=40,ttl=42,version=4)
ethernet(dst='00:00:00:00:00:04',ethertype=2048,src='00:00:00:00:00:01')

alertmsg: SCAN nmap XMAS
ipv4(csum=6852,dst='10.0.0.4',flags=0,header_length=5,identification=24072,offset=0,option=None,proto=6,src='10.0.0.1',tos=0,total_length=40,ttl=46,version=4)
ethernet(dst='00:00:00:00:00:04',ethertype=2048,src='00:00:00:00:00:01')

alertmsg: SCAN nmap XMAS
ipv4(csum=40828,dst='10.0.0.4',flags=0,header_length=5,identification=54607,offset=0,option=None,proto=6,src='10.0.0.1',tos=0,total_length=40,ttl=50,version=4)
ethernet(dst='00:00:00:00:00:04',ethertype=2048,src='00:00:00:00:00:01')

nomap-xmas

results matching ""

    No results matching ""