Linuxでsocatコマンドを使いこなす:ポート転送・リレー・SSLトンネルの実践ガイド

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

ファイアウォールに阻まれても、仕事は止められない

2年ほど前のことです。データセンター内の内部サーバーがポート5432(PostgreSQL)でサービスを提供しているのに、ファイアウォールはポート443しか通さないという厄介な状況に遭遇しました。開発チームはリモートから接続したいけれど、ファイアウォールの設定変更には触りたくない——チケットを起票して、承認を待って、一日が終わってしまいます。

そのとき使ったのがsocatです。コマンド一発、30秒で解決しました。それ以来、複雑な設定なしにネットワークの「両端をつなぎたい」ときはいつもこのツールを使っています。

socatSOcket CATの略)は、任意の2つのアドレス間に双方向接続を作るコマンドラインツールです。TCPポート、UDPポート、Unixソケット、ファイル、さらにはstdin/stdoutまで接続先として使えます。netcatが折りたたみナイフなら、socatはドライバーも栓抜きも付いた十徳ナイフといったところです。

socatの仕組み

覚えるパターンはひとつだけです:

socat [options] <address1> <address2>

2つの「アドレス」を指定すれば、socatがその間の接続確立とデータ転送を担います。アドレスには多くの種類が使えます:

  • TCP:host:port — host:portへのTCP接続
  • TCP-LISTEN:port — 指定ポートでTCPをリッスン
  • UDP:host:port / UDP-LISTEN:port — UDPも同様
  • SSL:host:port — SSL/TLS接続
  • UNIX-CONNECT:/path/to/socket — Unixドメインソケット
  • EXEC:/path/to/program — プログラムを起動してstdioをパイプ
  • STDIN / STDOUT / FILE:/path — ファイルおよびstdio

まずはインストールから:

# Debian/Ubuntu
sudo apt install socat

# RHEL/CentOS/Rocky
sudo dnf install socat

実践:よくあるユースケース

1. シンプルなポート転送(Port Forwarding)

私が最もよく使うユースケースです。例えば、ポート8080への接続をすべて同じマシンのポート80に転送するには:

socat TCP-LISTEN:8080,fork TCP:localhost:80

forkオプションは非常に重要です。これがないとsocatは1つの接続だけ処理して終了します。forkを付けることで、新しい接続ごとに子プロセスが生成されます。

より実践的なケース:ローカルマシンから外部に公開されていない内部サーバーへポートを転送する:

# ジャンプサーバー(パブリックIP持ち)上で、ポート5432を内部DBサーバーへ転送
socat TCP-LISTEN:5432,fork,reuseaddr TCP:192.168.1.50:5432

reuseaddrオプションにより、socatの再起動直後にポートを再バインドできます。TCP TIME_WAITタイムアウト(デフォルト60〜120秒)を待つ必要がなくなります。

2. リレー構築——複数ホップを経由した転送

東京と大阪にオフィスがあるとします。東京の内部サービスに大阪からアクセスしたいが、直接ルーティングはファイアウォールで遮断されている。そんなときは中間VPSをリレーとして使います:

# 中間VPS(例:シンガポール)上で
# ポート9000をリッスンして、東京サーバーのポート22へ転送
socat TCP-LISTEN:9000,fork,reuseaddr TCP:tokyo-server.internal:22

大阪からはシンガポールVPSのポート9000にSSHトンネル接続するだけで、実質的に東京サーバーへSSHできます:

ssh -p 9000 [email protected]

このリレーは追加の暗号化を行いません——VPSと東京サーバー間はプレーンTCPのままです。アプリケーション層で暗号化している場合(SSH、HTTPSなど)は問題ありません。

3. UDPリレー——netcatには難しい芸当

UDPは接続状態を持たないため、TCPよりリレーが複雑です。socatは専用の構文でこれをうまく処理します:

# UDPポート514(syslog)を集中ログサーバーへ転送
socat UDP-RECVFROM:514,fork UDP-SENDTO:logserver.internal:514

