web-dev-qa-db-ja.com

ネットワーク接続が拒否されるのはなぜですか?

CentOS 8ゲストをFedora 31ホストで実行しています。ゲストはブリッジネットワークvirbr0に接続され、アドレス192.168.122.217を持っています。そのアドレスでSSH経由でゲストにログインできます。

ポート80でリッスンしているゲストでサービスを開始すると、ホストからゲストへのすべての接続が次のように失敗します。

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

サービスは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                  [::]:*

tcpdump(ホストのvirbr0またはゲストのeth0のいずれか)を使用すると、ゲストがICMPの「管理者禁止」メッセージで応答しているようです。

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

ゲストのINPUTチェーンにはファイアウォールルールがありません:

guest# iptables -S INPUT
-P INPUT ACCEPT

ゲストのルーティングテーブルは完全に正常に見えます。

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はパーミッシブモードです。

guest# getenforce
Permissive

sshdを停止してポート22でサービスを開始すると、すべて期待どおりに機能します。

これらの接続が失敗する原因は何ですか?


誰かが要求した場合、ゲストのiptables-saveの完全な出力は次のとおりです。

*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
3
larsks

さて、私はそれを理解しました。そしてそれはおかしな話だ。

CentOS 8は nftables を使用しますが、それ自体は驚くべきことではありません。 nftコマンドのiptablesバージョンが同梱されています。つまり、iptablesコマンドを使用すると、nftablesに一連の互換性テーブルが実際に保持されます。

しかしながら...

Firewalld-デフォルトでインストールされます-はnftablesをnativeサポートしているため、iptables互換性レイヤーを利用しません。

したがって、iptables -S INPUTはあなたを示しています:

# iptables -S INPUT
-P INPUT ACCEPT

あなたが実際に持っているものは:

        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!
        }

ここでの解決策(そして正直言っておそらく一般的には良いアドバイスです)は次のとおりです:

systemctl disable --now firewalld

Firewalldを使用すると、iptablesルールはiptables -Sは期待どおりに動作します。

2
larsks

Firewalldをオンのままにする場合は、ハイパーバイザーホストにnftablesルールを追加する必要があります。

/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"

また、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"

これらの両方を1つのファイアウォールルールでカバーできるかどうかはわかりません。

0
Alexred