#!/bin/sh
#	fwgen-iptables ver 0.11
#	Process firewall-easy-lib	# Procesa firewall-easy-lib
#
#	Generates a firewall script	# Genera un script de cortafuegos
#	in "/etc/firewall-iptables"	# en "/etc/firewall-iptables"
#
#	Copyright (C) 2000-2002:	Manel Marin <manel3@wanadoo.es>
#	Licence:			GNU GPL version >= 2
#
#

	# Rules file of firewall-easy	# Archivo de reglas de firewall-easy
FROM=/etc/firewall-easy-lib

	# Script to create/overwritte	# Script a crear/sobreescribir
TO=/etc/firewall-iptables



echo "-> Generating firewall script $TO (fwgen-iptables)"
cat $FROM |  awk '

# We are going to parse the rules file	# Vamos a procesar el archivo de reglas
# line by line generating a bash script # linea a linea generando un script
# printing or echoing lines		# bash haciendo print o echo con lineas


# BE CAREFULL:				# CUIDADO:
# "" 0 = ASCII 0  comment		# Comentario  "" 0 = ASCII 0
# letter zero can be interpreted as	# la letra cero puede ser interpretada
# number zero not returning letter	# como nmero cero no devolviendo letra



#---------------FIX PART----------------#---------------PARTE FIJA-------------
#--independent of ipchains, iptables----#--independiente de ipchains, iptables-


# CONFIG VARS DETAILS			# DETALLES DE VARIABLES CONFIGURACION

#TESTFW					#TESTFW
#---to do firewall test in boot---	#---hacer test cortafuegos en arranque-

#NOLOG (ONLY 2.2)			#NOLOG (SOLO 2.2)
#---No to do any log---			#---NO hacer NINGUN LOG---
# log paramenter is $L in script	# el parametro para hacer log es $L
# So $L="" is enough to not log		# en el script, de modo que $L=""
# without regenerating firewall script	# basta para no hacer log

#LOGALLDENY				#LOGALLDENY
#---log all NO rule (for debuging)---	#---hacer log de toda regla NO (debug)-

#RSTALLDENY (ONLY 2.4)			#RSTALLDENY (SOLO 2.4)
#---return RST to all NO rule (debug)--	#---devolver RST a toda regla NO (debug)

#DEBUG					#DEBUG
#---If exists show rules---		#---Muestra reglas si existe---
# DEBUG shell var is checked in echorun	# La variable shell DEBUG es comprobada
# so export DEBUG=yes is enough	to	# en echorun, export DEBUG=si basta
# show rules when running the fwscript	# para mostrar las reglas al lanzar
#					# el script de firewall


#############################################################################
# BEFORE PROCESS THE FIRST LINE		# ANTES DE PROCESAR LA PRIMERA LINEA
# OF THE RULES FILE			# DEL ARCHIVO DE REGLAS
#############################################################################
    BEGIN{
	    # Put script begining	#Pongo principio del script

	begining()

	    # Initialize vars		#Inicializo valores por defecto

	hi = "1024:65535"
	interface = "*"
	iplocal = "*"
	ipremote = "*"


	    # Pattern to detect if there are	# Patrn para detectar si hay
	    # more than one value to use loops	# ms de un valor para usar
	    # in INTERFACE, IPLOCAL, and	# bucles en INTERFACE, IPLOCAL,
	    # IPREMOTE				# e IPREMOTE
	    #    For example:			#    Por ejemplo:
	    # $IP can hold several values	# $IP puede tener varios valores
	    # $IP1 has only one value		# $IP1 tiene un solo valor
	    # (var name ended in number		# (variable terminada en nmero
	    # do not generate while loops)	#  no genera bucle while)
	    # "1.1.1.1 $IP1" are two values	# "1.1.1.1 $IP1" son dos valores

	SEVERAL_VALUES = "(^\$.*[^0-9]+$)|([^ ]+[ ]+[^ ]+)"

	    # Pattern of IP ($VAR o x.x.x.x)	# Patrn de IP ($VAR o x.x.x.x)

	IS_IP = "(^\$)|(\.)"
	
	    # Pattern of commented var line	# Linea de variable comentada

	COMMENTED = "^[ \t]*#"

    }

#############################################################################
# IN EVERY LINE OF RULES FILE		# EN CADA LINEA DEL ARCHIVO DE REGLAS
#############################################################################

# SKIP EMPTY LINES			# SALTAR LINEAS VACIAS
    $1 ~ "^[ \t]*$" { next }

