パッケージ探訪: socat
2026年7月6日
著者: 竹洞 陽一郎
はじめに
今回紹介するsocatは、Slackwareの公式パッケージとして収録されているツールです。
名前の通り「SOcket CAT」——TCPやUDP、Unixドメインソケット、シリアルデバイス、SSL/TLS、仮想端末(PTY)、TUNデバイスまで、あらゆるI/Oエンドポイントを2点間でつなぐ汎用中継器です。
netcatを知っているなら「その強化版」と言えばおおよそ伝わりますが、実際には別の思想で設計されたツールです。
SMTPのデバッグをしているとき、Tailscaleのポート疎通を確認したいとき、シリアルデバイスをネットワーク越しに操作したいとき——場面は違っても、手元に socat があれば一本で済みます。そういう種類のツールです。
今回は使い方の前に、このツールが何者で、誰が作り、どんな思想を持っているかを掘り下げます。
dest-unreach.orgとは
socatのホームページにアクセスすると、ドメインが www.dest-unreach.org であることに気づきます。
「到達不能な宛先(destination unreachable)」——ICMPのエラーメッセージそのままをドメイン名に選んだ人物が、Gerhard Rieger です。
彼は1999年に、多数のアドレス型をサポートする netcat の拡張版として socat を作り始めました。
自分のドメインにICMPエラーを冠するセンスは、ただのネタではないでしょう。
ネットワークの「境界」や「到達不能」という概念に対して、逆に橋を架けることを生業にしてきた人間の自己紹介に読めます。
netcatという「先祖」
socatを理解するには、まず netcat を知る必要があります。
netcat は1990年代半ば(1995年とも1996年とも言われる)、"Hobbit" という人物によって書かれた小さなツールです。
TCP/UDPの任意のポートに接続し、標準入出力とつなぐ——それだけのことを、恐ろしく汎用的に実装しました。
Unixパイプの哲学を、ネットワーク越しに延長したような存在です。
socatは netcat のより複雑な変種と位置付けられています。規模が大きく、より柔軟で、特定のタスクに合わせて設定しなければならないオプションが多いです。
それは欠点ではなく、設計の違いです。
「アドレス」という抽象化
socatの設計思想の核心は、すべてのI/Oエンドポイントを「アドレス」という統一概念で扱うことにあります。
socat <アドレス1> <アドレス2>
この2項の構造は単純に見えますが、「アドレス」の内側には驚くほど多様なものが詰まっています。
TCPソケット、UDPソケット、Unixドメインソケット、ファイル、パイプ、標準入出力、シリアルデバイス、PTY(仮想端末)、TUNデバイス、SSL/TLSコネクション、プロセス実行——これらがすべて同じ文法で記述できます。
netcatがTCP/UDPに特化した「スイスアーミーナイフ」だとすれば、socatは「任意の通信媒体を2点間でつなぐ汎用リレー」です。この差は小さくありません。
インストール
Slackwareでは、n/(ネットワーク系パッケージ)スロットに公式パッケージとして収録されています。
Slackware-currentであれば最新版が収録されています。本記事執筆時点(2026年7月)では version 1.8.1.3 が収録されています。
# バージョン確認(表示されるバージョンはお使いの環境によって異なります) socat -V socat by Gerhard Rieger and contributors - see www.dest-unreach.org socat version 1.8.1.3 on Jun 26 2026 14:31:59 running on Linux version #1 SMP PREEMPT_DYNAMIC ..., release 6.18.37, machine x86_64 features: #define WITH_STDIO 1 #define WITH_OPENSSL 1 #define WITH_TUN 1 #define WITH_PTY 1 #define WITH_EXEC 1 #define WITH_UNIX 1 #undef WITH_READLINE ... (コンパイル時の有効・無効な機能フラグが続く)
ビルド日時(on Jun 26 2026 14:31:59 の部分)はお使いの環境によって異なります。
socatには本体のほかに、2つの付属ツールが同梱されています。
filan
プロセスが開いているファイルディスクリプタを解析するツールです。
FD(File Descriptor)番号・種別(chrdev/socket等)・デバイス番号・inode・パーミッション・タイムスタンプ・端末ウィンドウサイズなど、各FDの詳細情報を一行で出力します。
引数なしで実行すると、filan プロセス自身のFD(シェルから引き継いだ stdin/stdout/stderr)を表示します。
filan FD type device inode mode ... 0: chrdev 0,26 3 020620 ... /dev/pts/0 ... poll: OUT 1: chrdev 0,26 3 020620 ... /dev/pts/0 ... poll: OUT 2: chrdev 0,26 3 020620 ... /dev/pts/0 ... poll: OUT
FD 0・1・2(stdin/stdout/stderr)がいずれも /dev/pts/0(疑似端末)に接続されていることが読み取れます。
socatと組み合わせる場合、稼働中のsocatプロセスのFDは /proc/<PID>/fd/ を参照するのが正確です。
filan はあくまで自プロセスのFDを表示するツールです。
socatのEXECアドレスと組み合わせて、子プロセス側から呼び出すことでsocatが用意したFDの内容を確認できます。
# socatのPIDを調べてFD一覧を確認する(/proc経由) ls -la /proc/$(pgrep socat)/fd/ # socatのEXECで filan を呼び出し、子プロセス側のFD構成を確認する # filan の出力は一行が非常に長いため、受信側でリダイレクトして確認するとよい socat TCP4-LISTEN:19000,fork EXEC:filan # 別ターミナルから接続して filan の出力を受け取る(filan 終了後に接続が閉じる) socat - TCP:127.0.0.1:19000
ポートフォワードやUnixソケット橋渡しで「本当に期待通りのFDが開いているか」を確認するのに有用です。
filanを初めて実行したとき、自分のシェルのFD構成がこれほど詳細に見えることに素直に驚きました。
procan
プロセスの実行環境を網羅的に出力するツールです。
PID・PPID・制御端末・セッションID・UID/GID・umask・リソース制限・Cの型サイズ・ネットワークインターフェース一覧まで表示します。
procan process id = 1596 process parent id = 1576 controlling terminal by /proc/<pid>/: "/dev/pts/0" user id = 1000 effective user id = 1000 umask = 0022 ... open files 1024 4096 ... IP INTERFACES 1: lo 2: eth0 3: tailscale0
socat TCP-LISTEN:8023,fork,su=nobody EXEC:/bin/bash のように権限を落として実行した場合、子プロセス側で procan を実行することで effective user id が実際に nobody になっているかを確認できます。
また open files の上限(デフォルト1024)は、fork で多数の接続を扱う場合のボトルネックになり得るため、確認しておくとよいでしょう。
procanがネットワークインターフェース一覧まで出力することは、実際に使うまで知りませんでした。
権限降格が正しく機能しているかを確認するには、以下のように socat の中から procan を呼び出すのが手軽です。
# 権限降格が正しく行われているかを確認する例 # 接続後のシェルで procan を実行して effective user id を確認する # (19999は任意の未使用ポート番号) socat TCP4-LISTEN:19999,fork,su=nobody EXEC:procan # 別ターミナルから接続して出力を確認する socat - TCP:127.0.0.1:19999
主なアドレス型
socatで指定できる主なアドレス型を示します。これがそのままsocatの「できること一覧」にもなっています。
| アドレス型 | 説明 |
|---|---|
TCP:host:port | TCPクライアント接続(IPv4/IPv6自動選択) |
TCP-LISTEN:port | TCPサーバー(待受・IPv4/IPv6環境依存) |
TCP4-LISTEN:port | TCPサーバー(IPv4限定・bindと組み合わせる場合はこちらを推奨) |
TCP6-LISTEN:port | TCPサーバー(IPv6限定) |
UDP:host:port | UDPクライアント |
UNIX-CONNECT:path | Unixドメインソケット(クライアント) |
UNIX-LISTEN:path | Unixドメインソケット(サーバー) |
STDIO / - | 標準入出力 |
EXEC:cmd | コマンドを実行してその入出力に接続 |
OPENSSL:host:port | SSL/TLSクライアント接続 |
PTY | 仮想端末(シリアル機器エミュレーション等) |
TUN:addr/mask | TUNデバイス(VPN構築用途) |
PIPE:path | パイプ(path指定時は名前付きパイプ/FIFO、省略時は無名パイプ) |
GOPEN:path | ファイルをオープン(種別を自動判別) |
基本的な使い方
netcat代わりに使う
最もシンプルな使い方は、netcat の代替としてTCP接続を確認することです。
- が標準入出力を意味します。
# example.comのport 80に生TCPで接続して標準入出力と中継する(疎通確認用) # 接続後にHTTPリクエストを手入力できる(例:GET / HTTP/1.0 と入力してEnterを2回) socat - TCP:example.com:80 # SSL/TLS接続(verify=0は接続先サーバーの証明書検証を無効にする・テスト用途) socat - OPENSSL:example.com:443,verify=0
TCPポートフォワード
fork オプションを付けると、接続のたびに子プロセスをforkして複数の接続を同時に処理できます。
これがsocatをデーモンとして使う際の基本パターンです。
# ローカルの8080番ポートへの接続を、192.168.1.10の80番ポートに転送する socat TCP-LISTEN:8080,fork TCP:192.168.1.10:80 # ローカルの8080番への平文TCP接続を受け付け、転送先へはSSLで接続する(SSLアップグレード) socat TCP-LISTEN:8080,fork,reuseaddr OPENSSL:192.168.1.10:443,verify=0
TCPをUnixドメインソケットへ橋渡し
TCPとUnixドメインソケットを橋渡しする用途でよく使われます。
ただし、/var/run/docker.sock をTCPでネットワークに公開することは、認証なしでホストのroot権限をネットワーク越しに渡すに等しい操作です。信頼できるネットワーク内、またはループバックアドレスに限定して使用してください。
# TCPの2375番ポートをDockerのUnixソケットに橋渡しする # ※ セキュリティ上、外部ネットワークには絶対に公開しないこと socat TCP4-LISTEN:2375,fork,bind=127.0.0.1 UNIX-CONNECT:/var/run/docker.sock
シリアルポートをTCPに接続する
PTYやシリアルデバイスを扱える点が、netcatにはないsocatの強みです。
組み込み機器やシリアルコンソールをネットワーク越しに操作したい場合に便利です。
# /dev/ttyUSB0(115200bps)をTCPの5000番ポートに接続する socat TCP-LISTEN:5000,fork /dev/ttyUSB0,raw,b115200
仮想シリアルポートのペアを作る
PTYアドレスを2つ組み合わせると、仮想シリアルポートのペアを作成できます。
シリアル通信を必要とするソフトウェアのテストや、実機のないデバッグ環境の構築に使えます。
# 仮想シリアルポートのペアを作成する(-d -d は詳細ログを表示するオプション) # 割り当てられた /dev/pts/N のパスが -d -d のログ出力中に表示される socat -d -d PTY,raw,echo=0 PTY,raw,echo=0 # link= オプションで固定パスのシンボリックリンクを作ると扱いやすい # /tmp/ttyV0 と /tmp/ttyV1 として参照できる socat PTY,raw,echo=0,link=/tmp/ttyV0 PTY,raw,echo=0,link=/tmp/ttyV1
SSL/TLSサーバーを立てる
証明書さえあれば、socatだけでSSL/TLSサーバーを起動できます。
Webサーバーを用意せずにTLS接続を検証したい場合に重宝します。
server.pem は証明書と秘密鍵を1ファイルに結合したもので、以下のように作成できます。
# 自己署名証明書と秘密鍵を生成して server.pem に結合する(テスト用途) openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \ -subj "/CN=localhost" cat cert.pem key.pem > server.pem
server.pem を用意したら、以下のコマンドでSSLサーバーを起動できます。
# server.pem(証明書と秘密鍵を結合したファイル)を使ってSSLサーバーを起動する # OPENSSL-LISTEN が正式なアドレス型名(SSL-LISTEN はエイリアス) # verify=0 はクライアント証明書の検証(相互TLS)を要求しないという意味 # STDIO を指定するとターミナルがクライアントと直結する(接続確認・手動応答用) # 実用的なサービスには EXEC:cmd や TCP:host:port を使うこと socat OPENSSL-LISTEN:4433,cert=server.pem,verify=0,fork STDIO
TUNデバイスで簡易VPNを構成する
TailscaleのようなVPNツールを使わなくても、socatのTUNアドレスを使えば2ホスト間に仮想ネットワークを張れます。
UDPで接続するため、TCPのオーバーヘッドがなく、トンネリングに適しています。
ただし、TUNアドレスは Linux専用 で root権限が必要 です。
また、この構成はトンネル内のデータを暗号化しません。
インターネット越しに使う場合はDTLSを使うか、別途暗号化を施してください。
# サーバー側:UDPの11443番ポートで待受し、TUNデバイス(192.168.255.1/24)を作成する # root権限で実行する socat -d -d UDP-LISTEN:11443,reuseaddr TUN:192.168.255.1/24,up # クライアント側:サーバーに接続し、TUNデバイス(192.168.255.2/24)を作成する # root権限で実行する # ※ 203.0.113.1 はサーバー側のグローバルIPアドレスに置き換える socat -d -d UDP:203.0.113.1:11443 TUN:192.168.255.2/24,up
プロセスの出力をTCPで転送する
EXECアドレスを使うと、コマンドを実行してその標準入出力をソケットに接続できます。
syslogをリモートに転送したり、スクリプトの出力を別ホストで受け取ったりする用途に使えます。
# ローカルコマンドの出力をリモートホストの9999番ポートに送り続ける # -u(unidirectional)で片方向転送を明示する。接続終了後に残る tail -f は pkill tail で後始末する # ※ /var/log/messages は環境によって /var/log/syslog 等に異なる場合がある # ※ 192.168.1.20 はログ受信サーバーのIPアドレスに置き換える socat -u EXEC:'tail -f /var/log/messages' TCP:192.168.1.20:9999 # リモートからの接続に対して、接続のたびにシェルを起動して提供する # (GNU netcatには -e オプションがないため socat で代替する用途) # ※ セキュリティ上、信頼できるネットワーク内でのみ使用すること # ※ root で実行すると root シェルが公開される。必ず su= で権限を落とすこと socat TCP-LISTEN:8023,fork,su=nobody EXEC:/bin/bash
ファイルをネットワーク経由で転送する
scpやrsyncが使えない環境での簡易ファイル転送にも使えます。
# 受信側を先に起動しておく # creat,trunc で新規作成・既存ファイルは上書きする # fork を付けていないため1接続を受信して終了する(1回限りの転送用) socat TCP-LISTEN:8888 OPEN:received.tar.gz,creat,trunc # 受信側の起動を確認してから送信側を実行する # 送信完了後に socat が EOF を伝播して受信側も終了する # ※ 192.168.1.30 は受信側のIPアドレスに置き換える socat OPEN:archive.tar.gz TCP:192.168.1.30:8888
便利なオプション
| オプション | 説明 |
|---|---|
-d | 詳細ログを表示(最大4つまで重ねて詳細度を上げられる:-d -d -d -d) |
fork | 接続のたびに子プロセスをforkして並列処理する(TCPサーバー用途) |
reuseaddr | 再起動時のポート競合を解消し、TIME_WAIT中でも即座に再度待受できるようにする。fork と組み合わせる場合は実質必須 |
verify=0 | クライアント側では接続先の証明書検証を無効化、サーバー側ではクライアント証明書の要求(相互TLS)を無効化する(テスト用途) |
crnl | アドレスオプションとして指定し、そのアドレスへの書き込み時にLFをCR+LFに変換する(例:socat - TCP:192.168.1.100:25,crnl でSMTPサーバーを手入力デバッグ) |
raw,echo=0 | 端末をrawモードにしてエコーを無効にする(PTY使用時) |
max-children=N | 同時に起動する子プロセス数の上限を設定する |
なお、Slackwareの公式ビルドでは #undef WITH_READLINE となっており、readline サポートが無効です。
socat - TCP:... のようなインタラクティブ接続で上矢印キーによるコマンド履歴は使えません。
readline が必要な場合はソースから自前ビルドする必要があります。
四半世紀の開発、一人の手で
ソースリポジトリを見ると、コミットログはほぼすべて Gerhard Rieger 一人の名前で埋まっています。
UDP-Lite対応、DCCPソケット、TUNデバイスサポート、VSOCK——どれも彼が一人で実装してきました。
2025年12月には version 1.8.1.0 がリリースされ、新しいアドレス型(TEXTとSTALL)が追加されました。
その後も修正リリースが続き、2026年6月には SOCKS5リプライパーサーのヒープバッファオーバーフロー(CVE-2026-56123)を修正した version 1.8.1.3 がリリースされています。
1999年から数えると四半世紀を超えた今も、Rieger はコードを書き続けています。
一つの事件:Diffie-Hellman素数問題
そのような長い歴史の中で、socatはひとつ不穏な話を抱えています。
2016年2月、Santiago Zanella-Beguelin と Microsoft Vulnerability Research の協力のもと、Gerhard Rieger 自身が「Socat security advisory 7」として、OpenSSL実装にハードコードされた1024ビットのDHパラメータ(p)が素数ではなく合成数であることを公表しました。
問題の合成数パラメータは前年(2015年)に Zhigang Wang(当時Oracle社員)が提供したパッチで導入されたものです。
Wangのパッチを取り込んだのはRieger自身であり、なぜ素数検証が行われなかったのかは明らかにされていません。
なお、アドバイザリ公表の当日にWangのGitHubアカウントと個人サイトが削除されたことが記録されていますが、その理由も不明のままです。
素数が必要な場所に合成数が意図せず混入したとは考えにくいとして、バックドアを埋め込むための意図的な改竄ではないかという疑惑が持ち上がりました。
この問題は version 1.7.3.0 と 2.0.0-b8 に影響し、後続の 1.7.3.1 と 2.0.0-b9 で修正されています。
なお、TLS 1.3 では静的な DHパラメータを使用しない設計になっているため、現在の環境でこの問題が直接影響することはなく、歴史的な事案として記録される性質のものです。
真相は藪の中のままですが、この事件が問うているのは「外部から提供されたパッチを、素数検証という基本的な確認なしに取り込んでしまった」という点です。
一人で開発を続けるプロジェクトにおいて、外部コントリビューションのレビューをどう担保するかは、今も解決されていない課題です。
利用する際はリリースノートとセキュリティアドバイザリを確認する習慣を持っておくとよいでしょう。
netcatとの比較
| 機能 | netcat | socat |
|---|---|---|
| TCP / UDP | ○ | ○ |
| SSL / TLS | △(版による) | ○(ネイティブ対応) |
| Unixドメインソケット | △ | ○ |
| 並列接続(fork) | △ | ○ |
| シリアルデバイス / PTY | × | ○ |
| TUNデバイス | × | ○ |
| プロセス実行(EXEC) | △(実装依存・GNU版は非対応) | ○ |
| コマンドの簡潔さ | ○ | △(オプションが多い) |
Slackwareに収録された意味
socat は少なくとも2020年頃から Slackware の n/ スロットに公式パッケージとして収録されており、現在も継続してメンテナンスされています。
Slackware の公式パッケージに選ばれるツールには、ある種の「時代を超えた実用性」があります。
流行りのエコシステムに依存せず、シンプルな設計で長く生き残るもの——socatはまさにその条件を満たしています。
/etc/inittab に一行書けばサービスが立ち上がる世界と、「2点をつなぐ」という原始的な抽象でネットワークを操る道具は、よく似た精神を持っています。
実際の場面でも、socatは地味に活躍します。
PTYで仮想シリアルポートのペアを作って組み込みソフトの動作を確認したいとき、SSL証明書の更新後に接続確認を手軽に済ませたいとき——専用ツールを立ち上げるほどでもない作業を、一行で片付けてくれます。
そのスタンスが、Slackwareの思想と重なります。
参考リンク
公式サイト(dest-unreach.org)はHTTPのみの提供です。
- socat 公式サイト(dest-unreach.org)
- socat マニュアル(公式ドキュメント)
- Building TUN based virtual networks with socat(公式)
- Socat security advisory 7 — DH modulus not prime(公式)
- oss-security: Socat security advisory 7(Openwall)
- netcat — Wikipedia
- socat1 ソースリポジトリ(GitHub)
まとめ
dest-unreach.org というドメインは、ICMPの「到達不能」通知を指します。
しかし socat は、その「到達不能」とされてきた場所——異なるプロトコル、異なる通信媒体の間——に、静かに橋を架け続けてきました。
まずは socat -V でバージョンと有効な機能一覧を確認するところから始めてみてください。
どれだけ多くの機能がコンパイルされているか、眺めるだけでも楽しいはずです。