Iptables. El firewall del kernel de Linux

En este artículo vamos a explicar brevemente el firewall iptables. La configuración por Iptables es compleja y complicada. Requiere muchas veces, largas cadenas de parámetros. Por ese motivo suele preferirse utilizar interfaces de firewall como 'ufw' o 'firewallD' pero hay que tener muy presente que siempre por debajo estará Iptables que es el verdadero firewall de Linux. De ahí que se llame a Iptables como el firewall del núcleo o kernel. Profundizando un poco más, debemos decir que iptables es parte de netfilter y sería este el verdadero firewall pero la cultura popular acabó usando el término iptables.

Por la gran cantidad de opciones posibles en este primer artículo solamente es posible cubrir una introducción y una lista de ejemplos de casos muy comunes. Como siempre recomiendo consultar man iptables

Hacer experimentos con iptables en el firewall de un VPS tiene el riesgo de que por error filtremos las conexiones SSH y no podemos acceder a nuestro propio servidor. Algunos proveedores de servidores tienen un panel de control por web que permite anular la reglas de firewall en caso de emergencia.

Por prudencia, algunas de las prácticas serán demostradas en una máquina virtual en local mientras que otras serán en un VPS real.

Estructura de Iptables

Una sentencia con iptables puede tener una estructura como esta:

# iptables -t [tabla] [commando] [cadena] [match] -j [target]

Como veremos pronto en los ejemplos, esta estructura puede ser mas corta o larga dependiendo de la regla a aplicar. Tomaremos esto como un punto de inicio para comentar algunos de los parámetros comunes que se usan. Aunque no es una extructura exacta nos ayudará a construir y comprender la creación de reglas. Si ya has consultado la 'manpage' te habras dado cuenta de la magnitud de parámetros variados que puede tener iptables.

En la sinopsis anterior de iptables hay 5 partes: tabla, comando, cadena, match y target.

1.- Las tablas puede tener estos valores:

  • filter. Es la opción por defecto y a la que nos centraremos en este artículo por ser lo más común en redes pequeñas. Las tablas filter sirven para filtrar paquetes ( aceptar, descartar o rechazar o enrutar).
  • nat(Network Address Translation). Decidir que se hace con el paquete antes o después de ser enrutado.
  • mangle. De escaso uso. Sirve para modificar la estructura interna de un paquete con datos que afectan a su TTL (tiempo de vida) o ancho de banda.
  • security. Reglas que funcionan independientemente del subsistema de seguimiendo de conexiones Netfilter

Si se omite la tabla se toma como predeterminada la tabla filter. En este artículo solo veremos ejemplos de este tipo.

2.- En comando se define la acción sobre la cadena. Las más comunes son:

  • -A Append. Añadir una sentencia al final de la cadena.
  • -I Insert. inserta una regla en una posición específica de la cadena. Si no se especifica ocupará la primera posición.
  • -L List. Listar las sentencias de la cadena.
  • -D Delete. Borrar una sentencia de la cadena.
  • -X Borra la cadena especificada o si no se especifica ninguna borra las definidas por el usuario.
  • -F Flush. Borra todas las sentencias de la cadena.

3.- Cada grupo de reglas según sea para entradas, salidas, redireccionar,... se define como una cadena.

Las tablas filter tienen estas cadenas:

  • INPUT. Para paquetes con destino al equipo.
  • OUTPUT. Para paquetes con origen de si mismo y dirigidos a otro equipo
  • FORWARD. Para paquetes de paso. Llegan al sistema local pero tienen como destino otro equipo en la red

Las tablas nat tienen estas cadenas:

  • PREROUTING. Modifica cabeceras del paquete antes de que el sistema local ejecute el enrutamiento.
  • POSTROUTING. Modifica cabeceras del paquete después de que el sistema local ejecute el enrutamiento.
  • OUTPUT. Modifica los paquetes generados localmente antes del enrutamiento.

Consulta la 'manpage' para cadenas de raw y mangle.