# GROUP (starting with ####)		# GRUPO (empiezan con ####)
# add as a comment to the script	# escribir como comentario al script
    $1 ~ "^####" {
	print ""
	print ""
	print ""
	print "#"$0
	next
    }


# SKIP OTHER COMMENTS			# SALTAR OTROS COMENTARIOS
    $1 ~ "^#" { next }


# VARIABLES				# VARIABLES
# To allow VAR=VALUE and VAR = VALUE	# Para permitir VAR=VALUE y VAR = VALUE
# I split the whole line in:		# Divido la linea completa en:
# parts[1] (the VARIABLE_NAME) and	# parts[1] (el NOMBRE_DE_LA_VARIABLE) y
# parts[2] (the VALUE)			# parts[2] (el VALOR)

    $0 ~ "=" {
	split( $0, parts, "[ \t]*[=][ \t]*" )	# Separo y quito espacios
	gsub( "[ \t\$]+", "", parts[1] )	# Quito espacios del nombre
	gsub( "[ \t]*#.*", "", parts[2] )	# Quito comentario
	gsub( "[ \t]+", " ", parts[2] )		# Sustituyo TAB por espacios

##	print "#" $0					#DEBUG
##	print "#" parts[1] " / " parts[2]		#DEBUG


    # SPECIAL VARS			# VARIABLES ESPECIALES
    # (We use them internally)		# (Las usamos internamente)
	if ( parts[1] == "INTERFACE" ) {

    # FIN DE BUCLE INTERFACES ANTERIOR (si lo hubo)
	    if ( interface ~ SEVERAL_VALUES ) {
		print "done		# End of last INTERFACE for loop"
	    }
	    print "#" $0	# Poner linea de INTERFACE tras fin bucle
	    interface = parts[2]

    # INTERFACE VARIABLE LOOP 		# BUCLE PARA VARIABLE DE INTERFACES
	    interface_tmp = interface			#No modif var global
	    if ( interface ~ SEVERAL_VALUES ) {
		print "for IFACE in " interface "; do"
		interface_tmp = "$IFACE"
	    }
	}
	else if ( parts[1] == "IPLOCAL" )  { print "#" $0; iplocal = parts[2] }
	else if ( parts[1] == "IPREMOTE" ) { print "#" $0; ipremote = parts[2] }
	else if ( parts[1] == "HI" )       { print "#" $0; hi = parts[2] }

    # RESTO DE VARIABLES		# OTHER VARS
    	else if ( parts[2] ~ "\".*\"" ) {
	    print parts[1] "=" parts[2]		# already "...", ya es "..."
	}
	else {
	    print parts[1] "=\"" parts[2] "\""	# put "..."
	}
	next
    }

# IMPORT: Importing bash variables	# IMPORT: Importamos variables bash
# from a config file			# de un archivo de configuracin
    $1 ~ "^import$" {
	put_import( $2 )
	next
    }

