ということで、久しぶりのブログはネットワークの話題でございます。久しぶりの更新のため浅い内容ですが、これをトリガーにブログ習慣が戻ってくることを祈ってキーボードをタイプしております。
通信できない「ファイアウォールを開けるポートを教えてください」
仕事中、同僚PGさんからこんなお声がかかりました。
同僚さんは「PostgreSQLと通信するプログラム」を作り、WEBサーバにアップロードしたそうです。ところが通信ができない。聞くところ、通信先の
PostgreSQLサーバは社内LANにあり、プログラムをアップロードした
WEBサーバはDMZ領域にある。要するにサーバ間に存在する
FW機器にパケットを破棄され、通信ができないのだとか。

↑図1:概要
となるとFW機器のポートが必要ですが、ここの現場ではFW機器にポートを解放させる際に「IPアドレス/ポート解放依頼」という申請情報を作成し、インフラチームに提出する必要がありました。同僚さんはNWが苦手のようで、どのように書けばよいか分からないとのこと。
同僚さんは私が元ネットワークエンジニアということを知ってくれていたので、この件を相談してくれたのでしょう。
「それなら任せなさい!!」と言わんばかりに私は説明させていただきました。

↑図2:開発規模が大きいと役割がキッチリ分かれている
ところがその申請書が受理されたあと、いざ通信を試みてみると……繋がりませんでした。
なぜ繋がらないのか、この原因を調査する必要がありました。NWエンジニア時代の感覚を思い返しながら、PGとしてこの問題に挑むことになりました。
原因の切り分け通信ができない場合、トラブルの原因を切り分けなければなりません。
疑うべきは以下の4点でした。
1.サーバOS自体のFW設定
2.PostgreSQLの設定
3.FW機器の設定
4.プログラムのバグ
以下、ネットワーク環境。
・WEBサーバ:Windows Server 2012R2 (10.1.1.1)
・DBサーバ:Ubuntu16.04 PostgreSQL9.4 (20.1.1.1)
・FW機器:CentOS6.4 (eth0: 20.1.1.254 / eth1:10.1.1.254)

↑図3:あくまでサンプル環境
※本記事に乗せたIPアドレスは仮のもので、
同条件の環境を構築すると通信できます。今回の記事は技術の解説ではなく、あくまで
「考え方・心もち」が本旨でございます。
では、まずはじめに
「1.サーバOS自体のFW設定」を疑いました。通信ができない場合、サーバのFW機能を疑う必要があります。なぜならサーバ自体にも対象の通信ポートを許可設定しなければ、パケットは通信できずに破棄されてしまうからです。
しかし両サーバともに
ファイアウォールは全開放。どうやらこの現場はサーバ自体のセキュリティを全開放し、ゲートウェイでセキュリティを完全制御しているようです。また、それ以外の原因となりうるセキュリティ制御プログラムもOFFにしていたため、サーバOS自体のFW問題は見受けられませんでした。
次に
「2.PostgreSQLの設定」ですが、こちらも確認したところ特に問題なし。同一セグメントから
pgAdmin3を使った通信に成功したためです。相変わらずDMZ領域だけが通信ができないことを考えると、PostgreSQL自体は問題なさそう。

↑図4:pgAdminの通信はOK
「もしかすると自分が作ったプログラムにバグがあるんですかね…」と、同僚さんがつぶやきました。
その可能性も考えましたが、それもまた疑わしい状況でした。プログラムに問題があるかどうかは、
実際にDBサーバと通信しなければ分からないためです。なんにせよ、もう少し原因を切り分けなければなりません。
次に疑ったのは
「3.FW機器の設定」です。ちなみにWEB→DBのPingは通りません。理由はFW機器がDMZ→LANへのICMP通信を許可していないためです。「Pingが打てないんじゃNWとプログラムの原因切り分けは難しいですよね…」と同僚さんは困惑の表情を浮かべました。
tcpdump(まてよ?たしかDBサーバはLinuxだったよな?)
とインフラのプロを目指していた私は
「tcpdump」の存在を思い出しました。
tcpdumpはLinuxに搭載している
パケット解析ツールです。Windowsでパケット解析をする場合、Wiresharkなどのツールをインストールする必要があります。けれどもLinuxにはこのtcpdumpが標準で搭載されているケースが多く、調べたところ案の定インストールされていました。
要するにtcpdumpを使えば、Pingコマンドを打てなくとも「パケット受信」を確認できるのです。