4.- En match con el parámetro -m o --match se pueden añadir los llamados módulos o extensiones opcionales que sirven para poner una o mas condiciones que deben cumplirse. Módulos hay muchos, ejemplos: -m mac –mac-source 00:11:22:33:44:55 para filtrar una MAC, -m multiport –source-port 22,23,80:100 para poner varios puertos o rangos de puertos. Uno que usaremos mucho es -m conntrack que se usa conjuntamente con --ctstate para hacer seguimiento de si el paquete es de una conexión nueva, una ya establecida en curso, etc. Cuando filtremos los puertos comunes de web http y https hay que incluir en la sentencia -m conntrack --ctstate NEW,ESTABLISHED. Mas info en https://ipset.netfilter.org/iptables-extensions.man.html

Las más comunes son:

  • -s source, IP de la red de origen
  • -d destination, IP de la red de destino
  • --sport source port, puerto TCP de origen
  • --dport destination port, puerto TCP de destino
  • -p tipo de protocolo: tcp, udp, udplite, icmp, esp, ah, sctp
  • -i input, interfaz de entrada
  • -o output, interfaz de salida

5.- -j viene de jump y el target define que acción realizar con el paquete cuando cumple los criterios del match:

  • ACCEPT. Aceptar el paquete.
  • REJECT. Rechazar el paquete y dar respuesta ICMP
  • DROP. Desechar el paquete. El cliente pasado un tiempo solo recibe mensaje de que no se ha recibido contestación del equipo.
  • REDIRECT. Redirige el paquete hacia donde se le indique en el match
  • LOG. Crea un registro en el syslog
Sintetizando un poco

Tras esta saturación de parámetros como conclusión hay que tener muy claro que en la tabla 'filter' tenemos 3 políticas:

  • INPUT comportamiento del firewall en los paquetes entrantes
  • OUTPUT comportamiento del firewall en los paquetes salientes
  • FORWARD comportamiento del firewall en los paquetes redireccionados

y que cada una de estas tablas tendrá unas cadenas que definen las reglas.

Por medio de parámetros podremos añadir, modificar y borrar reglas a la cadena.

Primera toma de contacto con iptables

Una buena forma de tocar iptables es conociendo cuales son las reglas que actualmente tiene el firewall. Con la siguiente sentencia vemos todas las reglas existentes mostrándolas en líneas numeradas.

sudo iptables --line-numbers -nL

El parámetro --line-numbers numera cada una de las reglas. Muy útil para borrar reglas por su número. El parámetro nL en verdad son 2: la n muestra con números las direcciones IP y puertos. La L es para Listar reglas.

Se pueden listar entradas o salidas de manera independiente:

# Para entradas añadir INPUT
sudo iptables --line-numbers -nL INPUT
# Para salidas añadir OUTPUT
sudo iptables --line-numbers -nL OUTPUT
# Para redirecionado añadir FORWARD
sudo iptables --line-numbers -nL FORWARD

Borrar todas las reglas

Para borrar absolutamente todo de iptables y configurarlo de cero tenemos que entrar varias líneas. Antes de nada y para evitar quedarnos sin poder entrar por SSH debemos establecer por defecto que aceptamos todas las conexiones en las 3 políticas.

sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

A continuación podemos borrar todas las reglas de las tablas nat, mangle y filter

sudo iptables -t nat -F
sudo iptables -t mangle -F
sudo iptables -F # como filter es la tabla por defecto no face falta -t filter

Por último, borramos todas las cadenas que no se usan.

sudo iptables -X

Tras esto podemos comprobar que se permiten todas las entradas y salidas y no tenemos reglas. Con el ya conocido comando iptables -nL nos aparecen las 3 cadenas limpias.

Cambios persistentes

Los cambios en las tablas no son permanentes. Si reiniciamos el servidor volverá a tener la última configuración predeterminada. Para dejar los cambios permanentes se puede hacer de varias maneras y dependerá sobre que sistema Ubuntu estemos.

