Stunnel:Linux上のレガシーサービスにTCP接続の暗号化をもたらす「救世主」

Network tutorial - IT technology blog
Network tutorial - IT technology blog

VPNやSSHトンネルがある今、なぜStunnelが依然として非常に有用なのか?

システム管理者(SysAdmin)の方なら、古いバージョンのRedisやMemcached、あるいは生のTCPソケットを使用するPython/Goスクリプトといった「骨董品」のようなアプリケーションを維持しなければならない状況に馴染みがあるでしょう。これらのサービスは通常、データをプレーンテキスト形式で送信します。ハッカーが同じネットワークセグメントにいてスニッフィングを行うだけで、機密情報はすべて筒抜けになってしまいます。

社内のデータ配信システムでStunnelを6ヶ月間運用してみた結果、これが最も「軽量な」ソリューションであると実感しました。処理リソースを20〜30%消費するような重厚なVPNシステムを構築する代わりに、StunnelはスリムなSSLプロキシとして機能します。これはTCP接続を堅牢なTLSパイプで包み込む(ラッパー)ものです。暗号化と復号は下位レイヤーで透過的に行われるため、元のアプリケーションのコードを変更する必要は一切ありません。

LinuxへのStunnelのインストール

Stunnelのインストールは非常に簡単で、ほとんどのディストリビューションの公式リポジトリに含まれています。

Ubuntu/Debianの場合

sudo apt update
sudo apt install stunnel4 -y

CentOS/RHEL/AlmaLinuxの場合

sudo yum install stunnel -y

Debian/Ubuntuユーザーへのちょっとした注意点:/etc/default/stunnel4ファイルを編集する必要があります。ENABLED=0ENABLED=1に変更してください。そうしないと、サービスがシステム起動時に自動開始されません。

証明書の迅速な作成

Stunnelの動作には、秘密鍵と証明書のペアが必須です。サーバー間の内部ネットワークでのみ使用する場合、自己署名証明書(オレオレ証明書)が最も手軽な選択肢です。

以下は、有効期限365日の証明書を素早く作成する方法です:

openssl genrsa -out key.pem 2048
openssl req -new -x509 -key key.pem -out cert.pem -days 365
cat key.pem cert.pem > /etc/stunnel/stunnel.pem
chmod 600 /etc/stunnel/stunnel.pem

chmod 600コマンドを忘れないでください。stunnel.pemファイルには秘密鍵が含まれているため、rootユーザーまたはサービス実行ユーザーのみが読み取りを許可されるべきです。

サーバーとクライアントのStunnel設定

ポート9000で動作している(暗号化されていない)バックエンドサービスがあり、クライアントがポート9443を介して安全に接続できるようにしたい場合を想定してみましょう。

1. サーバー側(受信側)の設定

/etc/stunnel/stunnel.confファイルを開き、以下の内容を貼り付けます:

pid = /var/run/stunnel4.pid
cert = /etc/stunnel/stunnel.pem
sslVersion = TLSv1.2
foreground = no

[my-secure-service]
accept = 9443
connect = 127.0.0.1:9000

ここで、acceptは暗号化された接続を受け入れる「フロントゲート」のポートであり、connectは古いサービスがリッスンしている内部ポートです。

2. クライアント側(送信側)の設定

クライアント側では、Stunnelは逆の役割を果たします。ローカルアプリケーションから通常のデータを受け取り、SSLで包んで送信します。設定は以下の通りです:

client = yes
pid = /var/run/stunnel4.pid

[my-secure-service-client]
accept = 127.0.0.1:8000
connect = サーバーの外部IP:9443

これで、アプリケーションはlocalhost:8000を指すだけで済みます。残りの処理はStunnelが自動的に行います。

ファイアウォール経由でStunnelにアクセスできるIPを制限するために、私はよくtoolcraft.app/ja/tools/developer/ip-subnet-calculatorを使用します。このツールはCIDRやIP範囲を非常に素早く計算できるため、特定の内部サブネットを正確にホワイトリストに登録する際のミスを防げます。

動作確認と運用の監視

以下のコマンドで新しい設定を有効にします:

sudo systemctl restart stunnel4

ポートが開いているか確認するには、ssコマンドを使用します。これは高速で、数千の接続があるサーバーではnetstatよりも詳細な情報を提供してくれます:

ss -tlnp | grep stunnel

実戦的な経験から言うと、導入初期には設定ファイルにdebug = 7という行を追加することをお勧めします。ログが/var/log/syslogに詳細に記録され、SSLハンドシェイクエラーなどが発生した場合にすぐに気づくことができます。特に、証明書の期限が切れる前にアラートを設定しておき、サービスが突然切断されるのを防ぐようにしましょう。

プロダクション環境での「痛い目を見ないための」注意点

デフォルトでは、Stunnelは暗号化のみを担当し、ユーザー認証は行いません。セキュリティを最大化するには、クライアント証明書認証(Client Certificate Authentication)を使用すべきです。これにより、有効な証明書を持つクライアントのみがシステムに接続できるようになります。

パフォーマンス面では、Stunnelは暗号化タスクを非常にうまく処理します。ただし、システムが毎秒数万件の接続(高コンカレンシー)を処理する必要がある場合、継続的なSSLハンドシェイクによりCPU負荷が高くなる可能性があります。その場合は、HAProxyによるSSLターミネーションの方がよりプロフェッショナルな解決策となります。

最後はファイアウォールの問題です。信頼できるIPに対してのみacceptポートを開放し、ハッカーがセキュリティレイヤーをバイパスして元のサービスに直接アクセスできないよう、connectポート(元のサービス)は厳重に閉鎖してください。

Stunnelは、コードに手を加えることなく旧式のシステムを近代化するための、最も「安・近・短(手軽で効果的)」な選択肢です。設定で困ったことがあれば、お気軽にコメントを残してくださいね!

Share: