UFW umożliwia 22 dla IPv4 i IPv6, ale SSH rozłącza się po włączeniu

10

sudo ufw disablea następnie sudo ufw enablewykopuje mnie z SSH

Raporty 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

Mogę zalogować się ponownie bez konieczności zmiany reguł za pośrednictwem konsoli (nadal włączony UFW).

Zaczęło się to po aktualizacji Xenial (16.04) z jądra 4.4 do 4.15 (HWE). Aktualizacja do 18.04.1 nie rozwiązała problemu.

Wersje:

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

Pełen status UFW to (niektóre reguły zostały pominięte, ale wszystkie ZEZWALAJĄ)

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)

Dlaczego tak się dzieje, a przynajmniej jak wrócić do oczekiwanego zachowania?

Spojrzałem na tę odpowiedź i nie jestem pewien, czy ma ona zastosowanie, ale oto /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: Nie spodziewałem się, że to „naprawi” problem, ale dla odniesienia zmieniłem port nasłuchiwania SSHD na (i odpowiednią regułę) i problem nadal występuje.

Gaia
źródło
Więc wszystko działa tak, jak powinno, z wyjątkiem chwilowej rezygnacji z sesji ssh po wyłączeniu i ponownym włączeniu zapory?
Bernard Wei
tak, chwilowo jak to się rozłącza i muszę się połączyć ponownie. to nie „tylko” przeciągnięcie
Gaia,
Jest to bardzo dziwne, ponieważ włączanie / wyłączanie przez ufw powinno wejść w życie dopiero po ponownym uruchomieniu. Możesz sprawdzić za pomocą systemctl status ufw, aby sprawdzić, czy nadal działa (lub nie działa) po wydaniu tych poleceń.
Bernard Wei
2
Wydaje się, że jest to regresja jądra i wydaje się, że została wprowadzona między jądrami 4.13 i 4.14. Teraz robię bisekcję jądra. To zajmie dzień lub dwa. Jeśli któryś czytelnik już zna winowajcę, proszę opublikować tutaj, aby nie marnować czasu.
Doug Smythies,
1
Nie ma jeszcze numeru błędu, właśnie skończyłem bisekcję jądra. 4d3a57f23dec59f0a2362e63540b2d01b37afe0a netfilter: conntrack: nie włączaj śledzenia połączeń, jeśli nie jest to konieczne. Daj mi kilka godzin, a napiszę odpowiedź.
Doug Smythies,

Odpowiedzi:

9

Tło i granice problemu:

  • Problem występuje tylko wtedy, gdy UFW lub iptables, z tymi regułami zezwalającymi na ssh, jest włączony i rozpoczyna się sesja ssh. tzn. każda sesja SSH, która została rozpoczęta bez żadnych iptables, działa dobrze, ale może zostać poddana przypadkowym rezygnacjom po wprowadzeniu zestawu reguł.
  • Przypomnijmy, że ufw jest tylko interfejsem dla iptables.
  • Problem występuje nawet w jądrze 4.18-rc8.

Co się dzieje?

Te sudo ufw allow in port 22wyniki w następujących reguł iptables segmentu:

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

Po sudo ufw disablenastępnie sudo ufw enable, i choć sama połączenie ssh pozostaje w porządku, wynikające iptables wyklucza zestaw wydaje się zapominać skojarzenia z danym połączeniu i dlatego klasyfikuje przychodzące pakiety są nieważne. W jakiś sposób tabela śledzenia połączeń została pomylona, ​​a pakiet nie jest nawet uważany za NOWY, ale ma niepoprawne flagi, ani nie jest uważany za część istniejącego połączenia.

Rozważ bardzo podstawowy odpowiednik iptables tego, co ufwsię dzieje. Dwa skrypty, jeden do czyszczenia zestawu reguł i jeden do jego tworzenia:

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

I:

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

Wynikające z tych pakietów liczy się po cyklu czyszczenia / ładowania z sesją ssh, która została uruchomiona po cyklu ładowania:

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

Zwróć uwagę na 35 niepoprawnych pakietów podczas pisania na okaleczonym terminalu sesji ssh i przed zakończeniem PuTTY.

Dlaczego to przestało działać, kiedyś działało?

Ponieważ jest to w 100% powtarzalne, podział jądra był stosunkowo łatwy, czasochłonny. Wyniki były następujące:

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 do całego zatwierdzenia.

Jak przywrócić oczekiwane zachowanie?

Po wyłączeniu ufw lub wyczyszczeniu zestawu reguł iptables utwórz nową sesję SSH. Przetrwa kolejne włączenie ufw, ale w pewnym momencie może ulec przypadkowemu wypadnięciu.

Ten problem zostanie w pewnym momencie rozpatrzony wcześniej, za pośrednictwem powiązanej listy e-mail.

EDYCJA: poprzedni wątek e-mail (zawiera obejście). Obejście zostało skopiowane tutaj:

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

EDYCJA 2: proponowana łatka , którą przetestowałem i przekazałem z powrotem.

EDYCJA 3: 2018.11.06: To utknęło w martwym punkcie, a ja nie miałem czasu, aby ich męczyć. Spróbuję wkrótce do tego wrócić.

EDYCJA 4: 2019.03.17: Nie mogę w wiarygodny sposób odtworzyć tego problemu z jądrem 5.0.

Doug Smythies
źródło
1
Problem utrzymuje się nawet w przypadku jądra 4.18-rc8. Istnieje związek między tym, czy problem wystąpi, czy nie, w zależności od tego, czy kolejka do dowolnej sesji ssh jest pusta, czy nie. Nie, to złagodzenie nie jest rozwiązaniem. Potrzebuję więcej czasu.
Doug Smythies,
1
Ok dzięki. Muszę wprowadzić zmiany w odpowiedzi, ale nie wiem kiedy. Tutaj jest wiele problemów. Jestem w połowie drogi przez drugą wersję jądra, związaną tylko z iptables. Próbuję wyeliminować UFW z tego problemu. Wszystko jest trochę bałaganu (moja opinia), a narzędzie conntrak jest w zasadzie zepsute z powodu pierwszego zatwierdzenia, które znalazłem. Pójdę w górę rzeki, gdy będę miał wystarczająco dużo szczegółów, aby to zrobić.
Doug Smythies,
1
@ Gaia Jeśli nie przydzielisz pełnej nagrody, Doug dostanie tylko 50% JEŻELI są dwa głosy w górę. Obecnie jest tylko jeden głos w górę, więc dodam kolejny, aby uzyskać 50% nagrodę za nagrodę, ale głównie dlatego, że jest to doskonała odpowiedź.
WinEunuuchs2Unix,
1
@ Gaia: Mogę tylko założyć, że Twój problem jest w jakiś sposób związany z innymi zasadami Twojej UFW. Wysłałem wcześniejszą wiadomość e-mail (nie mają systemu błędów), ale całkowicie wyeliminowałem UFW i odnoszę się tylko do iptables. Ponieważ nie jestem na tej konkretnej liście e-mail i nie widzę jej jeszcze w archiwum, zakładam, że jest przechowywana do moderacji. Podam link, gdy będzie dostępny.
Doug Smythies
1
@Gaia: Nie mogę spekulować. Wiem tylko, że tylko z regułami ssh włączono UFW, a następnie ponowne połączenie ssh działa poprawnie, przynajmniej dla mnie. Zostaje upuszczony po kolejnym wyłączeniu / włączeniu UFW.
Doug Smythies