Una manera sencilla es con el comando iptables-save pero veo que en esta máquina no funciona como se espera. Tras pruebas, consultar manuales y perder mucho tiempo encuentro la solución en Stackoverflow. Es necesario instalar los siguientes paquetes porque en mi sistema iptables venía incompleto. Realmente, fue un poco doloroso encontrar la forma de que funcione ya que, como siempre pasa, hay muchos versiones de servidores y aparecen excepciones y comportamientos inesperados. En esta versión de Ubuntu al incorporar el firewall ufw afecta a la parte de iptables. En otros nos podemos encontrar firewallD que también puede hacer que al manipular directamente las reglas sobre iptables no funcione como se espere. Por supuesto que si lo que queremos es gestionar el firewall desde iptables se debe deshabilitar cualquier otra interfaz de firewall que tengamos. A fecha de hoy 'ufw' o 'firewallD' son dos interfaces que suelen venir predeterminadas en las distros Ubuntu.

# instalar paquetes para que iptables tenga persistencia
sudo apt install iptables-persistent netfilter-persistent

Tras instalar los paquetes se crearán en /dir/iptables/ los archivos rules.v4 y rules.v6. Cada vez que se reinicie el servicio iptables o el propio servidor se cargará las reglas de estos archivos. Podemos editarlos manualmente y añadir o quitar reglas o bien ponemos usar un comando que graba la configuración actual en el archivo. En mi caso como uso el protocolo IPv4 grabaremos sobre rules.v4

Con el operador de redirección > cargamos en el archivo la configuración actual de iptables.

sudo /sbin/iptables-save > /etc/iptables/rules.v4

También tenemos la posibilidad de cargar archivos de reglas ya sea porque tenemos varios perfiles de firewall o para restaurar la configuración.

sudo /sbin/iptables-restore < /etc/iptables/otrasreglas.v4

Para comprobar que los cambios son persistentes reiniciamos el servicio iptables.(NOTA: Algo extraño que me ocurre a veces es que tras reiniciar iptables las reglas aparecen duplicadas y tengo que reiniciar el servidor para que salgan solo una vez.)

sudo service iptables restart

Con esto aprendido me sale la duda de que pasará en mis servidores Oracle Cloud. Tras algunos pruebas veo que todo funciona bien según lo explicado anteriormente. Incluso aunque trae ufw instalado, la isntancia de Ubuntu ya incluye la persistencia sin tener que instalar nada. No ocurre igual en mis pruebas con Hostinger. Tengo también Ubuntu 18.01 con firewallD pero no hay persistencia y se requiere instalar los paquetes iptables-persistent y netfilter-persistent. Como ves cada servidor es un mundo.

Aprovechando que estoy en Oracle Cloud vamos a comentar donde crear las reglas en el archivo rules.v4. Este servidor está practicamente vacío y solo trae las reglas de origen.

Listando las reglas numeradas de la cadena INPUT obtenemos esto:

sudo iptables --line-numbers -nL INPUT

Vamos a comentar brevemente que significa cada línea:

  • 1.- En target ACCEPT nos dice que aceptemos conexiones, en prot ALL de todos los protocolos, source 0.0.0.0/0 es con origen de cualquier dirección posible, destination 0.0.0.0/0 a cualquier destino. Al final de la línea están los llamados 'Connection tracking status'. State ESTABLISHED significa aceptar todas las conexiones de cualquier protocolo que previamente han sido establecidas. State RELATED es cuando el paquete está iniciando una nueva conexión pero la nueva conexión está relacionada con una conexión existente (como la conexión de datos para una transferencia FTP).
  • 2.- Aceptar todas las conexiones de cualquier origen, del protocolo ICMP, a cualquier destino.
  • 3.- Aceptar todas las conexiones de cualquier origen, de cualquier protocolo, a cualquier destino.
  • 4.- En este regla se permite el tráfico del Network Time Protocol usado por todos los equipos informáticos para sincronizar los relojes a través del enrutamiento de paquetes. NTP usa UDP puerto 123 como capa de transporte.
  • 5.- Aceptar las comunicaciones con destino (dpt destination port) al puerto 22 que suele ser el de SSH
  • 6.- La última regla rechaza todo el tráfico. Si el paquete entrante no cumple ninguna de las reglas anteriores será rechazado. El icmp-host-prohibited es solo el mensaje de rechazo con el que se rechaza el paquete. Eso significa que su servidor notificará al remitente que el paquete fue rechazado con ese mensaje.

¿Qué pasaría si no existiera la regla 6? Pues que como anteriormente le hemos dicho que acepte todas las conexiones el servidor quedará expuesto a cualquier entrada venga de donde venga. En el caso concreto de Oracle Cloud como hay también un firewall de infraesctructura salvo que también exista esa peligrosa regla de aceptar todo, no estará el servidor abierto.