# ARRIVING HERE IT IS A RULE LINE	# SI LLEGA AQUI ES UNA LINEA DE REGLA
    {
    # $1 = action + to_log + prio :	>>!--   =   ">>" + "!" + "--"
    # $2 = proto (tcp   udp   tcp,udp)
    # $3 = local (ip:port:port)
    # $4 = dir (<, >, <>)
    # $5 = remote (ip:port:port)
    # $6 = [nat (ip:port)]
    # $6... = Description 

    
# PRINT RULES LINES AS COMMENTS		# IMPRIMIR LINEAS DE REGLAS COMO
# or echo them if debug			# COMENTARIOS o echo si es modo debug
	print " debug \"#" $0 "\""


    # EXTRACT $1: action, to_log, prio	# SEPARAR $1 EN: action, to_log, prio
	action = $1
	gsub( "[!+-]+", "", action )		# Supr.  !, +, ++, -, --

	if ( $1 ~ "!" ) { to_log = "!" }
	else { to_log = "" }

	prio = $1
	gsub( "[^+-]+", "", prio )		# Only/solo  +, ++, -, --

##	print action " / " to_log " / " prio		#DEBUG

    # SPLIT LOCAL IP FROM PORT/RANGE	# SEPARAR IP LOCAL DE PUERTO/RANGO
	split ( $3, parts, ":" )
	if ( parts[1] ~ IS_IP ) {
	    local = parts[1]
	    local_port = "" parts[2]		# "" 0 = ASCII 0
	    if ( parts[3] ) local_port = local_port ":" parts[3]  # Rango
	}
	else{					# No hay IP
	    if ( action == "NO" || action == "RST" ) {
		local = "*"		# NO/RST sin IP prohibir todas las IP
	    }
	    else local = iplocal		# */> sin IP usar IPLOCAL
	    local_port = "" $3			# "" 0 = ASCII 0
	}

    # SPLIT REMOTE IP FROM PORT/RANGE	# SEPARAR IP REMOTA DE PUERTO/RANGO
	split ( $5, parts, ":" )
	if ( parts[1] ~ IS_IP ) {
	    remote = parts[1]
	    remote_port = "" parts[2]		# "" 0 = ASCII 0
	    if ( parts[3] ) remote_port = remote_port ":" parts[3]  # Rango
	}
	else{					# No hay IP
	    if ( action == "NO" || action == "RST" ) {
		remote = "*"		# NO/RST sin IP prohibir todas las IP
	    }
	    else remote = ipremote		# */> sin IP usar IPREMOTE
	    remote_port = "" $5			# "" 0 = ASCII 0
	}

    # PROCESS PROXY/FORWARD		# PROCESO PROXY/FORWARD
    # Ignore "-" and ">" ("->")		# Ignorar "-" y ">" ("->")
	if ( action == "PROXY" || action == "FORWARD" ){
	    nat = $6
	    gsub ( "[->]*", "", nat )
	# SPLIT REMOTE IP FROM PORT	# SEPARAR IP REMOTA DE PUERTO
	    split ( nat, parts, ":" )
	    if ( parts[1] ~ IS_IP ) {
		nat_ip = parts[1]
		nat_port = "" parts[2]		# "" 0 = ASCII 0
	    }
	    else{				# No hay IP
		nat_ip = ""
		nat_port = "" nat		# "" 0 = ASCII 0
	    }
	}
	else nat = ""

    # REPLACING "HI" o "$HI"		# SUSTITUYO "HI" o "$HI"
	if ( local_port ~ "^[\$]?HI$" ) local_port = hi
	if ( remote_port ~ "^[\$]?HI$" ) remote_port = hi

    # LOOP FOR REMOTE IP		# BUCLE PARA VARIAS IP REMOTAS
	if ( remote ~ SEVERAL_VALUES ) {
	    print "for IP_R in " remote "; do"
	    remote = "$IP_R"
	}
    # LOOP FOR LOCAL IP			# BUCLE PARA VARIAS IP LOCALES
	if ( local ~ SEVERAL_VALUES ) {
	    print "for IP_L in " local "; do"
	    local = "$IP_L"
	}
    # SEVERAL PROTO ("," separated)	# VARIOS PROTOS (separados por comas)
	split ( $2, proto, "," )
	for ( n in proto ) {
    # MOUNT RULE			# MONTAR REGLA
	    put_rule( action, to_log, prio, interface_tmp, proto[n], \
		local, local_port, $4, remote, remote_port, nat_ip, nat_port )
	}
    # END OF LOOPS			# FINAL DE BUCLES
	if ( local ~ SEVERAL_VALUES ) print "done"
	if ( remote ~ SEVERAL_VALUES ) print "done"
    }


#############################################################################
# AFTER PROCESSING THE LAST LINE	# DESPUES DE PROCESAR LA ULTIMA LINEA
# OF THE RULES FILE			# DEL ARCHIVO DE REGLAS
#############################################################################

    END{
    # END OF PREVIOUS INTERFACE LOOP	# FIN DE BUCLE INTERFACES ANTERIOR
	if ( interface ~ SEVERAL_VALUES ) {
	    print "done		# End of last INTERFACE for loop"
	}
	print ""

    # LAST RULES AT THE END		# ULTIMAS REGLAS AL FINAL
	ending()
    }


#############################################################################
# FUNCTIONS				# FUNCIONES
#############################################################################

    # ERROR: Syntax errors arrive here	# ERROR: Los errores de sintaxis vienen
    #					# aqui
    # I put echo in the script so	# Pongo echos en el script de manera
    # errors are shown when run		# que muestre errores al lanzarlo

    function error( err ){
	print "echo"
	print "echo \"	SYNTAX ERROR IN: " err "\""
	print "echo \"	" $0 "\""
	print "echo"
    }


#---------------VARIABLE PART-----------#---------------PARTE VARIABLE---------
#--dependent of ipchains, iptables------#--dependiente de ipchains, iptables---


