🌸

さくらクラウドのパケットフィルタでハマった話

に公開

さくらクラウドでサーバーを運用されている皆さん、ネットワーク設定で思わぬ落とし穴にハマった経験はありませんか?

今回は、さくらクラウドのパケットフィルタの設定で遭遇した、少し特殊なケースについてご紹介します。

特に、古いLinux環境をコンテナ環境へ移行した際に同じような問題に直面するかもしれません。

何が起きたのか?

さくらクラウド上に仮想マシン(VM)を構築し、その上でincus (旧LXD) を使って古いLinux環境をコンテナ化したものを動かしていました。

さくらクラウドのパケットフィルタを設定し、必要な通信は許可しているはずなのに、どうも挙動がおかしい。

ホストのVMへはSSHで問題なく接続できるのですが、コンテナへ直接SSHしようとすると、接続できたりできなかったりするという不安定な状態でした。

調査開始:tcpdumpが教えてくれたこと

この不可解な現象を解決するために、まずは定番のネットワークデバッグツールであるtcpdumpを使って通信状況を調査しました。ホストVM上とコンテナ内の両方でtcpdumpを実行し、SSH接続時のパケットの流れを詳細に追ってみたのです。

すると、ある奇妙な挙動が判明しました。SSHクライアントからコンテナへの接続要求はコンテナに届いており、コンテナからの応答も送信されていました。
しかし、その応答パケットがどうもコンテナからホストVMの外へ出て行っていないように見えるのです。SSHクライアント側では、タイムアウトして接続が切れていました。

原因判明:/proc/sys/net/ipv4/ip_local_port_range

パケットがコンテナから出て行かない原因を探るべく、さらに調査を進めました。ネットワーク関連の設定ファイルやカーネルパラメータを一つずつ確認していく中で、ついに問題の核心にたどり着きました。

それは、コンテナ内の/proc/sys/net/ipv4/ip_local_port_rangeというカーネルパラメータでした。この値を確認してみると、なんと**1024 65000**という設定になっていました。

`/proc/sys/net/ipv4/ip_local_port_range` とは?

TCP/IP通信において、クライアントが外部のサービスに接続する際に使用される「エフェメラルポート(一時的なポート)」の範囲を定義するカーネルパラメータです。通常、この範囲内のポートがランダムに選択され、接続元ポートとして使用されます。

さくらクラウドのパケットフィルタは、公式ドキュメントに記載がある通り、ステートレスな動作を基本としています。つまり、接続元のポートと接続先のポートの組を厳密にチェックするため、戻りパケットの送信元ポートが、初期接続時の宛先ポートと同じ、あるいは特定の範囲内である必要があるのです。

今回ハマった原因は、さくらクラウドのパケットフィルタが**「戻りパケット用のポート」として想定している範囲とip_local_port_rangeとが異なっていた**ため、戻りパケットがパケットフィルタでブロックされてしまっていたことでした。

さくらクラウドのパケットフィルタがステートレス動作であることは頭にあったものの、さくらクラウドが用意しているプリセットを使っていたこともあり、戻りパケットのポート範囲がまさかパケットフィルタで指定している範囲からはみ出ているとは、最初は考えもしませんでした。

今回、古いLinux環境では、デフォルトのip_local_port_rangeが現代のネットワーク環境やパケットフィルタの仕様と合致しない場合がある、という良い教訓になりました。

まとめ:さくらクラウドのパケットフィルタとステートレス動作

今回の件から学んだことは、さくらクラウドのパケットフィルタは、公式ドキュメントに記載がある通り、ステートレス動作であるという点です。今回のケースのようにつながったり、つながらなかったりするときには、戻りパケットのポート範囲の指定についても確認してみるとよさそうです。

蛇足

パフォーマンス上の問題とかもあるんだろうけど、標準附帯のパケットフィルタをステートフル動作で提供してくれるようになると、こういうのも考えなくていいんだけどな。

Discussion