¿Qué pasaría si la regla 6 ocupara la posición 1? iptables aplica las reglas en orden de aparición. Esto quiere decir que si la primera regla es rechazar todo, las reglas siguientes no van a funcionar.

Añadir y eliminar reglas

El borrado y creación de nuevas reglas se puede hacer de 2 formas: editando el archivo rules.v4 o por comandos. Comentamos anteriormente que el parámetro (add) añade una regla, -I inserta una regla en una posición y el comando -D (delete) borra. Editar directamente el archivo rules.v4 se tiene que hacer con sumo cuidado y no tener errores de sintaxis o entrar reglas que no permitan tener control del servidor. Personalmente prefiero probar las reglas con comandos y cuando veo que funcionan como se espera las hago permanentes.

Siguiendo con el servidor Oracle Cloud vamos a abrir los puertos 80 y 443 de http y https. En el artículo 'Introducción a Oracle Cloud Infraestructura OCI. Parte 2' se explica como crear las reglas del firewall de infraestructura. Aquí solo veremos como crear las reglas del lado VPS Ubuntu.

¿En cual posición de la cadena INPUT colocar la regla? Antes de la regla que rechaza todo que aparece en último lugar. Entonces eso quiere decir que no puede usar el parámetro -A ya que añade reglas al final de la cadena. Usaremos -I con un número de índice. Si ponemos el 6, ocupará este lugar y la regla REJECT será desplazada a la línea 7.

Llegados a este punto ya se que el comienzo de mi sentencia iptables empezará así: sudo iptables -I INPUT 6. Traducido en lenguaje humano "Insertar en la posición 6 de la cadena para entradas INPUT"

La sentencia también debe indicar protocolo y puerto. Para ello -p tcp y --dport 80. Como http usa el puerto tcp 80 se lo indico en la cadena.

El siguiente parámetro es más complejo, el apartado -m o --match. Recordemos el enlace donde sacar la documentación de los módulos: https://ipset.netfilter.org/iptables-extensions.man.html

En el caso de abrir entradas para http y https se incluye lo siguiente: -m conntrack --ctstate NEW,ESTABLISHED. "conntrack" viene de connection tracking. Es un módulo usado para crear condiciones al tipo de conexión. En este caso a "conntrack" se le añade la opción ctstate para condicionar el tipo de conexión del paquete. NEW para nuevas conexiones y ESTABLISHED para conexiones previamente establecidas.

El último parámetro es la acción: -j ACCEPT. Si se cumple la regla "se acepta."

La instrucción completa quedará así:

sudo iptables -I INPUT 6 -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Tras esta línea podemos comprobar con sudo iptables --line-numbers -nL INPUT que en la posición 6 se añadió esta regla y la regla final REJECT se desplazó a la línea 7.

Ahora para el puerto 443 podemos repetir el código anterior únicamente cambiando el puerto. También sería posible en una sola línea especificar varios puertos separados por , o rangos de puertos separados por :. Para ello se usa el módulo multiport. Pronto veremos un ejemplo.

Vamos a borrar esta nueva regla creada en la línea 6 y crearemos una nueva que permita entradas por varios puertos de una vez. Para eliminar una regla sabiendo su número de línea se usa sudo iptables -D cadena índice. La D viene de Delete, la cadena es INPUT y como índice el valor 6 que corresponde con la línea que queremos eliminar. La instrucción completa quedará así:

sudo iptables -D INPUT 6

Tras esto añadiremos en una sola orden 2 puertos. Es necesario añadir el módulo multiport y se cambia el parámetro dport por dports

sudo iptables -I INPUT 6 -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Al usar el multiport la regla queda concentrada en una sola línea aunque sean varios puertos.

Otra posibilidad para crear reglas es sustituir el número de puerto por el del servicio. Por ejemplo para abrir el puerto 80 se puede poner -p tcp --dport http, ftp en lugar de 21, https para 443, etc

