VPN 専用 NGINX サイト:リスナー、ファイアウォール、HTTP 許可リスト
プライベートな NGINX サイトには、束縛された VPN ソケット、範囲を絞ったホスト入力ルール、無傷の HTTP アクセス リストが必要です。サーバー ブロック一つではなく、三つすべてをテストしてください。
プライベートなサイトとインターネットの間には三つの独立した判断があります。どのソケットが接続を受け入れるか、どの経路がそれを届けられるか、選択したサーバーがどの HTTP クライアントに応答するかです。サーバー ブロックが決めるのは最初の一つだけです。残り二つを別個の制御として扱わないと、古い入口が開いたままなのにサイトはプライベートに見えてしまいます。VPN 専用 NGINX の失敗の多くは、最初の層だけをテストすることから生じます。
この例では、tun0 上の 10.90.0.1 にある Linux OpenVPN ゲートウェイ、10.90.0.0/24 のクライアント、保存された送信元、そしてこの入口用に予約された TCP 8443 を使います。値は調整しても、層はそのまま保ってください。
ホスト名ではなくソケットから始める
HTTPS リスナーをトンネルのアドレスと専用ポートに束縛します。特定のアドレスのほうが、ワイルドカード ソケットと名前チェックの組み合わせより考えやすいのは、カーネルがそのポートを別のローカル アドレスに渡さないからです。
server {
listen 10.90.0.1:8443 ssl;
server_name admin.corp.example;
ssl_certificate /etc/nginx/tls/admin-fullchain.pem;
ssl_certificate_key /etc/nginx/tls/admin-key.pem;
root /srv/private-site;
allow 10.90.0.0/24;
deny all;
location / {
try_files $uri $uri/ =404;
}
}
証明書にはクライアントが入力するサービス ホスト名が入っている必要があり、プライベート DNS ビューはそのホストを束縛されたアドレスに解決しなければなりません。server_name は仮想ホストを選ぶだけで、誰も認証しません。DNS エントリがないと TLS 障害に見える証明書エラー が発生します。証明書を交換する前に名前を確認してください。
ファイルを追加する前に実際の設定を読みます。インクルードやワイルドカード リスナーが同じルートを別の場所で提供していたり、既定サーバーが新しいブロックの見ない要求に応答していたりすることがあります。
そのコンテンツの他のリスナーをすべて閉じる
listen ディレクティブを一覧し、それらが提供するルートを比較します。別のアプリケーション用に追加したブロックが同じ upstream にプロキシしたり、新しいものを置いても古い既定サーバーが応答し続けたりします。その出力が本当の棚卸しであり、たった今編集したファイルではありません。同じコンテンツを提供するすべてのルートを比較してください。
sudo nginx -T | grep -n "listen\|server_name\|root\|proxy_pass"
両方のアドレス ファミリを確認します。IPv4 の束縛は IPv6 ソケットをそのまま残し、新しい A レコードは公開経路を指したままの古い AAAA 応答を引退させません。
古い仮想ホストは別の変更として廃止します。新しいブロックの公開側の双子を削除することが、実際に入口を閉じる手順であることがほとんどです。プライベート リスナーは意図した入口を加えるだけです。
ホスト側で受信経路の範囲を絞る
リッスン アドレスが制限するのはソケットであり、イングレス インターフェースではありません。別の場所からそのアドレスにルーティングされたパケットもローカル入力として届くため、ホストのファイアウォールには接続元をどこから許すかという独自の宣言が必要です。だからこそ束縛だけでは監査を満たすことはほとんどありません。
既定で拒否する受信ポリシーがあり、このサービスに広い許可がない場合、範囲を絞ったルールはトンネル、送信元範囲、宛先、ポートをまとめて指定します。
sudo ufw allow in on tun0 proto tcp from 10.90.0.0/24 to 10.90.0.1 port 8443
適用する前に実際のファイアウォール順序を読みます。以前の広い許可が制限を無効にしたり、以前の最終的な破棄がこの許可に到達させなかったりします。例に合わせるために無関係なルールを流したり、ファイアウォールを切ったりしないでください。
そのルールはホストへの入力であり、別の LAN マシンへの経路ではありません。ゲートウェイの外側の OpenVPN リスナーは別のサービスのままです。サイトが以前公開されていたなら、古い入口をどう廃止し、既存のセッションをどう扱うかを計画してください。
ロケーションが変わっても HTTP リストを無傷に保つ
NGINX は allow と deny のエントリを順に評価し、上記のサーバー レベルのリストは最後の deny の前に宣言されたプールを許可します。アクセス モジュールは、アクセス エントリを定義したロケーションが親リストではなく独自のリストを使うことも記録します。順序はエントリそのものと同じくらい重要です。
そのリセットがよくある後退です。エントリを一つ追加した新しいアップロード、API、ヘルス ロケーションがサーバー レベルの制限を黙って置き換え、サイトは最も最近追加された経路で広くなります。
すべてのロケーション、エイリアス、代替ブロックを同じポリシーの一部として見直します。IP チェックを NGINX 認証と組み合わせるなら、satisfy を理解してください。any 設定では、一方の仕組みでクライアントを通し、もう一方が通っていない状態になり得ます。アクセス リストをロケーション見直しチェックリストに入れてください。
HTTP の拒否は TCP 接続が NGINX に届いた後に起こります。これはネットワーク制限を補うものであり、アプリケーション自身の承認は各ユーザーに引き続き適用されます。
実際の経路と障害ケースを検証する
設定パーサーを実行し、リッスンしているソケットを調べ、意図したクライアントから新しい名前付き要求を行います。証明書が検証され、DNS 名が束縛されたアドレスに解決し、応答が想定したルートから来ることを確認してください。
次に除外した送信元と代替の入口を試します。許可された要求が通っても、閉じたかった経路については何も分かりません。除外テストでこそ、残ったリスナーや広いファイアウォール許可が現れます。
起動時や VPN 復旧時のケースを繰り返します。トンネル アドレスが存在する前に NGINX が起動すると、完璧なファイルでも束縛が失敗します。アドレスの準備を調整し、共有 Web サーバーを変更する前にローカルの復旧経路を用意してください。
通過したソケット、ポート、送信元範囲、HTTP リストを記録します。次の VPN や DNS の変更でどれでも動き得ますし、四つの名前付き値は動くブラウザー タブより比べやすいものです。