UFW permite 22 para IPv4 e IPv6, mas o SSH desconecta ao ativar

10

sudo ufw disableseguido por sudo ufw enableme expulsa do SSH

Relatórios DMESG

[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

Posso efetuar login novamente sem precisar alterar as regras pelo console (o UFW ainda está ativado).

Isso começou após a atualização do Xenial (16.04) do kernel 4.4 para 4.15 (HWE). A atualização para 18.04.1 não resolveu o problema.

Versões:

  • iptables v1.6.1
  • ufw 0,35
  • 4.15.0-29-generic # 31-Ubuntu
  • Ubuntu 18.04.1 LTS

O status UFW é detalhado (algumas regras foram omitidas, mas todas são 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 que isso está acontecendo, ou pelo menos, como reverter para o comportamento esperado?

Eu olhei para esta resposta e não tenho certeza se ela se aplica, mas aqui está o /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

PS: Eu não esperava que isso "corrigisse" o problema, mas apenas para referência, mudei a porta em que o SSHD escuta (e a regra correspondente) e o problema persiste.

Gaia
fonte
Então, tudo funciona como deveria, exceto que você sai momentaneamente da sessão ssh quando desliga o firewall e liga novamente?
Bernard Wei
sim, momentaneamente como ele se desconecta e eu tenho que conectar novamente. ele não "apenas" tenda
Gaia
Isso é muito estranho, porque ativar / desativar via ufw só deve entrar em vigor após a reinicialização. Você pode verificar usando o status systemctl ufw para ver se ainda está em execução (ou não está em execução) quando esses comandos são emitidos.
Bernard Wei
2
Isso parece ser uma regressão do kernel e parece ter sido introduzido entre os kernels 4.13 e 4.14. Estou fazendo uma bissecção do kernel agora. Vai demorar um dia ou dois. Se algum leitor já conhece o culpado, por favor poste aqui para que eu não perca tempo.
Doug Smythies
11
Nenhum número de bug ainda, apenas terminei a bissecção do kernel. 4d3a57f23dec59f0a2362e63540b2d01b37afe0a netfilter: conntrack: não ative o rastreamento de conexão, a menos que seja necessário. Dê-me algumas horas e eu vou escrever uma resposta.
Doug Smythies

Respostas:

9

Antecedentes e limites do problema:

  • O problema ocorre apenas quando o UFW, ou iptables, com essas regras de permissão ssh, está ativado e uma sessão ssh é iniciada. ou seja, qualquer sessão SSH iniciada sem iptables funciona bem, mas pode estar sujeita a desistências aleatórias quando o conjunto de regras for implementado.
  • lembre-se de que o ufw é apenas um front end para o iptables.
  • O problema está presente mesmo no kernel 4.18-rc8.

O que está acontecendo?

Os sudo ufw allow in port 22resultados no seguinte segmento de regras do 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

Mediante sudo ufw disableseguido por sudo ufw enable, e mesmo que a própria conexão ssh permanece bem, as iptables resultantes governar conjunto parece ter esquecido a associação com essa conexão especial e, portanto, classifica quaisquer pacotes de entrada como inválida. De alguma forma, a tabela de rastreamento de conexão ficou confusa e o pacote nem sequer é considerado NOVO, mas com sinalizadores incorretos, nem é parte da conexão existente.

Considere um iptables muito básico equivalente ao que ufwestá fazendo. Dois scripts, um para limpar o conjunto de regras e outro para criá-lo:

#!/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.

E:

#!/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

O resultado desses pacotes conta após um ciclo de limpeza / carregamento com uma sessão ssh iniciada após um ciclo de carregamento:

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 os 35 pacotes inválidos enquanto eu digitava no terminal da sessão ssh danificado e antes do PuTTY terminar.

Por que isso parou de funcionar, costumava funcionar?

Como isso é 100% repetível, uma bissecção do kernel era relativamente fácil, apenas demorada. Os resultados foram:

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]>

Link para o commit inteiro.

Como reverter para o comportamento esperado?

Após desativar o ufw ou limpar o conjunto de regras do iptables, crie uma nova sessão SSH. Ele sobreviverá a uma ativação subseqüente do ufw, mas pode estar sujeito a um abandono aleatório em algum momento.

Esse problema será corrigido em algum momento, através da lista de email relacionada.

EDIT: thread de email upstream (contém uma solução alternativa). Solução alternativa copiada aqui:

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

EDIT 2: patch proposto a montante , que eu testei e relatei de volta.

EDIT 3: 2018.11.06: Isso parou a montante, e eu não tive tempo para importuná-los. Vou tentar voltar em breve.

EDIT 4: 2019.03.17: Não consigo reproduzir esse problema com segurança no kernel 5.0.

Doug Smythies
fonte
11
O problema persiste mesmo com o kernel 4.18-rc8. Existe um relacionamento entre se o problema ocorrerá ou não, com base na fila para qualquer sessão ssh estar vazia ou não. Não, essa mitigação não é a solução. Eu preciso de mais tempo.
Doug Smythies
11
OK obrigado. Eu tenho que fazer algumas alterações na resposta, mas não sei quando. Existem vários problemas aqui. Estou no meio de uma segunda bissecção do kernel, relacionada apenas ao iptables. Estou tentando eliminar o UFW do problema. As coisas estão um pouco confusas (na minha opinião), e a ferramenta conntrak está basicamente quebrada por causa do primeiro commit que encontrei. Subirei a montante assim que tiver detalhes suficientes para fazê-lo.
Doug Smythies
11
@ Gaia Se você não atribuir a recompensa completa, Doug receberá apenas 50% se houver dois votos positivos . Atualmente, há apenas um voto positivo, então estou adicionando outro em parte para garantir 50% de garantia de recompensa, mas principalmente porque é uma excelente resposta.
WinEunuuchs2Unix 12/08
11
@ Gaia: Só posso supor que seu problema esteja de alguma forma relacionado a outras regras da UFW. Enviei um email upstream (eles não têm um sistema de erros), mas eliminei completamente o UFW e me refiro apenas às tabelas de ip. Como não estou nessa lista de emails específica e ainda não a vejo no arquivo, presumo que ela esteja sendo mantida com moderação. Fornecerei um link assim que disponível.
Doug Smythies
11
@ Gaia: Eu não posso especular. Tudo o que sei é que, apenas com as regras ssh, o UFW ativado e a reinicialização da conexão ssh funcionam bem, pelo menos para mim. Ele é descartado após uma desativação / ativação subsequente do UFW.
Doug Smythies