Todas estas instrucciones en la cadena INPUT para entradas se deberá repetir para la cadena OUTPUT si no tenemos por defecto todas las salidas abiertas. Cada vez es más frecuente en los servidores y redes privadas filtrar las salidas. Será una decisión personal como administras tu accesos a la red.

Vamos a demostrar esto que ocurre cuando cerramos puertos. Actualmente la política de esta instancia de VPS es aceptar todas las salidas. Esto lo podemos comprobar con el conocido sudo iptables --line-numbers -nL OUTPUT

Para comprobar que en la práctica tenemos salida por el puerto 80 podemos usar el comando curl a cualquier página web y la terminal se llenará con caracteres y html que se descarga de esa web. Por ejemplo probamos con curl www.google.es o cualquier otra web que se te ocurra y si aparecen muchas líneas con carecteres quiere decir que hemos descargado algo por URL.

A continuación filtramos la salidas http y https. El formato de la instrucción es idéntico salvo la orden final de ACCEPT, REJECT o DROP. En este caso pondremos REJECT.

sudo iptables -A OUTPUT -p tcp -m multiport --dports http,https -m conntrack --ctstate NEW,ESTABLISHED -j REJECT

Tras este comando las salidas web serán rechazadas. Repetimos nuevamente curl www.google.es y comprobamos que el servidor nos rechaza la conexión con mensaje por protocolo ICMP.

¿Que ocurriría si cambiamos la orden de REJECT por DROP? Tampoco conseguerimos la conexión pero ahora el error es muy opaco. Simplemente dice "que no puede establecerse conexión con esa dirección al no encotrar nada". Para una mayor seguridad del servidor es mejor usar DROP antes que REJECT porque así no damos pistas sobre si realmente existe el servidor evitando ataques indiscriminados a rangos de direcciones IP.

Como estamos de pruebas y no queremos que los cambies sean permanentes haremos un reboot para restablecer las reglas.

Filtrado por IP de origen y destino

Se pueden bloquear paquetes dirigidos o prevenientes en función de la IP. Se usa el parámetro -s de source (origen) o -d destination (destino)

# Filtrar los paquetes dirigidos a la IP 10.0.0.100
iptables -A OUTPUT -d 10.0.0.100 -j DROP

# Filtrar los paquetes que vengan de la IP 10.0.0.100
iptables -A INPUT -s 10.0.0.100 -j DROP

# Filtrar los paquetes con origen del segmento de red 10.0.0.0
iptables -A INPUT -s 10.0.0.0/24 -j DROP

# Filtrar los paquetes con origen del segmento de red 10.0.0.0 que entren por puerto 22 SSH
# --dport es --destination-port abreviado
iptables -A INPUT -s 10.0.0.0/24 -p tcp --dport ssh -j DROP

Filtrado protocolo syn

Un ejemplo interesante que encontré es filtrar las conexiones a servidores web externos. Supongamos que en una intranet se quieren evitar las conexiones WEB del exterior. Para ello debe filtrarse el protocolo SYN con destino al puerto 80. Cuando dos equipos inician conexión por tcp, el que inicia el servicio envía un paquete SYN para indicar que está listo. Si filtramos los paquetes SYN no se podrá iniciar la comunicación.

# Filtrar los paquetes SYN
iptables -A OUTPUT -p tcp --syn --dport 80 -j DROP

Reglas para filtrar algunos conexiones cómunes

A continuación una recopilación de reglas para permitir algunos servicios de uso muy común como web, ftp, ping, etc. Es importante tener en cuenta que estas reglas solo las muestro para la cadena INPUT porque tengo una regla que permite todas las conexiones salientes. Si no fuera este el caso habría que crear para cada regla los permisos de OUTPUT.

En los ejemplos hago uso de la orden ACCEPT para determinados puertos según el servicio.

FTP

FTP es el acrónimo de File Transfer Protocol. Se usa para el intercambio de ficheros entre equipos conectados a una red. Las cuentas de FTP son el medio estándar para gestionar el contenido alojado en un servidor web: enviar archivos, descargarlos, crear directorios, borrar ficheros, etc.

Una opción más segura para el intercambio de ficheros es el protocolo SFTP (SSH File Transfer Protocol) que usa cifrado. Utiliza el puerto 22.

Ftp requiere el puerto 20 para la transferencia y 21 para establecer la conexión.

