![iptables を使用して Kubernetes クラスターにトラフィックをルーティングする](https://rvso.com/image/782618/iptables%20%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%20Kubernetes%20%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%BC%E3%81%AB%E3%83%88%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%92%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%99%E3%82%8B.png)
ルート サーバー (netcup) で Kubernetes クラスター (現在は 1 ノードのみ) が実行されており、トラフィックをルーティングしようとしています。私はネットワークにあまり詳しくないので、誰かが助けてくれることを願っています。
クラスター上メタルがインストールされ、CNI として calico が使用されています。Metallb は、K8s-LoadBalancers への IP アドレスの割り当てとアナウンスを担当しており、内部的には正常に動作します。そのため、サーバー内から負荷分散されたサービスにアクセスできます。固定内部 IP (リバース プロキシ) を持つ単一のサービスのみを公開します。
ここで、metallbからIPアドレスに直接トラフィックをルーティングして外部に公開したいと思います。iptables
iptables では次のルールが適用されました。
iptables -A PREROUTING -t nat -p tcp -m tcp -j DNAT --to-destination <metallb-ip> -i eth0 --destination-port 80 -m comment --comment Redirect web traffic to cluster (80)
iptables -A PREROUTING -t nat -p tcp -m tcp -j DNAT --to-destination <metallb-ip> -i eth0 --destination-port 443 -m comment --comment Redirect web traffic to cluster (443)
iptables -A POSTROUTING -t nat -p tcp -m tcp -j SNAT --to-source <public-server-ip> -o eth0 --destination-port 80 -m comment --comment Redirect web traffic from cluster (80)
iptables -A POSTROUTING -t nat -p tcp -m tcp -j SNAT --to-source <public-server-ip> -o eth0 --destination-port 443 -m comment --comment Redirect web traffic from cluster (443)
(コマンドは私の Ansible スクリプトから抽出したため、100% 正確ではない可能性があります。Ansible の部分は下部にあります)
私の理解する限り、これはすべての着信 TCP トラフィックを DNAT を使用して内部 IP に送信し、すべての発信トラフィックは SNAT を使用してパブリック サーバー アドレスを持つことになります。つまり、接続クライアントにとっては、パブリック IP/ポートと直接通信しているように見えるのでしょうか?
残念ながら、インターネットからサービスにアクセスしようとすると、次の結果になります。
$> curl <public-server-ip>
curl: (7) Failed to connect to <public-server-ip> port 80 after 647 ms: Network is down
サーバーからのアクセスは機能します:
$> curl <metallb-ip>
404 page not found # which the expected answer since its a blank Traefik reverse proxy
現在、nmap ポート スキャンでは次の結果がスローされます。
$> nmap -Pn -p 80,443 <public-server-ip>
Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-15 15:57 CET
Strange SO_ERROR from connection to <public-server-ip> (50 - 'Network is down') -- bailing scan
QUITTING!
しかし、SSH 経由で接続しているので、稼働しています。
現在ufw
有効になっていません。
前にも言ったように、私はネットワーキングがあまり得意ではないので、どんな助けでもありがたいです。 ;)
Ansible スクリプト:
- name: DNAT port 80 to cluster
iptables:
table: nat
chain: PREROUTING
in_interface: eth0
protocol: tcp
match: tcp
jump: DNAT # REDIRECT
to_destination: <metallb-ip>
destination_port: 80
comment: Redirect web traffic to cluster (80)
become: yes
- name: DNAT port 443 to cluster
iptables:
table: nat
chain: PREROUTING
in_interface: eth0
protocol: tcp
match: tcp
destination_port: 443
jump: DNAT # REDIRECT
to_destination: <metallb-ip>
comment: Redirect web traffic to cluster (443)
become: yes
- name: SNAT port 80 from cluster
iptables:
table: nat
chain: POSTROUTING
out_interface: eth0
protocol: tcp
match: tcp
destination_port: 80
jump: SNAT # REDIRECT
to_source: <public-server-ip>
comment: Redirect web traffic from cluster (443)
become: yes
- name: SNAT port 443 from cluster
iptables:
table: nat
chain: POSTROUTING
out_interface: eth0
protocol: tcp
match: tcp
destination_port: 443
jump: SNAT # REDIRECT
to_source: <public-server-ip>
comment: Redirect web traffic from cluster (443)
become: yes
- name: Configure IP Masquerading
iptables:
table: nat
chain: POSTROUTING
out_interface: eth0
jump: MASQUERADE
アップデート: の助けを借りてこれこの記事で、流れを理解しようとしました。問題がどこにあるかを調べるために、ログ ステートメントを追加しました。これまでにわかったことは次のとおりです。
パケットが失われる場所を確認するために、次のルールを追加しました。
iptables -t raw -A PREROUTING -p tcp --dport 80 -j LOG --log-prefix "[raw:PREROUTING]: "
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j LOG --log-prefix "[mangle:PREROUTING]: "
iptables -t nat -A PREROUTING -p tcp --dport 80 -j LOG --log-prefix "[nat:PREROUTING]: "
iptables -t mangle -A POSTROUTING -p tcp --sport 80 -j LOG --log-prefix "[mangle:PREROUTING]: "
iptables -t nat -A POSTROUTING -p tcp --sport 80 -j LOG --log-prefix "[nat:PREROUTING]: "
/var/log/kern.log
およびログ ステートメントのみがraw
表示mangle
されます。したがって、nat
-step はトリガーされていないようです。次のコマンドでマングル ルールを確認しました
sudo iptables -t mangle -L
が、ここでは問題は特定できませんでした。
IP 転送が有効になっています:
$> sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
では、なぜパケットはnat
-step に到達しないのでしょうか?
$> sudo iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
cali-PREROUTING all -- anywhere anywhere /* cali:6gwbT8clXdHdC1b1 */
LOG tcp -- anywhere anywhere tcp dpt:http LOG level warning prefix "[mangle:PREROUTING]: "
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
cali-POSTROUTING all -- anywhere anywhere /* cali:O3lYWMrLQYEMJtB5 */
Chain KUBE-IPTABLES-HINT (0 references)
target prot opt source destination
Chain KUBE-KUBELET-CANARY (0 references)
target prot opt source destination
Chain KUBE-PROXY-CANARY (0 references)
target prot opt source destination
Chain cali-from-host-endpoint (1 references)
target prot opt source destination
Chain cali-to-host-endpoint (1 references)
target prot opt source destination
Chain cali-PREROUTING (1 references)
target prot opt source destination
ACCEPT all -- anywhere anywhere /* cali:6BJqBjBC7crtA-7- */ ctstate RELATED,ESTABLISHED
ACCEPT all -- anywhere anywhere /* cali:KX7AGNd6rMcDUai6 */ mark match 0x10000/0x10000
cali-from-host-endpoint all -- anywhere anywhere /* cali:wNH7KsA3ILKJBsY9 */
ACCEPT all -- anywhere anywhere /* cali:Cg96MgVuoPm7UMRo */ /* Host endpoint policy accepted packet. */ mark match 0x10000/0x10000
Chain cali-POSTROUTING (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere /* cali:NX-7roTexQ3fGRfU */ mark match 0x10000/0x10000
MARK all -- anywhere anywhere /* cali:nnqPh8lh2VOogSzX */ MARK and 0xfff0ffff
cali-to-host-endpoint all -- anywhere anywhere /* cali:nquN8Jw8Tz72pcBW */ ctstate DNAT
RETURN all -- anywhere anywhere /* cali:jWrgvDQ0xEZHmta3 */ /* Host endpoint policy accepted packet. */ mark match 0x10000/0x10000