UFW permite 22 para IPv4 e IPv6 pero SSH se desconecta al habilitar

10

sudo ufw disableseguido por sudo ufw enableme echa de SSH

DMESG informa

[UFW BLOCK] IN=eth0 OUT= MAC=30:........ SRC=192.168.1.me DST=192.168.1.server LEN=52 TOS=0x00 PREC=0x00 TTL=128 ID=15776 DF PROTO=TCP SPT=55640 DPT=22 WINDOW=253 RES=0x00 ACK URGP=0

Puedo volver a iniciar sesión sin tener que cambiar las reglas a través de la consola (UFW todavía está habilitado).

Esto comenzó después de actualizar Xenial (16.04) del kernel 4.4 a 4.15 (HWE). La actualización a 18.04.1 no resolvió el problema.

Versiones

  • iptables v1.6.1
  • ufw 0.35
  • 4.15.0-29-genérico # 31-Ubuntu
  • Ubuntu 18.04.1 LTS

El estado de UFW es detallado (se omitieron algunas reglas, pero todas están PERMITIDAS)

Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22                         ALLOW IN    Anywhere
22 (v6)                    ALLOW IN    Anywhere (v6)

¿Por qué sucede esto, o al menos, cómo volver al comportamiento esperado?

Miré esta respuesta , y no estoy seguro de que se aplique, pero aquí está /etc/ufw/before.rules

#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#

# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines


# allow all on loopback
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-output -o lo -j ACCEPT

# quickly process packets for which we already have a connection
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP

# ok icmp codes for INPUT
-A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-input -p icmp --icmp-type source-quench -j ACCEPT
-A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT

# ok icmp code for FORWARD
-A ufw-before-forward -p icmp --icmp-type destination-unreachable -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type source-quench -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type time-exceeded -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type parameter-problem -j ACCEPT
-A ufw-before-forward -p icmp --icmp-type echo-request -j ACCEPT

# allow dhcp client to work
-A ufw-before-input -p udp --sport 67 --dport 68 -j ACCEPT

#
# ufw-not-local
#
-A ufw-before-input -j ufw-not-local

# if LOCAL, RETURN
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN

# if MULTICAST, RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN

# if BROADCAST, RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN

# all other non-local packets are dropped
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP

# allow MULTICAST mDNS for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 224.0.0.251 --dport 5353 -j ACCEPT

# allow MULTICAST UPnP for service discovery (be sure the MULTICAST line above
# is uncommented)
-A ufw-before-input -p udp -d 239.255.255.250 --dport 1900 -j ACCEPT

# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT

PD: No esperaba que esto "solucionara" el problema, pero solo como referencia, cambié el puerto en el que escucha SSHD (y la regla correspondiente) y el problema persiste.

Gaia
fuente
Entonces, ¿todo funciona como debería, excepto que se cae momentáneamente de la sesión ssh cuando apaga el firewall y luego lo vuelve a encender?
Bernard Wei
Sí, momentáneamente, ya que se desconecta y tengo que volver a conectarme. no "solo" se atasca
Gaia
Esto es muy extraño porque habilitar / deshabilitar a través de ufw solo debería entrar en vigencia después de reiniciar. Puede verificar el uso de systemctl status ufw para ver si aún se está ejecutando (o no se está ejecutando) cuando se emiten esos comandos.
Bernard Wei
2
Esto parece ser una regresión del núcleo y parece haberse introducido entre los núcleos 4.13 y 4.14. Estoy haciendo una bisección del núcleo ahora. Tomará uno o dos días. Si algún lector ya conoce el compromiso del culpable, publique aquí para que no pierda el tiempo.
Doug Smythies
1
Aún no hay un número de error, solo acabo de terminar la bisección del kernel. 4d3a57f23dec59f0a2362e63540b2d01b37afe0a netfilter: conntrack: no habilite el seguimiento de la conexión a menos que sea necesario. Dame unas horas y escribiré una respuesta.
Doug Smythies

Respuestas:

9

Antecedentes y límites del problema:

  • El problema solo ocurre cuando UFW, o iptables, con estas reglas de permiso ssh, está habilitado y se inicia una sesión ssh. es decir, cualquier sesión SSH que se inició sin iptables funciona bien, pero puede estar sujeta a abandonos aleatorios una vez que se establece el conjunto de reglas.
  • recuerde que ufw es simplemente una interfaz para iptables.
  • El problema está presente incluso con el kernel 4.18-rc8.