# BEGINING OF FIREWALL SHELL SCRIPT	# PRINCIPIO DEL SCRIPT SHELL

    function begining( ){
	print "#!/bin/sh"
	print "#	firewall-iptables"
	print "#"
	print "#	GENERADO POR / FILE GENERATED BY: fwgen-iptables"
	print "#"
	print "#	Este script monta un cortafuegos con iptables"
	print "#	This script mounts firewall with iptables"
	print "#"
	print ""
	print "# DEFAULTS"
	print "PATH=/usr/lib/firewall-easy:/sbin:/usr/sbin:/bin:/usr/bin"
	print ""
	print "# THIS IS TO BE ABLE TO DO LOGALLDENY AND RSTALLDENY"
	print "DROP=DROP"
	print "DROPLOG=DROPLOG"
	print ""
	print ""
	print "# LOAD DEFAULT CONFIG FILE"
	print ". /etc/firewall-easy.conf"
	print ""
	print "# DEBUG"
	print "if [ \"$DEBUG\" != \"\" ]; then export DEBUG; fi"
	print ""
	print "# LOGALLDENY"
	print "if [ \"$LOGALLDENY\" != \"\" ]; then DROP=DROPLOG; fi"
	print ""
	print "# RSTALLDENY"
	print "if [ \"$RSTALLDENY\" != \"\" ]"
	print "then"
	print "  DROP=RST"
	print "  DROPLOG=RSTLOG"
	print "fi"
	print ""
	print ""
	print "# ASEGURANDO EL KERNEL / SECURING KERNEL"
	print "secure-kernel-24"
	print ""
	print "echo \"-> Setting up firewall (firewall-iptables)\""
	print ""
	print "# ESTABLECER POLITICA DEL CORTAFUEGOS / FW POLICY DENY"
	print "echorun iptables -P INPUT DROP		# default policy"
	print "echorun iptables -P FORWARD DROP"
	print "echorun iptables -P OUTPUT DROP"
	print ""
	print "# BORRAR REGLAS ANTERIORES / DELETE PREVIOUS RULES"
	print "echorun iptables -F			# flush everything"
	print "echorun iptables -t nat -F"
	print "echorun iptables -t mangle -F"
	print "echorun iptables -X			# delete all chains"
	print "echorun iptables -t nat -X"
	print "echorun iptables -t mangle -X"
	print ""
	print "# CREATE CHAINS				# CREAR CADENAS"
	print ""
	print "# We need IN and OUT because we can not	# Necesitamos IN y OUT porque no se"
	print "# do -A FORWARD -o $IFACE -j INPUT	# puede -A FORWARD -o $IFACE -j INPUT"
	print ""
	print "# IN					# IN"
	print "echorun iptables -N IN"
	print "echorun iptables -F IN"
	print "echorun iptables -A INPUT -j IN"
	print ""
	print "# OUT					# OUT"
	print "echorun iptables -N OUT"
	print "echorun iptables -F OUT"
	print ""
	print "# LIMIT OF LOGING (DOS)			# LIMITACION DE LOG (SEGURIDAD)"
	print "# limiting max log to 3/minute to	# Limito mximo registro a 3/minute"
	print "# avoid flood in attack			# para evitar inundacin en ataque"
	print ""
	print "# ACCEPT & LOG				# ACCEPT Y LOG"
	print "echorun iptables -N ACCEPTLOG"
	print "echorun iptables -F ACCEPTLOG"
	print "echorun iptables -A ACCEPTLOG -m limit --limit 3/minute \
  -j LOG --log-prefix \"ACCEPT->\""
	print "echorun iptables -A ACCEPTLOG -j ACCEPT"
	print ""
	print "# DROP & LOG				# DROP Y LOG"
	print "echorun iptables -N DROPLOG"
	print "echorun iptables -F DROPLOG"
	print "echorun iptables -A DROPLOG -m limit --limit 3/minute \
  -j LOG --log-prefix \"DROP->\""
	print "echorun iptables -A DROPLOG -j DROP"
	print ""
	print "# RST					# RST"
	print "echorun iptables -N RST"
	print "echorun iptables -F RST"
	print "echorun iptables -A RST -p tcp -j REJECT --reject-with tcp-reset"
	print "echorun iptables -A RST -p udp -j REJECT"
	print "echorun iptables -A RST -j DROP"
	print ""
	print "# RST & LOG				# RST Y LOG"
	print "echorun iptables -N RSTLOG"
	print "echorun iptables -F RSTLOG"
	print "echorun iptables -A RSTLOG -m limit --limit 3/minute \
  -j LOG --log-prefix \"REJECT->\""
	print "echorun iptables -A RSTLOG -p tcp -j REJECT --reject-with tcp-reset"
	print "echorun iptables -A RSTLOG -p udp -j REJECT"
	print "echorun iptables -A RSTLOG -j DROP"
	print ""
	print "# PROHIBIR FRAGMENTOS / DENY FRAGMENTS"
	print "echorun iptables -A IN -f -j $DROP"
	print ""
	print "# ALLOW INPUTS OF RST AT lo IFACE FOR TESTING"
	print "echorun iptables -A IN -j ACCEPT -i lo -p tcp --tcp-flags RST RST -d 1.1.1.1 -s 1.1.1.1"
	print ""
	print "# LIMIT OUTPUT ON OWNER USER OR GROUP"
	print "for NAME in $USERCONN; do"
	print "  EVERYBODY=no"
	print "  case $NAME in"
	print "    NO)"
	print "      NAME=\"\";;"
	print "    ALL)"
	print "      echorun iptables -A OUTPUT -j OUT;;"
	print "    *)"
	print "      echorun iptables -A OUTPUT -j OUT -m owner --uid-owner $NAME;;"
	print "  esac"
	print "done"
	print "for NAME in $USERREPLY; do"
	print "  EVERYBODY=no"
	print "  case $NAME in"
	print "    NO)"
	print "      NAME=\"\";;"
	print "    ALL)"
	print "      echorun iptables -A OUTPUT -j OUT -m state --state ESTABLISHED,RELATED;;"
	print "    *)"
	print "      echorun iptables -A OUTPUT -j OUT -m state --state ESTABLISHED,RELATED -m owner --uid-owner $NAME;;"
	print "  esac"
	print "done"
	print "if [ \"$EVERYBODY\" = \"no\" ]; then"
	print "  echorun iptables -A OUTPUT -j DROPLOG"
	print "else"
	print "    # NORMAL OUTPUT"
	print "  echorun iptables -A OUTPUT -j OUT"
	print "fi"
	print ""
	print ""
	
	
	print "##### firewall-easy-lib ####################################"
    }


    function put_import ( file ){
	print ""
	print "# IMPORTING VARS FROM CONFIG FILE: " file
	print ". " file
	print ""
	print "# DEBUG"
	print "if [ \"$DEBUG\" != \"\" ]; then export DEBUG; fi"
	print ""
	print "# LOGALLDENY"
	print "if [ \"$LOGALLDENY\" != \"\" ]; then DROP=DROPLOG; fi"
	print ""
	print "# RSTALLDENY"
	print "if [ \"$RSTALLDENY\" != \"\" ]"
	print "then"
	print "  DROP=RST"
	print "  DROPLOG=RSTLOG"
	print "fi"
    }