iptables -A INPUT -p tcp -m multiport --dports 20,21 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

SSH

SSH (o Secure SHell) es un protocolo usado para establecer comunicaciones seguras entre dos sistemas usando una arquitectura cliente/servidor y que permite a los usuarios conectarse a un host remotamente.

Normalmente usa el puerto 22 aunque es recomendable cambiarlo por otro para evitar ataques.

iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT

Servicios WEB

Los protocolos http y https requieren los puertos 80 y 443 respectivamente.

iptables -A INPUT -p tcp -m multiport --dports http,https -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Samba

Samba es una implementación de código abierto del protocolo Server Message Block (SMB). Permite la interconexión de redes Microsoft Windows, Linux, UNIX y otros sistemas operativos juntos, permitiendo el acceso a archivos basados en Windows y compartir impresoras.

El protocolo Samba requiere los puertos 137,138,139 y 445

sudo iptables -A INPUT -p udp -m udp --dport 137 -j ACCEPT
sudo iptables -A INPUT -p udp -m udp --dport 138 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 139 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 445 -j ACCEPT

Bases de datos MySQL y MariaDB

MySQL es la base de datos mas popular del mundo. Inicialmente era un proyecto software libre pero pasó a manos privadas a Sun MicroSystems en 2008 y posteriormente a Oracle en 2010 que la mantiene con licendia dual pública/comercial. Uno de los desarrolladores originales del proyecto descontento con que pasara a manos privadas creó un nuevo proyecto totalmente libre llamado MariaDB con una muy alta compatibilidad con MySQL.

MySQL y MariaDB están en el puerto 3306. Podemos abrir ese puerto para todas las entradas o ser mas restrictivo y que solo se pueda acceder desde el propio servidor.

# aceptar todas las entradas para MySql
iptables -A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT

# aceptar solo conexiones de MySql desde el propio servidor. Sustituir a.b.c.d por la IP del servidor
iptables -I INPUT 8 -p tcp --dport 33306 -s a.b.c.d -j ACCEPT

Ping

El comando ping utiliza el protocolo icmp para enviar y recibir respuestas entre dispositivos.

iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT

El potente iptables nos permite afinar muchísimo que es lo que queremos filtrar. La siguientes líneas sirven de ejemplo de como permitir icmp solo del tipo requerido para ping y además teniendo en cuenta las interfaces de entrada y salida. Recuerda que para saber el nombre de las interfaces se usa ip address

iptables -A OUTPUT -o enp0s3 -p icmp -m icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -i enp0s3 -p icmp -m icmp --icmp-type echo-reply -j ACCEPT

DNS Domain Name System

Para resolver dominios con DNS se utiliza el puerto 53 para entradas y salidas en los protocolos tcp y udp. En iptables esto lo hacemos con:

iptables -A INPUT -p tcp --dport 53 -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

Servidor Minecraft

Un uso lúdico de los VPS es la creación de servidores de juegos para uso particular entre grupos de amigos. En el caso de Minecraft se necesita permitir los accesos al puerto 25565 para tcp y udp.

iptables -A INPUT -p tcp --dport 25565 -j ACCEPT
iptables -A INPUT -p udp --dport 25565 -j ACCEPT

Ampliando la seguridad del servidor

Desde iptables se pueden crear reglas complejas para protegernos de ataques de DoS (denegación de servicio). Esta técnica consiste en generar una petición masiva de solicitudes desde una misma IP saturando al servidor por no tener capacidad de respuesta y empezará a rechazar peticiones. El filtro es el siguiente:

iptables -A INPUT -p tcp --syn --dport 25565 -m connlimit --connlimit-above 10 -j DROP

Con este ejemplo no se admitirán mas de 10 conexiones simultáneas por cliente al puerto indicado 25565 (usado por Minecraft).

Dónde buscar más info

Con lo explicado en este artículo ya sabemos movernos con iptables en la tabla filter pero queda muchísimo por saber. Si quieres profundizar te recomiendo estos enlaces:

http://redesdecomputadores.umh.es/iptables.htm
https://sio2sio2.github.io/doc-linux/08.redes/07.cortafuegos/01.iptables/02.conn.html