↑図5:Linuxならではの疎通チェック
さっそくUbuntuからtcpdumpコマンドを実行。パケット待機状態を確認し、WEBサーバ側からPostgreSQL通信を試しました。
するとtcpdumpに反応あり。
Ubuntu側の画面からWEBサーバからの「SYNセグメント」の受信を確認しました。SYNセグメントを受け取れたということは
「FWは開通している」ということを意味しています。すなわち「3.FW機器の設定」の可能性は低くなったということです。

↑図6:TCPはFW越え成功…?
となると、残る原因は
「4.プログラムのバグ」の可能性です。「やっぱりプログラムのバグだったんですかね…」と同僚さんがプログラムの見直し準備を始めました。ところが……違和感を抱きました。
(……tcpdumpの結果、なんかおかしくね?)
SYNセグメントを受け取ったことを表示するtcpdumpを眺めつづけていたら、不思議な現象を確認したのです。
ACKが返らないSYNセグメントを受け取ったtcpdumpですが、
なぜか「ACK」のレスポンスを表示しませんでした。続けてSYNセグメントを数度受け取ったUbuntuは、のちにタイムアウトを起こしてしまいました。この瞬間、
私の背中にはイヤァな汗が…。なぜならこれにより
「4.プログラムのバグ」の可能性が消えてしまったからです。ネットワークドライバのようなソケットに絡むプログラムの場合ならともかく、今回同僚さんが作られたプログラムはPostgreSQLと通信する一般的な機能です。もしプログラムが不通の原因であれば、「SYN→ACK,SYN→ACK」のコネクションを経て張られた
TCP5432ポートのセッションの中でプログラムのバグによる通信断になるはず。
↑図7:プログラムの影響はハンドシェイク後
しかし、そもそもハンドシェイクに失敗している現状を踏まえますと「4.プログラムのバグ」はあり得ないことが分かってしまいます。
この結果はすなわち、今まで潰してきた原因の可能性がすべて
再浮上することにもなります。それだけならまだしも、トラブルの原因そのものが
自分が把握しきれていない範囲に及んでいる可能性さえあります。でも、現状は以下の通り。。
1.サーバOSの設定 → 全開放。問題なし
2.PostgreSQLの設定 → 他マシンからの通信は確認。DMZも許可した。問題なし
3.FW機器の設定 → SYNは受け取れている。問題なし
4.プログラムのバグ → そもそもハンドシェイクに失敗。問題なし
どこが通信断絶の原因か、まったく見当がつきません。。。
TCP Retransmission受け取ったSYNセグメントをダンプファイルとして出力し、Wiresharkで解析すると
「TCP retransmission」が表示されました。これはReceiverが受信したSYNセグメントと同じものがSenderから再送されてきたことを意味します。SenderがACKセグメントを受け取れていないということ。

