同じポート検査をオフィス回線とVPN出口から実行すると、誰も変えていないアドレスについて二つの答えが食い違うことがあります。その差は経路と、どちらのホストが応答したかから来るもので、サービスが稼働しているかどうかではありません。三つの問い、つまり検査が実際に何を尋ねたか、どのホストが答えたか、自分のサーバーが何を記録したかが、その説明を分けます。この順に確認し、次へ進む前にそれぞれの答えを書き留めてください。

二つの実行を比べる前に検査を直す

状態語は、両方が同じ実験から出たものでなければ、別の状態語と比較できません。五つの項目がそれを固定します。遠い側が見た送信元アドレス、解決された宛先、ポート、スキャンの種類、そして時刻です。どれか一つを変えれば、最初の実験を二度測るのではなく、二つ目の実験を行ったことになります。

VPNクライアントが起動していても通信が物理インターフェースから出ていることがあるため、まず送信元を確認し、遠い側に何が見えるかを尋ねたうえで、カーネルがどのインターフェースを選んだかを尋ねてください:

curl -s https://ifconfig.me
ip route get 203.0.113.20

二つのアドレスが別のネットワークにあるなら、説明はすでに手元にあります。それらが一致したら、理由フラグを立てた状態で検査を記録し、状態が裸の単語として単独で立つのではなく説明に結びついて返るようにします。スキャンの種類も、返ってきたことではなく尋ねたことを記述するものとして、その記録に属します。送信元も方法もタイムスタンプもない状態は、何とも比較できません:

nmap -sT -p 443,8443 --reason 203.0.113.20

その出力は、次の人が見られないスクロールバッファではなく、記録の隣に置いてください。意見の食い違う二つの正直なスキャンは、誰も条件を書き留めていないときにだけ論争になります。条件が固定されれば、結果が一致して問いが閉じるか、あるいは結果が異なり、その違いは経路についての事実です。

どのホストがハンドシェイクを終えたのかを突き止める

完了したハンドシェイクは、何らかのホストがそれを完了したことを証明しますが、そのホストがあなたの想定するプロセスである必要はありません。ロードバランサー、リバースプロキシ、SYNプロキシは、実際のサーバーが関与する前に応答することがあり、これは異常ではなく通常の設計です。期待する名前に対する有効な証明書も、サービスの関係を記述するだけでどのマシンが接続を終えたかは言わないため、これを狭めません。

Nmapのポート状態のリファレンスはこれを基本とみなします。状態は、送信された場所から検査が観測できたことを記録するのであって、ポートの性質ではありません。状態語をそう読めば、食い違っていた二つの実行は矛盾ではなく一貫して見え始め、問いはポートが開いているかどうかから、その前に誰が立っていたかへと移ります。

二つ目の問いには外側からではなくバックエンドで答えてください。接続を受け付けてから上流に届かないフロントエンドは、遅いアプリケーションを抱えた健全なサービスの外観をそのまま作ります。二つの場合は上流自身の記録だけが分けます:

tail -n 5 /var/log/nginx/access.log
ss -ltnp 'sport = :443'

ログ行はアプリケーションが実際に見たクライアントアドレスを示し、二つ目のコマンドはポート443を保持しているプロセスが自分のアプリケーションか、その手前の何かを示します。両者がどのアドレスが接続したかで食い違うなら、一つのリクエストの二本の脚を見ているのであり、チケットはそう書くべきです。

トンネルを責める前に自分のルールを確認する

意図的に設けたポリシーは、あるネットワークではポートが応答し別のネットワークでは応答しない最も一般的な理由であり、利用できる説明の中で最も面白くないものです。アクセスルールは一つの送信元を許可し残りを落とすために存在するので、出口の変更はまさにそれらが書かれた出来事です。したがってVPN経由の異なる状態は、提供者が通信を検査していることを示しません。それは送信元アドレスが今は違うということを示すだけで、はるかに小さな主張です。

そのルールはサーバー上で読めるので、ネットワークの中央について推測せずに読み、二つのアドレス範囲のどちらかに触れるフィルタールールを列挙して、接続がそもそもデーモンに届いたかを確認してください:

nft list ruleset | grep -n -e 203.0.113 -e 198.51.100
journalctl -u sshd -n 50 | grep 203.0.113

二つ目の結果が空であることは情報になります。デーモンには何も届いておらず、問いはフィルター、セキュリティグループ、あるいは経路そのものに属するからです。ヒットは、サービスが送信元を見て応答を選んだことを意味し、その判断は通常、読めるルールに書かれています。どちらの結果も提供者についての物語を支えず、どちらもパケットキャプチャより安く確認できます。

トランスポート、証明書、応答を別々に読む

三つの層が三つの観測を生み、その一つを試す検査は残りの二つについて報告できません。一つの評決に折りたたむのではなく、記録の中で別々の行として保ってください。各行はそれぞれの仕方で失敗し、その失敗の仕方が次にどこを見るべきかを教えてくれます。

ObservationWhat it settlesWhat it leaves open
Connection completedA host on the path accepted the handshakeWhich host, and whether its upstream is reachable
Certificate valid for the nameThe endpoint holds a credential for that nameWhether the process behind it is the one you meant
Expected response bodyThe application handled the requestAnything about other ports or other paths
Connection refusedA host replied and nothing was listeningWhether a filter sits ahead of the refused port
TimeoutNo reply arrived before the deadlineDrop, blackhole route or an overloaded host

一つのコマンドが自分が管理するサービスに対して最初の三行を生み出すので、その出力はチャットメッセージではなくスキャンの隣の記録に置いてください:

curl -v --resolve office.example:443:203.0.113.20 https://office.example/

出力を順に読んでください。ハンドシェイクはトランスポートの問いに、証明書の主体は名前の問いに、応答本体はアプリケーションの問いに答えます。ハンドシェイクの行が成功して応答の行が失敗するなら、ブロックされたポートではなく上流が壊れたフロントエンドを持っています。それは開いたチケットとは別のチケットであり、はっきりそう書く価値があります。

チケットに四つの事実を書いて終えてください。送信元アドレス、スキャンの種類、応答したホスト、そして時刻です。後での比較に必要なものはすべてこの四つの中にあり、次にこの案件を引き継ぐ人にはあなたのターミナル履歴がありません。四つすべてを埋められないなら、その実行は終わっていません。

関連記事