Fedora 31ホストでCentOS 8ゲストを実行しています。ゲストはブリッジされたネットワークに接続されており、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 "Admin Forbidden"メッセージで応答するように見えます。
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
ゲストのルーティングテーブルは完全にOKです。
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
答え1
わかりました。本当にすごいです。
CentOS 8は以下を使用します。nftables、それ自体は驚くべきことではありません。これは、コマンドを使用するときに実際にnftablesに互換性のあるテーブルセットを保持することを意味するコマンドnft
バージョンに付属しています。iptables
iptables
しかし...
デフォルトでインストールされているファイアウォールは、国のnftablesをサポートしているので、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
ファイアウォールをオフにすると、表示されるiptablesルールが期待どおりにiptables -S
実行されます。
答え2
Firewalldを無効にしたくない場合、回避策はハイパーバイザーホストに以下のnftablesルールを追加することです。
まだ別の特定の領域を使用していない場合は、まず内部領域にdocker0を追加してください。
firewall-cmd --zone=internal --change-interface=docker0 --permanent firewall-cmd --reload
nftablesを実行して、ターゲットが192.168.122.217のポート80からvirbr0インターフェイスへのTCPトラフィックを許可するルールを適用します。
/sbin/nft ルールを追加 inet Firewalld filter_FWDI_internal_allow oifname "virbr0" ip baddr 192.168.122.217 tcp dport 80 counter コメントを承諾する
また、iptablesルールを追加する必要があります(または一貫性のためにこれをnftablesに変換します。以下を参照)。
/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"
シェルスクリプトを使用してこれら2つのルールをラップし、systemdサービスユニットを追加し、遅延を5秒に設定できます。起動時に自動的に起動します。
また、iptablesルールをnftablesに変換し、両方ともnftablesルールセットに保存することができます。ただし、変換されたiptablesルールを実行するとiptablesがロックされ、iptablesへの新しい変更はFirewalldとnftablesを介してのみ実行できます。
また、ブリッジを通過するパケットがiptablesを通過しないように、カスタムカーネル調整可能エントリが必要です。Net.bridge.bridge-nf-call および sysctl.conf
sysctl net.bridge.bridge-nf-call-iptables=0
sysctl net.bridge.bridge-nf-call-arptables=0
sysctl net.bridge.bridge-nf-call-ip6tables=0
これをsysctl.confに追加すると既知のバグであるため(Linuxディストリビューションによっては)再起動中に自動的に適用されない可能性があります。