Nginx の TCP プロキシ機能を使って SSH 接続の管理を行う
はじめに
リモートサーバーへのSSH接続には、セキュリティと利便性の両面から「踏み台サーバー」を利用するケースが多くあります。しかし、従来の踏み台サーバーを使用する場合、SSHクライアント側でプロキシ設定を別途行う必要があるため、SSHに詳しくないユーザーは接続の設定に苦労しがちです。
あるサーバーを経由して別のサーバーにSSH接続を行うとき、この接続をより簡単に行うための仕組みとしてNginxのTCPプロキシ機能を利用することができます。 この記事ではこの機能を使うことで複雑なSSHクライアント設定を避け、シンプルなSSH接続の管理を実現する方法を説明します。
Nginx TCP プロキシとは
Nginxは通常HTTP/HTTPSプロトコルのリバースプロキシとして利用されますが、モジュール ngx_stream_proxy_module を使用することで TCP 通信をプロキシすることもできます。 このモジュールは、TCPやUDPなどのストリームプロトコルをプロキシするためのNginxの拡張機能で、SSHやMySQLなどのデータベースのようなTCPプロトコルを中継するのに利用されます。
ただし、このモジュールは標準では導入されていないこともあります。 例えば Amazon Linux 2023 であれば標準の nginx とは別で nginx-mod-stream として提供されているので、以下に示す dnf コマンドで追加インストールする必要があります。
$ sudo dnf install nginx-mod-stream
本記事の内容を利用する場合はこのモジュールをインストールした nginx を利用してください。
TCPプロキシとSSHプロキシの違い
踏み台サーバー(SSHプロキシサーバー)は主に外部ネットワークから内部のサーバーに安全に接続するための中継用途として利用されます。 クライアントはまずプロキシサーバーにSSH接続し、その後、目的のサーバーに接続します。 そのため、プロキシサーバーと目的のサーバーの両方に接続可能な認証情報が必要となります。
一方、NginxのTCPプロキシサーバーも通信の中継用途として利用されますが、TCPプロキシでは特定のポートでListenしたクライアントからのTCP通信(ここではSSH通信)を指定のサーバーに転送します。 単なる転送であるため、プロキシサーバーではSSHプロトコルには介入せず、認証は転送先のサーバーのみで行われます。 そのため、目的のサーバーのみに認証情報を登録しておけば良いということが利点です。
さらに、TCPプロキシ経由でSSH接続を行った場合、バックエンドのサーバーからはすべてのアクセスがTCPプロキシサーバーからの接続として認識されます。そのため、目的のサーバー側でIP制限を設定する場合、接続元のIPアドレスをNginxサーバーのIPに集約できます。
SSHクライアント設定についても、SSH プロキシの場合はクライアントにプロキシを利用する設定をする必要がありますが、TCPプロキシの場合はプロキシの特定ポートに対して SSH 接続するような単純な設定を行うだけで設定が完了します。
Nginx の設定例
Nginxの設定ファイル (例: nginx.conf) に以下のような stream ディレクティブを記載します。 このような設定を行った後、<nginxサーバー>:20022
に対して ssh 接続を行うことで、目標のサーバー(ここでは 192.168.1.10)に接続できます。 複数の接続先サーバーがある場合、それぞれ異なるポート番号を使用することで、Nginx経由で異なるサーバーに簡単に接続できます。
stream { upstream ssh_server { # 接続先SSHサーバーのIPとポート server 192.168.1.10:22; } server { # クライアントが接続するポート listen 20022; proxy_pass ssh_server; } }
おわりに
この記事では、従来のSSHプロキシの代わりにNginxのTCPプロキシ機能を利用することで、SSH接続を簡素化する方法を紹介しました。NginxのTCPプロキシを活用することで、クライアント設定がシンプルにすることができます。
今回はSSHの例を中心に説明しましたが、Nginxのstream機能はTCP/UDP通信全般に応用可能です。たとえば、データベース接続の中継や、多量のリクエストの負荷分散といった用途にも適しています。
NginxはHTTP/HTTPSだけでなく、幅広い通信プロトコルのプロキシとして機能するため、柔軟で強力なソリューションとして、多様なシステム構築に役立つことを改めて確認できました。