UDP-LISTENではなくUDP-RECVFROMを使うことで、複数クライアントが同時に送信しても競合せずに処理できます。

4. SSLトンネル——意外と知られていないが便利な機能

プレーンTCPのサービスを暗号化接続で外部公開したい、でもnginxやstunnelは立てたくない——そんなときもsocatが使えます。証明書さえあればOKです。

自己署名証明書の作成(または既存の証明書を使用):

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt
cat server.crt server.key > server.pem

サーバー側——プレーンTCPサービスをSSLでラップ:

# ポート8443でSSLをリッスンし、localhostのポート8080へ転送
socat SSL-LISTEN:8443,cert=server.pem,verify=0,fork TCP:localhost:8080

クライアント側——SSLエンドポイントに接続してローカルポートに公開:

# サーバーにSSL接続し、ローカルポート8080として公開
socat TCP-LISTEN:8080,fork SSL:yourserver.com:8443,verify=0

verify=0は証明書の検証をスキップします——内部環境では問題ありません。本番環境では有効な証明書を使い、このオプションは外してください。

5. クイックデバッグ——TCPサーバーのエミュレート

クライアントが接続できるか確認したいときや、何を送信しているか確認したいときによく使います:

# ポート8080をリッスンして、クライアントが送ったデータをターミナルに表示
socat -v TCP-LISTEN:8080,fork -

-vオプションはデータと接続情報を方向別に出力します。アプリケーションの生のリクエストを確認したいだけならWiresharkより手軽です。

固定レスポンスを返すサーバーのエミュレーション:

# ポート9999への接続にresponse.txtの内容を返す
socat TCP-LISTEN:9999,fork OPEN:response.txt,rdonly

6. systemdサービスとしてsocatを常駐させる

管理しているオフィス環境では、一部のリレーを常時稼働させる必要があります。ターミナルを開きっぱなしにする代わりに、systemdサービスとして登録するとすっきりします:

# /etc/systemd/system/socat-relay.service
[Unit]
Description=socat port relay 8080 -> internal:80
After=network.target

[Service]
ExecStart=/usr/bin/socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.1.10:80
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now socat-relay

実運用での注意点

  • セキュリティ: socatには認証機能がありません。パブリックインターフェースにバインドすると誰でも接続できます。ufw/iptablesと組み合わせて接続元IPをホワイトリスト化しましょう。
  • bindオプション: デフォルトではsocatはすべてのインターフェースでリッスンします。ローカルのみに制限するにはbind=127.0.0.1を追加します:TCP-LISTEN:8080,bind=127.0.0.1,fork
  • IPv6: IPv6が必要な場合はTCPの代わりにTCP6-LISTENTCP6を使います。
  • 接続数の制限: max-children=10オプションで同時子プロセス数を制限できます——パブリック公開時のフラッド対策に有効です。

socatを使うべき場面、使わない場面

socatは状況に応じて使うツールだと考えています——システム設定を変えずにサクッと解決したいときに真価を発揮します。向いているのは:

  • 一時的なポート転送(テスト、デバッグ、緊急対応)
  • 複雑な設定不要のシンプルなリレー
  • プレーンTCPをSSLで手早くラップ
  • 低レイヤーのネットワーク通信のデバッグ

一方、socatを使わない方がよい場面:

  • ロードバランシングやヘルスチェックが必要 → HAProxy/nginxの方がずっと適切
  • ログ、リトライ、タイムアウトが必要な本番リバースプロキシ → socatは機能不足
  • 強固な暗号化を備えたVPNトンネルが必要 → WireGuard/OpenVPNが正しい選択

socatのコマンドを30秒で打つ方が、他のツールを2時間かけて設定するより効果的な場面があります。HAProxyやnginxの代替ではありませんし、その必要もありません。それぞれに役割があるということです。

まだツールボックスに入っていないなら、今すぐ追加しておきましょう。毎日使うわけではありませんが、必要なときに代わりになるものはありません。

Share: