Firewall de Javier en Fraga (iptables)

#!/sbin/runscript
 
# firewall it! -Javier Barrio- Febrero 2003
# modificado en Julio 2003
# retocado para wifi en Enero 2004
 
start()
{
        INTERFAZ_LOOP="lo"
        INTERFAZ_INET="eth0"
        INTERFAZ_LAN="eth1"
        INTERFAZ_WIFI="eth2"
        DHCP="si"
        NAT="si"
        SERVER_DHCP="81.202.91.1"
        IP_LO="127.0.0.1"
        IP_LAN="192.168.0.1"
        IP_WIFI="10.66.0.96"
        RANGO_LAN="192.168.0.0/16"
        RANGO_WIFI="10.66.0.96/28"
        PUERTOS_FORWARD="1863:1872 4661:4669"
  IPTABLES=`which iptables`
 
 
        echo -e " >>> ARRANCANDO FIREWALL... <<<\n"
        PROCVARS="ip_forward ip_dynaddr"
        echo -e "* Habilitando las siguientes variables de /proc:\n"
        echo " -> ${PROCVARS}..."
        for i in ${PROCVARS}; do echo 1 > /proc/sys/net/ipv4/${i}; done
        PROCVARS="rp_filter proxy_arp"
        echo " -> ${PROCVARS}..."
        for i in $PROCVARS; do echo 1 > /proc/sys/net/ipv4/conf/all/${i}; done
 
        echo -ne ">> POLITICAS\n"
 
        CADENAS="INPUT OUTPUT FORWARD"
        for i in ${CADENAS}
        do
                echo -n " -> Aplicando DROP a la cadena predefinida ${i}..."
                ${IPTABLES} --policy ${i} DROP
                echo -ne "[ ok ]\n"
        done
 
        # creamos una cadena para paquetes chungos y permitidos
        # y otras para diferenciar entre tcp, udp e icmp
 
        echo -ne "\n>> CADENAS\n"
        MISCADENAS="tcp_nigros permitidos paquetes_tcp paquetes_udp paquetes_icmp"
        for i in ${MISCADENAS}
        do
                echo -n " -> Creando cadena personal ${i}..."
                ${IPTABLES} --new-chain ${i}
                echo -ne "[ ok ]\n"
        done
 
        # filtramos y logueamos cualquier paquete marcado como NEW
        # en el estado de la conexion que no sea un SYN
 
        echo -n " -> Filtrando conexiones nuevas (NEW) que no tengan el flag de SYN activado... "
        ${IPTABLES} --append tcp_nigros --protocol TCP --tcp-flags SYN,ACK SYN,ACK \
        --match state --state NEW --jump REJECT --reject-with tcp-reset
        echo -n "[ ok ]"
 
        # comentada porque genera demasiada broza
        #${IPTABLES} --append tcp_nigros --protocol TCP ! --syn --match state --state NEW --jump LOG \
        #--log-prefix "Nuevo y no syn:"
 
        ${IPTABLES} --append tcp_nigros --protocol TCP ! --syn --match state --state NEW --jump DROP
        ${IPTABLES} --append permitidos --protocol TCP --syn --jump ACCEPT
        ${IPTABLES} --append permitidos --protocol TCP --match state --state ESTABLISHED,RELATED --jump ACCEPT
        ${IPTABLES} --append permitidos --protocol TCP --jump DROP
 
        echo -e "\n\n>> PROTOCOLOS\n"
 
  #######
  # TCP #
  #######
 
        echo "* Permitiendo el paso de los siguientes servicios TCP:"
 
 
        PUERTOS="20 21 24 25 80 81 110 113 143 220 443 873 993 995"
        for i in ${PUERTOS}
        do
                echo -n " -> Habilitando acceso TCP al puerto ${i}... "
                ${IPTABLES} --append paquetes_tcp --protocol TCP --src 0/0 --destination-port ${i} --jump permitidos
                echo -ne "[ ok ]\n"
        done
 
  #######
  # UDP #
  #######
 
        echo -e "\n* Permitiendo el paso de los siguientes servicios UDP:"
        SRVUDP="20 53 110 143 220 993"
        for i in ${SRVUDP}
        do
                echo -n " -> Habilitando acceso UDP en el puerto ${i}... "
                ${IPTABLES} --append paquetes_udp --protocol UDP --src 0/0 --source-port ${i} --jump ACCEPT
                echo -ne "[ ok ]\n"
        done
 
        if [ ${DHCP} == "si" ]
        then
                echo -n " -> Filtrando correctamente el servicio DHCP... "
                ${IPTABLES} --append paquetes_udp --protocol UDP -s $SERVER_DHCP --source-port 67 --dport 68 --jump ACCEPT
                echo -ne "[ ok ]\n"
        fi
 
        # Si usamos NetBEUI sin WINS se nos llenaran de broza los logs,
  # con esto se intenta prevenir
 
        echo -n " -> Filtrando peticiones NetBIOS para no cargar los LOGS... "
        ${IPTABLES} --append paquetes_udp --protocol UDP --in-interface ${INTERFAZ_INET} \
        --destination-port 135:139 --jump DROP
        echo -ne "[ ok ]\n"
 
        # Esta para no llenar los logs de mierda de DHCP_REQUEST desde fuera de la LAN
 
        echo -n " -> Filtrando posibles peticiones DHCP desde internet... "
        ${IPTABLES} --append paquetes_udp --protocol UDP --in-interface ${INTERFAZ_INET} \
        --destination 255.255.255.255 --destination-port 67:68 --jump DROP
        echo -ne "[ ok ]\n"
 
  ########
  # ICMP #
  ########
 
        echo -e "\n* Trafico de control ICMP:"
        # aceptamos echo request y reply
 
        TICMP="8 11"
        for i in ${TICMP}
        do
                echo -n " -> dejando pasar paquetes ICMP del tipo ${i}... "
                ${IPTABLES} --append paquetes_icmp --protocol ICMP --src 0/0 --icmp-type ${i} --jump ACCEPT
                echo -ne "[ ok ]\n"
        done
 
        # fieXta, aplicamos las reglas a las cadenas
  #########
  # INPUT #
  #########
 
        echo -e "\n>> Aplicando las reglas a las cadenas...\n"
 
        #Igual que en la OpenBSD, filtramos los paquetes incompletos y/o raros
        ${IPTABLES} --append INPUT --protocol TCP --jump tcp_nigros
 
        # aceptamos conexiones provenientes de la LAN y del Loopback
        ${IPTABLES} --append INPUT --protocol ALL --in-interface $INTERFAZ_LAN --src $RANGO_LAN --jump ACCEPT
        ${IPTABLES} --append INPUT --protocol ALL --in-interface $INTERFAZ_LOOP --jump ACCEPT
 
        # servimos dhcp a la LAN de forma correcta
        ${IPTABLES} --append INPUT --protocol UDP --in-interface $INTERFAZ_LAN \
        --destination-port 67 --source-port 68 --jump ACCEPT
 
        # aceptamos conexiones desde internet _YA_ establecidas
        ${IPTABLES} --append INPUT --protocol ALL --in-interface $INTERFAZ_INET \
        --match state --state ESTABLISHED,RELATED --jump ACCEPT
 
        # asignamos cada protocolo a su cadena
        ${IPTABLES} --append INPUT --protocol TCP --in-interface $INTERFAZ_INET --jump paquetes_tcp
        ${IPTABLES} --append INPUT --protocol UDP --in-interface $INTERFAZ_INET --jump paquetes_udp
        ${IPTABLES} --append INPUT --protocol ICMP --in-interface $INTERFAZ_INET --jump paquetes_icmp
 
        # denegamos las broacasts de las redes MS
        ${IPTABLES} --append INPUT --in-interface $INTERFAZ_INET --destination 224.0.0.0/8 --jump DROP
 
        # demasiada broza
        #${IPTABLES} --append INPUT --match limit --limit 3/minute --limit-burst 3 --jump LOG \
        #--log-level DEBUG --log-prefix "IPT: paquete INPUT muerto: "
 
  ###########
  # FORWARD #
  ###########
 
        ${IPTABLES} --append FORWARD --protocol TCP --jump tcp_nigros
 
        ${IPTABLES} --append FORWARD --in-interface $INTERFAZ_LAN --jump ACCEPT
        ${IPTABLES} --append FORWARD --match state --state ESTABLISHED,RELATED --jump ACCEPT
 
        #${IPTABLES} --append FORWARD --match limit --limit 3/minute --limit-burst 3 --jump LOG \
        #--log-level DEBUG --log-prefix "IPT: paquete FORWARD muerto: "
 
  for i in ${PUERTOS_FORWARD}
  do
    echo -n " -> Forwardeando rango de puertos ${i} a la LAN... "
    ${IPTABLES} --append FORWARD -i eth0 --protocol TCP -d ${RANGO_LAN} --dport ${i} --jump ACCEPT
    echo -ne "[ ok ]\n"
  done
 
  ##########
  # OUTPUT #
  ##########
 
        ${IPTABLES} --append OUTPUT --protocol TCP --jump tcp_nigros
 
        ${IPTABLES} --append OUTPUT --protocol ALL --src $IP_LO --jump ACCEPT
        ${IPTABLES} --append OUTPUT --protocol ALL --src $IP_LAN --jump ACCEPT
        ${IPTABLES} --append OUTPUT --protocol ALL --out-interface $INTERFAZ_INET --jump ACCEPT
 
        #${IPTABLES} --append OUTPUT --match limit --limit 3/minute --limit-burst 3 --jump LOG \
        #--log-level DEBUG --log-prefix "IPT: paquete OUTPUT muerto: "
 
  ###############
  # POSTROUTING #
  ###############
 
        if [ ${NAT} == "si" ]
        then
                echo -n " [NAT] -> Aplicando Network Address Translation..."
                ${IPTABLES} --table nat --append POSTROUTING --out-interface ${INTERFAZ_INET} --jump MASQUERADE
                echo -ne "[ ok ]\n"
        fi
 
  ##############
  # PREROUTING #
  ##############
 
  for i in ${PUERTOS_FORWARD}
  do
    echo -n " [RED] -> Permitiendo el envio de archivos por el puerto ${i} desde la LAN... "
    ${IPTABLES} --append PREROUTING --table nat -i eth0 --protocol TCP --dport ${i} --jump DNAT --to 192.168.0.2
    echo -ne "[ ok ]\n"
  done
 
  echo -n " [RED] -> Redireccionando el puerto 23 al 24... "
  ${IPTABLES} --append PREROUTING --table nat -p tcp --dport 23 -j REDIRECT --to-ports 24
  echo -ne "[ ok ]\n"
 
  echo -n " [TOS] -> Aplicando un TTL comun a todos los paquetes..."
  ${IPTABLES} --append PREROUTING --table mangle -i eth0 -j TTL --ttl-set 64
  echo -ne "[ ok ]\n"
 
        echo -n " [TOS] -> Cambiando los campos TOS para prioridad de ancho de banda entrante a WWW y SSH... "
        ${IPTABLES} --append PREROUTING --table mangle --protocol TCP --source-port 80 \
        --jump TOS --set-tos Maximize-Throughput
 
        ${IPTABLES} --append PREROUTING --table mangle --protocol TCP --source-port 22 \
        --jump TOS --set-tos Minimize-Delay
        echo -ne "[ ok ]\n"
 
  ##########
  # OUTPUT #
  ##########
 
        echo -n " [TOS] -> Cambiando los campos TOS para prioridad de ancho de banda saliente a WWW y SSH..."
        ${IPTABLES} --append OUTPUT --table mangle --protocol TCP --destination-port 80 \
        --jump TOS --set-tos Maximize-Throughput
 
        ${IPTABLES} --append OUTPUT --table mangle --protocol TCP --destination-port 22 \
        --jump TOS --set-tos Minimize-Delay
        echo -ne "[ ok ]\n"
 
        echo -e "\n>> Reglas aplicadas\n"
        echo ">>> FIREWALL COMPLETAMENTE ACTIVADO <<<"
 
}
 