↑図8:Wiresharkで解析した結果
ACKセグメントがレスポンスされず破棄された場合、通常ならばReceiverのFWを疑います。けれども前述したとおりFWは全開放、かつセキュリティソフトなどもOFFにしています。
私が持ち合わせているNWスキルでは、正直いって完全に「詰み」でした。けれども王手をかけられて投了することは許されません。これは勝負ではなく、仕事なのです。とにかく無い頭脳を振り絞って、あらゆる可能性を疑いました。
(…もしかしてUbuntuはACKセグメントをレスポンスしているも、tcpdumpが表示されていないだけ?)
その可能性はたいへん低いとは思いましたが、
どんな些細な事でも疑うことがトラブル解決の基本です。「今インストールされているtcpdumpはACKセグメントを表示しないバグなのだ。そうに違いない!!」なんて都合よく仮定して、無理やりながらもあらゆる可能性を疑いました。 けれどもACKセグメントを返していたとしても、
戻りポートを確かに開放しているため辻褄が合いません。
「もしかして
ポートフォワーディングが原因では?」とも疑いました。
「NAT の理解は芋づる式(2014/05/10)」でメモしましたが、ポートフォワーディングを正しく指定しない場合、SYNを受け取ったReceiverからのレスポンスとなるACKセグメントをNAPTが置換前のポートに戻すことができず、通信断を引き起こすケースがありました。
DMZからのLAN通信の際にポートフォワーディングを設定することは珍しくなく、この可能性を大いににらみました。

↑図9:同時のイメージ
しかし、この予想も冷静に考えたらハズレ。
そもそもポートフォワーディングをDMZ領域では設定していない、という情報も後ほど教えていただきました。
いよいよサッパリ訳が分からない状態に陥りました。
完全に行き詰ってしまったので、もう一度初心にかえってイチから…いえ
白紙撤回してゼロから調査を再開することにしました。
ネットマスクが違った解決は突然やってきました。最初から原因を切り分けるため、根本的な部分「IPアドレス」の確認から再スタートしようとifconfigコマンドを実行。指さし確認しながら、画面に表示された項目をひとつひとつチェックしていきました。
(………あっ!!もしかしてコレじゃね!?)
驚愕―――
PostgreSQLサーバのネットマスクが未設定でした。
急いでネットマスクを再設定して、通信を試みた結果……
なんと通信が無事に確立してしまいました。こんなに頭を悩ませたのに、なんとあっけないことでしょうか…。
普通に考えれば不通の原因を探るとき、ネットマスクの確認なんて当たり前のことです。けれども同一セグメントからの通信が確立しており、なによりもPostgreSQLサーバは数年前から稼働しているモノ。まさか「ネットマスクが未設定」なんて誰が疑うでしょうか。
しかし私は
「どんな些細な事でも疑うことがトラブル解決の基本」と前述してしまったので、今の発言は大変矛盾しています。なんにせよブランクを言い訳にせず、私が普段からNWスキルの習得を怠らなければ、ここまで時間がかかることは無かったでしょう。
「つながってくれれば、それでよし!!」
と同僚さんはおっしゃってくれて、私もそれは同感です。
けれども一時はインフラまわりのプロを目指した身からすれば、終始勘を取り戻せずに終わってしまった本トラブル対応には、反省ばかりが残ったのでした。
最後に冒頭にも書きましたが、この経験はとても勉強になりました。
その理由は「NWスキルが役立ったから」ですが、それは二次的なこと。根本的には
「PGでもトラブル原因の追及力が必要」という現状を肌で感じたことです。
もちろんスタンスは現場によりけりで「PGはプログラムだけできれば良い」というケースもあるかもしれません。私自身も、開発チームとしてこの現場に来たとき(ここには凄腕のインフラチームがいるし、この現場で自分のNWスキルが活躍することはないだろうな)と思っていたくらいです。
けれどもその考えは間違っていました。
もしトラブルに行き詰ってしまい、インフラチームに助け乞うとしても「なぜか通信できないのでなんとかしてください」といった、いわゆる
「丸投げ」が通用しないケースがあります。そういった場合、
自分自身でトラブルの発生原因を論理的に説明できるくらいまで追及し、理解するスキルが求められます。今回の私はサブネットマスクを見落とすといった、
ハイパーありえない醜態にダウナーになりました。その反面で(PGやSEになっても、NWの学習は怠っちゃイカンなぁ…)といった収穫もありました。
やはり日々切磋琢磨ですな。
そうシミジミした、久しぶりのブログでございましたw
スポンサーサイト