Que esta pasando?

Los sudo ufw allow in port 22resultados en el siguiente segmento de reglas de iptables:

Chain ufw-before-input (1 references)
    pkts      bytes target     prot opt in     out     source               destination
      16     1553 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
     386   300622 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
      15     1068 ufw-logging-deny  all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
      15     1068 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID

Una vez sudo ufw disableseguido sudo ufw enable, y aunque la conexión ssh en sí misma permanece bien, el conjunto de reglas iptables resultante parece haber olvidado la asociación con esa conexión en particular y, por lo tanto, clasifica los paquetes entrantes como no válidos. De alguna manera, la tabla de seguimiento de la conexión se ha confundido y el paquete ni siquiera se considera NUEVO, sino con indicadores incorrectos, ni se considera parte de la conexión existente.

Considere un equivalente de iptables muy básico de lo que ufwestá haciendo. Dos scripts, uno para borrar el conjunto de reglas y otro para crearlo:

#!/bin/sh
FWVER=0.01
#
# clear_firewall_min 2018.08.10 Ver:0.01
#       clear iptables minimum.
#       Currently for this question:
#       /ubuntu/1059781/ufw-allows-22-for-ipv4-and-ipv6-but-ssh-disconnects-when-enabling
#
echo "Loading clear_firewall_min version $FWVER..\n"

# The location of the iptables program
#
IPTABLES=/sbin/iptables

#Set some stuff
#
EXTIF="ens5"
UNIVERSE="0.0.0.0/0"

#Clearing any previous configuration
#
echo "  Clearing any existing rules and setting default policies.."
$IPTABLES -P INPUT ACCEPT
$IPTABLES -F INPUT

# Reset all IPTABLES counters
$IPTABLES -Z

#sleep 10

echo clear_firewall_min $FWVER done.

Y:

#!/bin/sh
#
# test_firewall 2018.08.13 Ver:0.01
#       Minimum version of most basic iptables firewall.
#
# test_firewall 2018.08.09 Ver:0.01
#       Most basic iptables firewall.
#       Currently for this question:
#       /ubuntu/1059781/ufw-allows-22-for-ipv4-and-ipv6-but-ssh-disconnects-when-enabling
#

#sleep 50

# The location of the iptables program
#
IPTABLES=/sbin/iptables

#Set some stuff
#
EXTIF="ens5"
UNIVERSE="0.0.0.0/0"

#Clearing any previous configuration
#
#echo "  Clearing any existing rules and setting default policies.."
$IPTABLES -P INPUT DROP
$IPTABLES -F INPUT

# loopback interfaces are valid.
#
$IPTABLES -A INPUT -i lo -s $UNIVERSE -d $UNIVERSE -j ACCEPT

$IPTABLES -A INPUT -i $EXTIF -p tcp -m conntrack --ctstate INVALID -j LOG --log-prefix "IINVALID:" --log-level info
$IPTABLES -A INPUT -i $EXTIF -p tcp -m conntrack --ctstate INVALID -j DROP
$IPTABLES -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j LOG --log-prefix "NEW TCP no SYN:" --log-level info
$IPTABLES -A INPUT -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
$IPTABLES -A INPUT -i $EXTIF -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $EXTIF -p tcp -m conntrack --ctstate NEW --dport 22 -j ACCEPT

echo "test_firewall_min $FWVER done..." >> /dev/kmsg

sleep 3

Como resultado, estos paquetes cuentan después de un ciclo de limpieza / carga con una sesión ssh que se inició después de un ciclo de carga:

doug@s17:~$ sudo iptables -v -x -n -L
Chain INPUT (policy DROP 3 packets, 220 bytes)
    pkts      bytes target     prot opt in     out     source               destination
       0        0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
      35     6388 LOG        tcp  --  ens5   *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID LOG flags 0 level 6 prefix "IINVALID:"
      35     6388 DROP       tcp  --  ens5   *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
       0        0 LOG        tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:!0x17/0x02 ctstate NEW LOG flags 0 level 6 prefix "NEW TCP no SYN:"
       0        0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp flags:!0x17/0x02 ctstate NEW
       9      680 ACCEPT     all  --  ens5   *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
       0        0 ACCEPT     tcp  --  ens5   *       0.0.0.0/0            0.0.0.0/0            ctstate NEW tcp dpt:22

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 12 packets, 1408 bytes)
    pkts      bytes target     prot opt in     out     source               destination