stop()
{
        IPTABLES=`which iptables`
        echo -e " >>> PARANDO FIREWALL <<<\n"
 
        echo -e "Reiniciando pol<ED>ticas por defecto..."
        for i in INPUT FORWARD OUTPUT; do ${IPTABLES} --policy ${i} ACCEPT; done
        for i in PREROUTING POSTROUTING OUTPUT; do ${IPTABLES} --table nat --policy ${i} ACCEPT; done
        for i in PREROUTING OUTPUT; do ${IPTABLES} --table mangle --policy ${i} ACCEPT; done
        echo -ne "[ ok ]\n"
 
        for i in filter nat mangle
        do
                echo -n " -> Flusheando tabla ${i}..."
                ${IPTABLES} --table ${i} --flush
                echo -ne "[ ok ]\n"
        done
 
        for i in filter nat mangle
        do
                echo -n " -> Borrando cadenas no predefinidias de la tabla ${i}..."
                ${IPTABLES} --table ${i} --delete-chain
                echo -ne "[ ok ]\n"
        done
 
        echo -e "\n >>> FIREWALL COMPLETAMENTE PARADO <<< \n"
}
 
panic ()
{
        IPTABLES=`which iptables`
        TABLAS="nat mangle limit"
        for i in ${TABLAS}
        do
                ${IPTABLES} --flush --table $i
                ${IPTABLES} --zero --table $i
        done
        echo "Modo paranoico, cerrandolo TODO."
        ${IPTABLES} --policy INPUT --jump DROP
        ${IPTABLES} --policy FORWARD --jump DROP
        ${IPTABLES} --policy OUTPUT --jump DROP
        echo "Hecho. Aqui no se mueve ni dios xD"
}