web-dev-qa-db-fra.com

Pourquoi mes connexions réseau sont-elles rejetées?

J'ai un client Centos 8 qui court sur un hôte Fedora 31. L'invité est attaché à un réseau de pont, virbr0, et a l'adresse 192.168.122.217. Je peux me connecter à l'invité via SSH à cette adresse.

Si je démarre un service sur la liste des invités sur le port 80, toutes les connexions de l'hôte à l'invité manquent comme suit:

$ curl 192.168.122.217
curl: (7) Failed to connect to 192.168.122.217 port 80: No route to Host

Le service est tenu de 0.0.0.0:

guest# ss -tln
State    Recv-Q    Send-Q        Local Address:Port        Peer Address:Port

LISTEN   0         128                 0.0.0.0:22               0.0.0.0:*
LISTEN   0         5                   0.0.0.0:80               0.0.0.0:*
LISTEN   0         128                    [::]:22                  [::]:*

En utilisant tcpdump (soit sur virbr0 sur l'hôte, ou sur eth0 Sur l'invité), je vois que l'invité semble répondre avec un message ICMP "Admin Interdit".

19:09:25.698175 IP 192.168.122.1.33472 > 192.168.122.217.http: Flags [S], seq 959177236, win 64240, options [mss 1460,sackOK,TS val 3103862500 ecr 0,nop,wscale 7], length 0
19:09:25.698586 IP 192.168.122.217 > 192.168.122.1: ICMP Host 192.168.122.217 unreachable - admin prohibited filter, length 68

Il n'y a pas de règles de pare-feu sur la chaîne INPUT à l'invité:

guest# iptables -S INPUT
-P INPUT ACCEPT

La table de routage dans l'invité a l'air parfaitement normale:

guest# ip route
default via 192.168.122.1 dev eth0 proto dhcp metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.217 metric 100

SELINUX est en mode permissif:

guest# getenforce
Permissive

Si j'arrête sshd et démarrez mon service sur le port 22, tout fonctionne comme prévu.

Qu'est-ce qui cause ces connexions échoue?


Au cas où quelqu'un le demande, la sortie complète de iptables-save sur l'invité est:

*filter
:INPUT ACCEPT [327:69520]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [285:37235]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
*security
:INPUT ACCEPT [280:55468]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [285:37235]
COMMIT
*raw
:PREROUTING ACCEPT [348:73125]
:OUTPUT ACCEPT [285:37235]
COMMIT
*mangle
:PREROUTING ACCEPT [348:73125]
:INPUT ACCEPT [327:69520]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [285:37235]
:POSTROUTING ACCEPT [285:37235]
COMMIT
*nat
:PREROUTING ACCEPT [78:18257]
:INPUT ACCEPT [10:600]
:POSTROUTING ACCEPT [111:8182]
:OUTPUT ACCEPT [111:8182]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i docker0 -j RETURN
COMMIT
4
larsks

Eh bien, je l'ai compris. Et c'est un doozy.

Centos 8 utilise nftables , ce qui n'est en soi pas surprenant. Il est livré avec la version nft des commandes iptables, ce qui signifie que lorsque vous utilisez la commande iptables, il maintient réellement un ensemble de tables de compatibilité dans NFTABBLES.

Toutefois...

FirewallD - qui est installé par défaut - a Native prend en charge les NFTABLES, de sorte qu'il n'utilise pas la couche de compatibilité IPTABLES.

Donc pendant iptables -S INPUT vous montre:

# iptables -S INPUT
-P INPUT ACCEPT

Ce que vous en fait ont:

        chain filter_INPUT {
                type filter hook input priority 10; policy accept;
                ct state established,related accept
                iifname "lo" accept
                jump filter_INPUT_ZONES_SOURCE
                jump filter_INPUT_ZONES
                ct state invalid drop
                reject with icmpx type admin-prohibited  <-- HEY LOOK AT THAT!
        }

La solution ici (et honnêtement probablement bon conseil en général) est:

systemctl disable --now firewalld

Avec le pare-feu hors du passage, les règles IPTABLES visibles avec iptables -S se comportera comme prévu.

2
larsks

Si vous devez quitter le pare-feu, vous devez ajouter NFTABLES RESTION sur l'hôte Hypervisor.

Ajoutez d'abord Docker0 à la zone interne Si vous n'en utilisez pas un autre spécifique:

firewall-cmd --zone=internal --change-interface=docker0 --permanent
firewall-cmd --reload

Exécutez NFTABLES pour appliquer la règle pour accepter le trafic TCP sur 80 ports à l'interface VIRBR0 avec la destination 192.168.122.217:

/sbin/nft add rule inet firewalld filter_FWDI_internal_allow oifname "virbr0" ip daddr 192.168.122.217 tcp dport 80 counter accept comment "comment something"

En outre, il est nécessaire d'ajouter une règle d'Iptables:

/usr/sbin/iptables -t filter -I FORWARD -p tcp -o virbr0 -d 192.168.122.217 --dport 80 -j ACCEPT -m comment --comment "comment something"

Ces deux règles que vous pouvez envelopper avec un script shell et ajouter une unité de service SystemD avec délai défini sur 5 secondes, pour l'avoir exécuté automatiquement pendant la démarrage. Ou convertissez la règle IPTABLES en NFTABLES et sauvegardez-les à la fois à NFTABLES. Mais une fois que vous exécuterez une règle d'iptables convertie, les iptables seront verrouillés et toute nouvelle modification des IPTABLES ne sera possible qu'avec un pare-feu et NFTABLES.

J'AIME J'ai également personnalisé Kernel Tuntables que les paquets traversant le pont n'allèderont pas à IPTABLES.

sysctl net.bridge.bridge-nf-call-iptables=0
sysctl net.bridge.bridge-nf-call-arptables=0
sysctl net.bridge.bridge-nf-call-ip6tables=0

Remarque Si vous allez l'ajouter à SYSCTL.CONF, il peut ne pas être automatiquement appliqué lors du redémarrage comme un bogue connu en fonction de votre distribution Linux.

0
Alexred