Observe los 35 paquetes no válidos mientras escribía en el terminal de sesión ssh paralizado, y antes de que PuTTY terminara.

¿Por qué esto dejó de funcionar, solía funcionar?

Debido a que esto es 100% repetible, una bisección del núcleo fue relativamente fácil, solo tomó mucho tiempo. Los resultados fueron:

4d3a57f23dec59f0a2362e63540b2d01b37afe0a is the first bad commit
commit 4d3a57f23dec59f0a2362e63540b2d01b37afe0a
Author: Florian Westphal <[email protected]>
Date:   Fri Jul 28 11:22:04 2017 +0200

    netfilter: conntrack: do not enable connection tracking unless needed

    Discussion during NFWS 2017 in Faro has shown that the current
    conntrack behaviour is unreasonable.

    Even if conntrack module is loaded on behalf of a single net namespace,
    its turned on for all namespaces, which is expensive.  Commit
    481fa373476 ("netfilter: conntrack: add nf_conntrack_default_on sysctl")
    attempted to provide an alternative to the 'default on' behaviour by
    adding a sysctl to change it.

    However, as Eric points out, the sysctl only becomes available
    once the module is loaded, and then its too late.

    So we either have to move the sysctl to the core, or, alternatively,
    change conntrack to become active only once the rule set requires this.

    This does the latter, conntrack is only enabled when a rule needs it.

    Reported-by: Eric Dumazet <[email protected]>
    Signed-off-by: Florian Westphal <[email protected]>
    Signed-off-by: Pablo Neira Ayuso <[email protected]>

Enlace a todo el commit.

¿Cómo volver al comportamiento esperado?

Después de deshabilitar ufw o borrar el conjunto de reglas de iptables, cree una nueva sesión SSH. Sobrevivirá una habilitación posterior de ufw, pero podría estar sujeto a un abandono aleatorio en algún momento.

Este problema se abordará en algún momento, a través de la lista de correo electrónico relacionada.

EDITAR: hilo de correo electrónico ascendente (contiene una solución alternativa). Solución alternativa copiada aquí:

echo 1 | sudo tee /proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal

EDIT 2: parche propuesto aguas arriba , que he probado e informado.

EDIT 3: 2018.11.06: Esto se ha estancado río arriba, y no he tenido tiempo de molestarlos. Intentaré volver pronto.

EDIT 4: 2019.03.17: No puedo reproducir de manera confiable este problema con el kernel 5.0.

Doug Smythies
fuente
1
El problema persiste incluso con el kernel 4.18-rc8. Existe una relación entre si el problema ocurrirá o no en función de si la cola de cualquier sesión ssh está vacía o no. No, esa mitigación no es la solución. Necesito más tiempo.
Doug Smythies
1
OK gracias. Tengo que hacer algunos cambios en la respuesta, pero no sé cuándo. Hay múltiples problemas aquí. Estoy en medio de una segunda bisección del kernel, relacionada solo con iptables. Estoy tratando de eliminar UFW del problema. Las cosas están un poco desordenadas (mi opinión), y la herramienta conntrak está básicamente rota debido a la primera confirmación que encontré. Subiré una vez que tenga suficientes detalles para hacerlo.
Doug Smythies
1
@Gaia Si no se asigna la recompensa completa, entonces Doug no harán más que 50% de los que SI hay dos arriba-votos. Actualmente solo hay un voto positivo, así que agrego otro en parte para una garantía de recompensa del 50%, pero principalmente porque es una excelente respuesta.
WinEunuuchs2Unix
1
@Gaia: Solo puedo suponer que tu problema está relacionado de alguna manera con alguna de tus reglas de UFW. He enviado un correo electrónico ascendente (no tienen un sistema de error), pero eliminé UFW por completo, y solo me refiero a iptables. Como no estoy en esa lista de correo electrónico en particular, y todavía no la veo en el archivo, supongo que se mantiene con moderación. Proporcionaré un enlace una vez que esté disponible.
Doug Smythies
1
@Gaia: no puedo especular. Todo lo que sé es que, con solo las reglas ssh, UFW habilitado y luego reiniciar la conexión ssh funciona bien, al menos para mí. Se deja caer en un UFW posterior deshabilitar / habilitar.
Doug Smythies