Linux サーバーの運用中に、次のような状況に遭遇したことはないでしょうか。
- アプリケーションのポートを変更せず、別のポートからアクセスしたい
- MariaDB や API サーバーへの接続経路を一時的に変更したい
- UNIX ドメインソケットを TCP 経由で利用したい
- Docker コンテナやバックエンドサービスの通信を調査したい
- サーバー移行時に、一時的な TCP 中継を設置したい
- 通信障害がアプリケーション側なのか、ネットワーク側なのかを切り分けたい
このような場面で役立つのが、Linux の socat です。
socat は、TCP、UDP、UNIX ドメインソケット、標準入出力、ファイル、プロセスなど、異なる通信エンドポイント間でデータを転送できるツールです。
本記事では、基本構文から始めて、実務で利用する代表的な構成を再現しながら、運用上の注意点まで解説します。
対象読者
- Linux サーバーを運用するエンジニア
- Docker、nginx、Laravel、MariaDB などを利用するバックエンドエンジニア
- ネットワークやアプリケーションの通信障害を調査する担当者
- systemd を使ったサービス運用を学びたい方
検証環境
| 項目 | 環境 |
|---|---|
| OS | Ubuntu Server 24.04 LTS を想定 |
| ツール | socat |
| サービス管理 | systemd |
| Web サーバー | Python 標準 HTTP サーバー |
| DB | MariaDB を例示 |
| その他 | curl、ss、journalctl |
※以降のコマンドは一般的な Linux 環境を想定した例です。実際の運用に合わせて IP アドレス、ポート番号、ファイアウォール設定を調整してください。
1. socat とは?
socat は SOcket CAT に由来する名前で、2つの通信エンドポイントを双方向につなぐコマンドラインツールです。
基本構文は次のとおりです。
socat [オプション] <アドレス1> <アドレス2>
例えば、TCP ポート 8080 で受信した通信を、ローカルの TCP ポート 3000 に転送する場合は、次のように記述します。
socat \
TCP-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork \
TCP:127.0.0.1:3000
通信の流れは次のようになります。
Client
|
| TCP :8080
v
+------------------+
| socat |
| |
| Listen :8080 |
| | |
| v |
| TCP :3000 |
+------------------+
|
v
Application
127.0.0.1:3000
クライアントは 8080 番ポートに接続するだけで、3000 番ポートで動作するアプリケーションと通信できます。
socat は基本的にデータをそのまま転送するため、HTTP 以外の TCP プロトコルにも利用できます。
nginx や netcat との違い
| ツール | 主な特徴 | 向いている用途 |
|---|---|---|
| socat | 多様な通信エンドポイントを接続 | TCP 中継、ソケット変換、デバッグ |
| netcat(nc) | シンプルなネットワーク通信 | 疎通確認、簡易 TCP/UDP テスト |
| nginx | HTTP リバースプロキシ、TCP/UDP プロキシ | Web サーバー、リバースプロキシ |
| HAProxy | 高性能な L4/L7 プロキシ | ロードバランサー、可用性向上 |
| SSH | 暗号化通信とポート転送 | 安全なリモート接続 |
socat は、nginx や HAProxy の代替というよりも、通信経路を素早く作成・変更・検証するためのツールと考えると理解しやすいでしょう。
2. socat をインストールする
Ubuntu / Debian の場合:
sudo apt update
sudo apt install -y socat
Rocky Linux / AlmaLinux などの場合:
sudo dnf install -y socat
インストール後、バージョンを確認します。
socat -V
実行ファイルの場所も確認できます。
command -v socat
一般的には /usr/bin/socat が返されます。
詳細なマニュアルは次のコマンドで確認できます。
man socat
3. 実践① TCP ポート転送を構築する
最初に、最も利用頻度の高い TCP ポート転送を試します。
想定する構成
アプリケーションはローカルのポート 3000 で稼働しています。
これを、ポート 8080 からアクセスできるようにします。
Client
|
| http://127.0.0.1:8080
v
socat :8080
|
| TCP Forward
v
Web Server :3000
Step 1. Web サーバーを起動
まず、検証用の HTTP サーバーを起動します。
mkdir -p /tmp/socat-demo
cd /tmp/socat-demo
echo "Hello from Backend Server" > index.html
python3 -m http.server 3000 --bind 127.0.0.1
別ターミナルから確認します。
curl http://127.0.0.1:3000
期待する出力:
Hello from Backend Server
Step 2. socat を起動
別ターミナルで実行します。
socat -d -d \
TCP-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork \
TCP:127.0.0.1:3000
各オプションの意味は以下のとおりです。
| オプション | 説明 |
|---|---|
TCP-LISTEN:8080 |
TCP 8080 番ポートで待ち受け |
bind=127.0.0.1 |
ローカルホストからの接続に限定 |
reuseaddr |
ソケットアドレスの再利用を許可 |
fork |
接続ごとに子プロセスを生成 |
TCP:127.0.0.1:3000 |
TCP 3000 番ポートに接続 |
-d -d |
接続イベントなどの診断情報を出力 |
Step 3. 転送を確認
curl http://127.0.0.1:8080
期待する出力:
Hello from Backend Server
8080 番ポートでアクセスしたにもかかわらず、3000 番ポートの Web サーバーから応答が返っています。
これが socat による TCP ポート転送です。
Step 4. 待ち受けを確認
ss -lntp | grep 8080
socat が 127.0.0.1:8080 で待ち受けていることを確認できます。
実務での活用例
例えば、nginx が TCP バックエンドへ接続する前段で、既存サービスのポート変更や通信経路の検証を行う場合に利用できます。
ただし、HTTP のリバースプロキシとしての機能が必要なら nginx を使う方が適切です。
4. 実践② MariaDB サーバーへの TCP 接続を中継する
次は、インフラ運用で利用できる DB 接続中継の例です。
想定する構成
Application Server
10.0.1.10
|
| 127.0.0.1:3307
v
socat
|
| TCP
v
MariaDB Server
10.0.1.20:3306
MariaDB は 10.0.1.20:3306 で稼働しているとします。
アプリケーションサーバー上で socat を実行し、ローカルの 3307 を MariaDB の 3306 に接続します。
socat を起動
socat -d -d \
TCP-LISTEN:3307,bind=127.0.0.1,reuseaddr,fork \
TCP:10.0.1.20:3306
MariaDB クライアントから接続
mariadb \
--host=127.0.0.1 \
--port=3307 \
--user=appuser \
--password
MariaDB クライアントはローカルの 3307 番ポートに接続しますが、実際には socat が DB サーバーの 3306 番ポートに転送します。
Laravel での接続設定
.env を以下のように設定します。
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3307
DB_DATABASE=example_db
DB_USERNAME=appuser
DB_PASSWORD=your_password
これにより、Laravel アプリケーションは通常の TCP 接続として socat を経由できます。
設定キャッシュを使用している場合は、設定の再読み込みが必要です。
php artisan config:clear
この構成が役立つ場面
- DB サーバー移行前の接続検証
- アプリケーションの接続先切り替えテスト
- MariaDB のポート変更に伴う影響調査
- ネットワーク接続障害の切り分け
注意点:DB から見える接続元 IP
socat を経由すると、MariaDB サーバーには通常、socat を稼働させているサーバーの IP アドレスが接続元として見えます。
MariaDB ではユーザー認証に接続元ホストが関係するため、接続元 IP が変わることで認証エラーが発生する可能性があります。
また、socat は DB 接続を自動的に暗号化しません。
本番 DB では適切なアクセス制御と TLS を使用し、長期的な DB 接続管理やフェイルオーバーには ProxySQL、MariaDB MaxScale などの専用ツールも検討してください。
5. 実践③ UNIX ドメインソケットを TCP に変換する
Linux には TCP/IP 通信のほかに、UNIX ドメインソケットを使ったプロセス間通信があります。
例えば、以下のソケットです。
/run/myapp/app.sock
この UNIX ソケットで待ち受けるアプリケーションに、TCP 経由で接続したいケースを考えます。
TCP Client
|
| :8080
v
socat
|
| UNIX Socket
v
/run/myapp/app.sock
|
v
Application
TCP から UNIX ソケットへ転送
socat \
TCP-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork \
UNIX-CONNECT:/run/myapp/app.sock
これだけで TCP と UNIX ドメインソケットを接続できます。
UNIX ソケットのテスト環境を作る
最初にテスト用 UNIX ソケットを作成します。
ターミナル A:
socat \
UNIX-LISTEN:/tmp/demo.sock,unlink-early,fork \
EXEC:/bin/cat
ターミナル B:
socat \
TCP-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork \
UNIX-CONNECT:/tmp/demo.sock
ターミナル C:
printf "Hello UNIX Socket\n" | \
socat - TCP:127.0.0.1:8080
期待する出力:
Hello UNIX Socket
この例では /bin/cat が受信したデータをそのまま返しています。
unlink-early は既存のソケットファイルを削除してから作成するため、専用のテスト用パスで使用してください。
注意点:プロトコルは変換されない
socat は通信経路を接続しますが、アプリケーションプロトコルを自動変換するわけではありません。
例えば、PHP-FPM が UNIX ソケットで待ち受けている場合、そこで使われるのは FastCGI プロトコルです。
TCP に変換しても、HTTP クライアントから直接 HTTP リクエストを送れるようになるわけではありません。
6. 実践④ API 通信をデバッグする
アプリケーション間の通信障害を調査する場合にも socat が利用できます。
例えば、次のような構成です。
HTTP Client
|
| :8080
v
socat -v -x
|
| :3000
v
HTTP Backend
バックエンドの HTTP サーバーが 127.0.0.1:3000 にあるとします。
通信内容を確認する
socat -v -x \
TCP-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork \
TCP:127.0.0.1:3000
別ターミナルから:
curl -X POST http://127.0.0.1:8080/api/test \
-H "Content-Type: application/json" \
-d '{"message":"hello"}'
socat には以下のようなデータが出力されます。
POST /api/test HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/json
Content-Length: 19
{"message":"hello"}
実際の出力には転送方向や16進数表現も含まれます。
デバッグオプション
| オプション | 内容 |
|---|---|
-d |
基本的な診断情報 |
-d -d |
接続、終了などのイベント |
-d -d -d |
詳細な診断情報 |
-v |
転送データを表示 |
-x |
転送データを16進数形式で表示 |
運用上の注意
-v や -x による通信記録には、次の情報が含まれる可能性があります。
- Authorization ヘッダー
- セッション Cookie
- API トークン
- 個人情報
- パスワード
そのため、本番環境では通信データを無条件にログ出力しないようにしてください。
また、HTTPS の通信を単純な TCP 中継で観察しても、暗号化されたデータが表示されるだけです。
7. 実践⑤ サーバー移行時の一時的な通信転送
サーバー移行作業でも socat が活躍します。
例えば、API サーバーを新しいサーバーへ移行する場面を考えます。
Client
|
| TCP :8080
v
Old Server
10.0.1.10
|
| socat
v
New Server
10.0.2.20:9000
旧サーバー上で:
socat -d -d \
TCP-LISTEN:8080,bind=10.0.1.10,reuseaddr,fork \
TCP:10.0.2.20:9000
これにより、旧サーバーの TCP 8080 番ポートに届いた通信は、新サーバーの TCP 9000 番ポートへ中継されます。
この方式のメリット
- クライアント側の接続先を変更せずに検証できる
- 一時的な通信経路を素早く設置できる
- 移行対象アプリケーションの TCP プロトコルを基本的に変更しない
注意点
socat は HTTP ヘッダーや TLS 証明書を自動調整しません。
また、新サーバーから見える接続元 IP は一般的に旧サーバーの IP になります。
HTTP/HTTPS サービスの本番移行であれば、nginx、HAProxy、ロードバランサーなどで切り替えを管理する方が適切なことが多いです。
8. 【運用編】socat を systemd で常駐させる
ここからは socat を運用するための構成を紹介します。
コマンドを手動実行した場合、そのターミナルを閉じるとプロセスが終了することがあります。
継続的に中継サービスとして利用する場合は、systemd で管理すると便利です。
今回は以下の構成を作成します。
localhost:8080
|
v
socat.service
|
v
localhost:3000
8.1 専用ユーザーを作成する
まず、socat 実行専用のシステムユーザーを作成します。
sudo useradd \
--system \
--no-create-home \
--shell /usr/sbin/nologin \
socat-relay
確認:
id socat-relay
socat に管理者権限が必要ない場合は、root で実行しないことを推奨します。
8.2 systemd ユニットを作成する
/etc/systemd/system/socat-relay.service を作成します。
[Unit]
Description=Socat TCP Relay Service
Documentation=man:socat(1)
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=socat-relay
Group=socat-relay
ExecStart=/usr/bin/socat -d -d TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork,max-children=50 TCP4:127.0.0.1:3000
Restart=on-failure
RestartSec=5
LimitNOFILE=4096
TasksMax=128
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
設定のポイント
| 設定 | 説明 |
|---|---|
User |
専用ユーザーで実行 |
Restart=on-failure |
異常終了時に再起動 |
RestartSec=5 |
再起動まで5秒待機 |
max-children=50 |
同時接続を扱う子プロセスを最大50に制限 |
LimitNOFILE=4096 |
ファイルディスクリプタの上限 |
TasksMax=128 |
systemd 管理下のタスク数を制限 |
NoNewPrivileges=true |
新たな権限取得を防止 |
ProtectSystem=strict |
原則としてファイルシステムを読み取り専用化 |
ProtectHome=true |
ホームディレクトリへのアクセスを制限 |
PrivateTmp=true |
専用の一時ディレクトリ名前空間を使用 |
この例は TCP から TCP への転送専用です。
UNIX ソケットやファイルを利用する場合、権限や systemd の保護設定を別途調整する必要があります。
なお、max-children を指定しても、アプリケーションレベルでのタイムアウト管理や流量制限が実現するわけではありません。
8.3 サービスを起動する
sudo systemctl daemon-reload
sudo systemctl enable --now socat-relay
状態を確認します。
systemctl status socat-relay
正常に起動すれば、次のような状態になります。
Active: active (running)
8.4 動作確認
バックエンドが起動していることを確認した上で:
curl -v http://127.0.0.1:8080
また、ポートの待ち受けも確認します。
sudo ss -lntp | grep 8080
8.5 ログを確認する
journalctl -u socat-relay -f
直近100行を表示する場合:
journalctl -u socat-relay -n 100 --no-pager
特定日時以降のログを確認する場合:
journalctl -u socat-relay \
--since "2026-11-01 00:00:00"
systemd を利用すると、サービスの起動、停止、再起動、ログ管理を統一できます。
9. 【セキュリティ編】公開範囲とアクセス制御
socat の運用で最も注意すべきなのは、待ち受けアドレスです。
例えば:
socat \
TCP-LISTEN:8080,reuseaddr,fork \
TCP:127.0.0.1:3000
この指定は環境によって外部インターフェースでも待ち受けます。
意図せずサービスをネットワーク上に公開してしまう可能性があります。
9.1 ローカル接続だけを許可する
socat \
TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork \
TCP4:127.0.0.1:3000
bind=127.0.0.1 を指定することで、ローカル IPv4 インターフェースに限定できます。
9.2 特定ネットワークからのみ接続させる
socat の range オプションを利用すると、接続元アドレスを制限できます。
socat \
TCP4-LISTEN:8080,bind=10.0.1.10,reuseaddr,fork,range=10.0.1.0/24 \
TCP4:10.0.2.20:9000
この例では、指定された IPv4 ネットワーク範囲からの接続を許可します。
ただし、range だけに依存せず、ファイアウォールやクラウドのセキュリティグループでもアクセス制限を行うことが重要です。
9.3 ufw によるアクセス制御
Ubuntu で UFW を利用している場合、次のように接続元を指定できます。
sudo ufw allow from 10.0.1.0/24 \
to any port 8080 proto tcp
実行前に既存の UFW ルールや SSH 接続への影響を確認してください。
また、この許可ルールだけでは、既存のより広い許可ルールを打ち消せるとは限りません。
9.4 暗号化について
通常の TCP: による接続は自動的には暗号化されません。
socat には OpenSSL を利用する機能もありますが、証明書検証、鍵管理、暗号スイートなどを適切に設計する必要があります。
本番環境で安全な遠隔アクセスが目的なら、SSH トンネルや VPN、適切に設定された TLS プロキシなども選択肢になります。
特に、Docker の /var/run/docker.sock のような管理権限を持つソケットを、認証なしで TCP 公開することは避けてください。
10. 【監視編】socat の稼働状態と接続数を確認する
本番環境で socat を利用する場合、プロセスが存在することだけでなく、実際に通信できる状態かどうかを確認する必要があります。
10.1 サービスの状態を確認
systemctl is-active socat-relay
正常時:
active
10.2 TCP リスナーを確認
ss -lntp '( sport = :8080 )'
10.3 接続状態を確認
ss -tnp '( sport = :8080 or dport = :8080 )'
ESTAB の接続があれば、TCP セッションが確立していることが確認できます。
ただし、ESTAB があるだけでは、バックエンドのアプリケーションが正常に応答しているとは限りません。
10.4 HTTP ヘルスチェック
HTTP サーバーを中継している場合は、curl を使ってアプリケーションの応答まで確認できます。
curl \
--connect-timeout 3 \
--max-time 5 \
--fail \
--silent \
--show-error \
http://127.0.0.1:8080/health
/health はアプリケーション側で実装済みのエンドポイントを想定しています。
バックエンドが正常でも socat の待ち受け設定に問題があれば失敗し、逆に socat が起動していてもバックエンドが異常なら失敗します。
プロセス監視とエンドツーエンドの疎通確認を組み合わせることが、実際の運用では重要です。
10.5 簡単な監視スクリプト
例えば、/usr/local/bin/check-socat-relay.sh を作成します。
#!/usr/bin/env bash
set -euo pipefail
SERVICE="socat-relay"
URL="http://127.0.0.1:8080/health"
if ! systemctl is-active --quiet "$SERVICE"; then
echo "CRITICAL: $SERVICE is not running"
exit 2
fi
if ! curl --fail --silent --show-error \
--connect-timeout 3 \
--max-time 5 \
"$URL" > /dev/null; then
echo "CRITICAL: relay health check failed"
exit 2
fi
echo "OK: relay is healthy"
exit 0
実行権限を設定します。
sudo chmod 755 /usr/local/bin/check-socat-relay.sh
実行:
/usr/local/bin/check-socat-relay.sh
正常時:
OK: relay is healthy
これを Zabbix、Nagios などの監視システムや定期実行ジョブから呼び出すことで、異常検知に利用できます。
11. 【障害対応編】よくあるエラーと切り分け方法
socat の運用で遭遇しやすい代表的なトラブルを紹介します。
ケース① Address already in use
代表的なエラー:
bind: Address already in use
原因として考えられるのは、すでに別のプロセスが同じ IP アドレスとポートで待ち受けていることです。
まず確認します。
sudo ss -lntp | grep ':8080'
該当するプロセスを確認し、設定を変更するか、不要なサービスを停止します。
reuseaddr は万能なポート競合回避オプションではありません。
すでに別の TCP サービスが同じ組み合わせで待ち受けている場合、reuseaddr を指定しても通常は解決しません。
ケース② Connection refused
代表的なエラー:
connect: Connection refused
接続先でサービスが待ち受けていない、または接続を拒否された可能性があります。
まず接続先サーバーで:
ss -lntp | grep ':3000'
次に socat サーバーから直接:
curl -v http://127.0.0.1:3000
を試します。
ここで失敗する場合、socat の手前ではなく、バックエンドサービス側に問題がある可能性が高くなります。
ケース③ Connection timed out
接続がタイムアウトする場合、次のような原因が考えられます。
- ファイアウォールによる遮断
- AWS セキュリティグループによる制限
- ルーティングの不備
- 接続先の応答停止
- ネットワーク ACL の設定不備
まず接続先の TCP ポートを確認します。
nc -vz -w 3 10.0.2.20 9000
さらに必要に応じて、ネットワークパケットを確認します。
sudo tcpdump -ni any 'tcp port 9000'
SYN パケットが送信されているか、SYN-ACK が返っているかなどを確認すると、ネットワークレベルの問題を絞り込みやすくなります。
ケース④ socat は起動しているが API が動かない
このケースでは、次の順序で調査します。
1. socat のプロセスは起動しているか
|
v
2. 待ち受けポートは存在するか
|
v
3. socat へ TCP 接続できるか
|
v
4. 転送先へ直接 TCP 接続できるか
|
v
5. HTTP ステータスやレスポンスは正常か
|
v
6. アプリケーションログに異常はないか
このように、プロセス → TCP → アプリケーションプロトコルの順で切り分けると、原因を特定しやすくなります。
12. 本番運用における設計上の注意点
socat は軽量で柔軟ですが、本格的なロードバランサーではありません。
利用時には次の点を考慮します。
| 項目 | 注意点 | 対策 |
|---|---|---|
| 同時接続数 |
fork で子プロセスが増加 |
max-children、systemd の制限 |
| セキュリティ | 意図しない TCP 公開 |
bind、FW、ACL |
| 通信暗号化 | TCP 転送は暗号化されない | SSH、TLS、VPN |
| 可用性 | 中継プロセスが単一障害点になり得る | systemd、監視、冗長化設計 |
| ログ | 通信内容に機密情報が含まれる可能性 | 診断ログとデータログの分離 |
| 接続元 IP | 中継元の IP に変わる | 認証・アクセス制御への影響確認 |
| プロトコル | HTTP などを自動解析しない | 適切なプロキシを選択 |
| 性能 | 大量接続向けの専用プロキシではない | nginx、HAProxy などを検討 |
また、重要な点として、systemd の Restart=on-failure はバックエンドの正常性を保証するものではありません。
socat の親プロセスが稼働している状態で転送先が停止しても、systemd のサービスが active のままになる場合があります。
そのため、本番運用ではバックエンドを含むヘルスチェックが必要です。
13. socat を使うべき場面・使わない方がよい場面
最後に、ツール選定の観点から整理します。
socat が適している場面
- 一時的な TCP ポート転送
- アプリケーションの疎通確認
- UNIX ソケットと TCP の橋渡し
- サーバー移行前の通信テスト
- ネットワーク障害の調査
- 開発・検証環境での通信経路の変更
他のツールを検討すべき場面
- 大量の本番トラフィックを継続的に処理する
- 複数バックエンドにロードバランシングする
- HTTP の Host や URL を使って転送先を変更する
- 高度なヘルスチェックと自動フェイルオーバーが必要
- リトライ、レート制限、認証などを統合的に管理する
このような場合には、nginx、HAProxy、Envoy、クラウドロードバランサーなどが候補になります。
14. まとめ
socat は、Linux の通信トラブルシューティングやシステム運用で非常に便利なツールです。
本記事では、以下の内容を紹介しました。
- socat の基本構造と TCP ポート転送
- MariaDB 接続の中継
- UNIX ドメインソケットと TCP の相互接続
- API 通信のデバッグ
- サーバー移行時の一時的な通信転送
- systemd を使った常駐化
- アクセス制御とセキュリティ対策
- ログ監視とヘルスチェック
- ネットワーク障害の切り分け
- 本番運用時の設計上の注意点
基本構文は次の一行です。
socat <接続元> <接続先>
最初に覚えるコマンドとしては、以下がおすすめです。
# TCP ポート転送
socat TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork TCP4:127.0.0.1:3000
# 通信デバッグ
socat -d -d -v TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork TCP4:127.0.0.1:3000
# UNIX ソケットへの転送
socat TCP4-LISTEN:8080,bind=127.0.0.1,reuseaddr,fork UNIX-CONNECT:/tmp/app.sock
socat の本質は、アプリケーション側の実装を変更せずに、通信経路を作成・変更・観察できることです。
特に Linux サーバーや Docker、データベース、API サーバーを扱うエンジニアにとって、覚えておくと障害調査や検証作業の選択肢が広がります。
一方で、通信経路を柔軟に変更できるということは、設定を誤ると重要なサービスを意図せず公開する危険性もあるということです。
手軽な検証には socat、本格的なプロキシ運用には専用ツール。
この使い分けを意識することが、安全で保守しやすいインフラ構築につながります。