# PUT_RULE: generate valid rules	# PUT_RULE: genera reglas coherentes
# with paramenters given		# con los parmetros que se le dan
# Not allowed several values of		# No admite varios valores de from,
# from, proto, etc... just one		# proto, etc... Sino solo uno
#
# action 	NO, >, >>, *, RST, MASQUERADE, PROXY, FORWARD
# to_log	"", !
# prio		"", ++, +, -, --
# iface		"", *, eth0, ppp0
# proto		*, tcp, udp, icmp, ... (/etc/protocols)
# local		*, $DNS, 1.2.3.4
# local_port	"", *, domain, 53, 1:1024
# dir		>, <, <>
# remote	= local
# remote_port	= local_port
# nat_ip	= local (optional)
# nat_port	= local_port (optional)

    function put_rule ( action, to_log, prio, iface, proto, \
	local, local_port, dir, remote, remote_port, nat_ip, nat_port ){

    # CONVERT "*" TO ""			# NORMALIZO "*" A ""

	if ( iface == "*" )	 iface = ""
	if ( proto == "*")	 proto = ""
	if ( local == "*")	 local = ""
	if ( local_port == "*")	 local_port = ""
	if ( remote == "*")	 remote = ""
	if ( remote_port == "*") remote_port = ""
	if ( nat_ip == "*")	 nat_ip = ""
	if ( nat_port == "*")	 nat_port = ""


    # CHOOSE PROPER FUNCTION		# ELEGIR LA FUNCION ADECUADA
    # put_filter, put_masquerade, put_redir, put_port_forward

	if ( action == "FORWARD" ) {
	    put_port_forward( action, to_log, prio, iface, proto, \
	      local, local_port, dir, remote, remote_port, nat_ip, nat_port )
	}
	else if ( action == "PROXY" ) {
	    put_redir( action, to_log, prio, iface, proto, \
	      local, local_port, dir, remote, remote_port, nat_ip, nat_port )
	}
	else if ( action == "MASQUERADE" ) {
	    put_masquerade( action, to_log, prio, iface, proto, \
	      local, local_port, dir, remote, remote_port, nat_ip, nat_port )
	}
	else {
	    put_filter( action, to_log, prio, iface, proto, \
	      local, local_port, dir, remote, remote_port, nat_ip, nat_port )
	}
    }


# FILTER + PROXY: ipchains		# FILTER + PROXY: ipchains

    function put_filter ( action, to_log, prio, iface, proto, \
	local, local_port, dir, remote, remote_port, nat_ip, nat_port ){

    # TRANSLATING TO ipchains		# TRADUCCION A ipchains
    # REMEMBER: add space at end	# RECUERDA: dejar un espacio al final
    # of every string			# de cada cadena
    # t is a traslating array		# t es un array de traduccin

	input = "echorun iptables -A IN "
	output = "echorun iptables -A OUT "
	input_tos = "echorun iptables -t mangle -A PREROUTING -j TOS "

	if ( to_log ) {
	    t["*"] = "-j ACCEPTLOG "		# with log	# con log
	    t[">"] = "-j ACCEPTLOG "
	    t[">>"] = "-j ACCEPTLOG "
	    t["NO"] = "-j $DROPLOG "		
	    t["RST"] = "-j RSTLOG "
	}
	else {
	    t["*"] = "-j ACCEPT "		# without log	# sin log
	    t[">"] = "-j ACCEPT "
	    t[">>"] = "-j ACCEPT "
	    t["NO"] = "-j $DROP "
	    t["RST"] = "-j RST "
	}

	t["++"] = "--set-tos 0x10 "	# IPTOS_LOWDELAY
#	t["+"] = "--set-tos 0x18 "		# LOWDELAY + THROUGHPUT
	t["+"] = "--set-tos 0x10 "	# Bug in 0x18 in iptables (9 June 2001)
	t["-"] = "--set-tos 0x08 "	# IPTOS_THROUGHPUT
	t["--"] = "--set-tos 0x02 "	# IPTOS_MINCOST


    # SYNTAX ERRORS			# ERRORES DE SINTAXIS
    # all errors begining with		# todos los errores que empiezan
    # "/" are from variable part	# con "/" son de la parte variable

	if ( t[action] == "" ) error( "/action unknown" )
	if ( dir != "<" && dir != ">" && dir != "<>" ) error( "/dir invalid" )
	if ( prio != "" && t[prio] == "" ) error( "/prio unknown" )


    # LOAD ip_conntrack_ftp IF NEEDED	# CARGAR ip_conntrack_ftp SI NECESARIO
    # available and not already done	# disponible y no hecho ya
	if ( action == ">>" ){
	    if ( remote_port == "ftp-data" || remote_port == "20" || \
		  local_port == "ftp-data" || local_port == "20" ){
		if ( conntrack_ftp_loaded != "yes" ){
		    print ""
		    print "# LOADING CONNECTION TRACKING FTP"
		    print "# CARGANDO SEGUIMIENTO DE CONEXIONES FTP"
		    print " debug \"insmod ip_conntrack_ftp\""
		    print "insmod -p ip_conntrack_ftp > /dev/null 2>&1 && \
			insmod ip_conntrack_ftp"
		    print ""
		    conntrack_ftp_loaded = "yes"
		}
	    }
	}


    # PROCESS ">" AND ">>"		# PROCESAR ">" Y ">>"
    # we can also deny input SYN	# Tambien podemos impedir paquetes SYN
    # packets in tcp			# de entrada en tcp

	if ( action == ">" ) {
	    established = "-m state --state ESTABLISHED "
	    if ( proto == "tcp" ) established = established "! --syn "
	}
	else if ( action == ">>" ) {
	    established = "-m state --state ESTABLISHED,RELATED "
	}
	else { established = "" }


    # NO PORT WITHOUT IP ALLOWED	# NO PUEDE HABER PUERTO SIN IP
    # PUT 0/0 (any IP)			# PONER 0/0 (cualquier IP)

	if ( local == "" && local_port ) local = "0/0"
	if ( remote == "" && remote_port ) remote = "0/0"


    # LOCAL SIDE			# LADO LOCAL
	input_to = ""; 	output_from = ""
	input_to_port = ""; output_from_port = ""

	if ( local ) {
	    input_to = "-d " local " "
	    output_from = "-s " local " "
	}
	if ( local_port && proto != "icmp" ) {
	    input_to_port = "--dport " local_port " "
	    output_from_port = "--sport " local_port " "
	}
	if ( local_port && proto == "icmp" ) {
	    input_to_port = output_from_port = "--icmp-type " local_port " "
	}

    # REMOTE SIDE			# LADO REMOTO
	output_to = ""; input_from = ""
	output_to_port = ""; input_from_port = ""

	if ( remote ) {
	    output_to = "-d " remote " "
	    input_from = "-s " remote " "
	}
	if ( remote_port && proto != "icmp" ) {
	    output_to_port = "--dport " remote_port " "
	    input_from_port = "--sport " remote_port " "
	}
	if ( remote_port && proto == "icmp" ) {
	    output_to_port = input_from_port = "--icmp-type " remote_port " "
	}


    # GENERATING PARAMETERS		# GENERO PARAMETROS

	if ( iface ) iface_in = "-i " iface " "
	else iface_in = ""
	if ( iface ) iface_out = "-o " iface " "
	else iface_out = ""

	if ( proto ) proto = "-p " proto " "


    # ASSEMBLING INPUT RULE		# ENSAMBLO REGLA DE ENTRADA
	if ( dir ~ "<" ) {
	    print input t[action] iface_in proto established \
		input_to input_to_port input_from input_from_port

	    if ( prio ) print input_tos t[prio] proto \
		input_to input_to_port input_from input_from_port
	}

    # ASSEMBLING OUTPUT RULE		# ENSAMBLO REGLA DE SALIDA
	if ( dir ~ ">" ) {
	    print output t[action] iface_out proto \
		output_from output_from_port output_to output_to_port

	    if ( prio ) print input_tos t[prio] proto \
		output_from output_from_port output_to output_to_port
	}
    }


# MASQUERADE				# ENMASCARAMIENTO

    function put_masquerade ( action, to_log, prio, iface, proto, \
	local, local_port, dir, remote, remote_port, nat_ip, nat_port ){

    # IF USING MASQ			# SI SE USA MASQ activar
    # activate forward (only once)	# forward (solo una vez)

	if ( forward_enabled != "yes" ){
	    print ""
	    print "# ENABLING FORWARD (needed by MASQUERADE)"
	    print "# ACTIVANDO FORWARD (necesario para MASQUERADE)"
	    print " debug \"echo 1 > /proc/sys/net/ipv4/ip_forward\""
	    print "echo 1 > /proc/sys/net/ipv4/ip_forward"
	    print ""
	    forward_enabled = "yes"
	}


    # SYNTAX ERRORS			# ERRORES DE SINTAXIS
    # all errors begining with		# todos los errores que empiezan
    # "/" are from variable part	# con "/" son de la parte variable

	if ( dir != ">" ) error ( "/dir != > in MASQUERADE" ) 


    # NO PORT WITHOUT IP ALLOWED	# NO PUEDE HABER PUERTO SIN IP
    # PUT 0/0 (any IP)			# PONER 0/0 (cualquier IP)

	if ( local == "" && local_port ) local = "0/0"
	if ( remote == "" && remote_port ) remote = "0/0"


    # GENERATING PARAMETERS		# GENERO PARAMETROS

	if ( local ) local = "-s " local " "
	if ( local_port ) {
	    if ( proto != "icmp" ) local_port = "--sport " local_port " "
	    if ( proto == "icmp" ) local_port = "--icmp-type " local_port " "
	}
	if ( remote ) remote = "-d " remote " "
	if ( remote_port ) {
	    if ( proto != "icmp" ) remote_port = "--dport " remote_port " "
	    if ( proto == "icmp" ) remote_port = "--icmp-type " remote_port " "
	}

	masquerade = "-j MASQUERADE "

	if ( iface ) iface = "-o " iface " "
	if ( proto ) proto = "-p " proto " "


    # ASSEMBLING RULE			# ENSAMBLO REGLA

	print "echorun iptables -t nat -A POSTROUTING " iface proto \
	     masquerade local local_port remote remote_port
    }



# PROXY					# REDIRECCION DE PUERTO

    function put_redir ( action, to_log, prio, iface, proto, \
	local, local_port, dir, remote, remote_port, nat_ip, nat_port ){

    # SYNTAX ERRORS			# ERRORES DE SINTAXIS
    # all errors begining with		# todos los errores que empiezan
    # "/" are from variable part	# con "/" son de la parte variable

	if ( nat_ip != "" ) error ( "/NAT IP in PROXY not allowed" ) 
	if ( nat_port == "" ) error ( "/NAT port absent" )
	if ( dir != "<" ) error ( "/dir != < in PROXY" ) 
	if ( proto == "" ) error ( "/proto == * in PROXY" )


    # NO PORT WITHOUT IP ALLOWED	# NO PUEDE HABER PUERTO SIN IP
    # PUT 0/0 (any IP)			# PONER 0/0 (cualquier IP)

	if ( local == "" && local_port ) local = "0/0"
	if ( remote == "" && remote_port ) remote = "0/0"


    # GENERATING PARAMETERS		# GENERO PARAMETROS

	if ( local ) local = "-d " local " "
	if ( local_port ) {
	    if ( proto != "icmp" ) local_port = "--dport " local_port " "
	    if ( proto == "icmp" ) local_port = "--icmp-type " local_port " "
	}
	if ( remote ) remote = "-s " remote " "
	if ( remote_port ) {
	    if ( proto != "icmp" ) remote_port = "--sport " remote_port " "
	    if ( proto == "icmp" ) remote_port = "--icmp-type " remote_port " "
	}

	nat_port = "-j REDIRECT --to-port " nat_port " " 

	if ( iface ) iface = "-i " iface " "
	if ( proto ) proto = "-p " proto " "


    # ASSEMBLING RULES			# ENSAMBLO REGLAS

	print "echorun iptables -t nat -A PREROUTING " iface proto \
	    nat_port local local_port remote remote_port
	print "echorun iptables -t nat -A OUTPUT " proto \
	    nat_port local local_port remote remote_port
    }



# PORT FORWARDING			# PORT FORWARDING

    function put_port_forward ( action, to_log, prio, iface, proto, \
	local, local_port, dir, remote, remote_port, nat_ip, nat_port ){

    # SYNTAX ERRORS			# ERRORES DE SINTAXIS
    # all errors begining with		# todos los errores que empiezan
    # "/" are from variable part	# con "/" son de la parte variable

	if ( nat_ip == "" ) error ( "/NAT IP absent" ) 
	if ( nat_port == "" ) error ( "/NAT port absent" )
	if ( dir != "<" ) error ( "/dir != < in FORWARD" ) 
	if ( proto == "" ) error ( "/proto == * in FORWARD" )


    # NO PORT WITHOUT IP ALLOWED	# NO PUEDE HABER PUERTO SIN IP
    # PUT 0/0 (any IP)			# PONER 0/0 (cualquier IP)

	if ( local == "" && local_port ) local = "0/0"
	if ( remote == "" && remote_port ) remote = "0/0"
	if ( nat_ip == "" && nat_port ) nat_ip = "0/0"


    # GENERATING PARAMETERS		# GENERO PARAMETROS

	if ( local ) local = "-d " local " "
	if ( local_port ) {
	    if ( proto != "icmp" ) local_port = "--dport " local_port " "
	    if ( proto == "icmp" ) local_port = "--icmp-type " local_port " "
	}
	if ( remote ) remote = "-s " remote " "
	if ( remote_port ) {
	    if ( proto != "icmp" ) remote_port = "--sport " remote_port " "
	    if ( proto == "icmp" ) remote_port = "--icmp-type " remote_port " "
	}

	nat = "-j DNAT --to-destination " nat_ip
	if ( nat_port ) nat = nat ":" nat_port " "

	if ( iface ) iface = "-i " iface " "
	if ( proto ) proto = "-p " proto " "


    # ASSEMBLING RULES			# ENSAMBLO REGLAS

	print "echorun iptables -t nat -A PREROUTING " iface proto \
	    nat local local_port remote remote_port
	print "echorun iptables -t nat -A OUTPUT " proto \
	    nat local local_port remote remote_port
    }



# ENDING OF FIREWALL SHELL SCRIPT	# FINAL DEL SCRIPT SHELL

    function ending( ){
	print ""
	print "# FORWARD MUST USE INPUT OR OUTPUT	# FORWARD DEBE USAR INPUT O OUTPUT"
	print "# If packet is out towards a local	# Si un paquete sale hacia un iface"
	print "# iface is because it INPUT from inet	# local es porque ENTRO de Internet"
	print ""
	print "for IFACE_L in $FORWARD_IFACES"
	print "do"
	print "echorun iptables -A FORWARD -o $IFACE_L -j IN"
	print "echorun iptables -A FORWARD -i $IFACE_L -j OUT"
	print "done"
	print ""
	print "# LOG ALL OTHER FORWARD TRIALS"
	print "echorun iptables -A FORWARD -j DROPLOG"
	print ""
	print "# TEST FIREWALL"
	print "if [ \"$TESTFW\" != \"\" ]; then testfw; fi"
    }


' > $TO 

chmod ugo+x $TO		# Exec perms 	# Permisos de ejecucin

