Libzmq を使用した Vsock の活用

2026/09/08 5:24

Libzmq を使用した Vsock の活用

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

Linux カーネルバージョン 4.8 以降で利用可能であり、VMware が VMCI として元々開発した AF_VSOCK は、32 ビットのコンテキスト ID(CID)およびポートを用いて、ゲスト VM とホストハイパーバイザーの間、あるいは同じホスト上の複数つのゲストの間での通信を可能にする。予約されている CID の値には

VMADDR_CID_ANY
VMADDR_CID_HYPERVISOR
および
VMADDR_CID_LOCAL
(カーネル 5.6 で追加)が含まれる。ポートも 32 ビットであり、1024 未満のポートにはルート権限が必要である。VSOCK はストリーム(TCP 類似)およびデータグラム(UDP 類似)の両方の機能をサポートする。AWS は Nitro Enclaves に VSOCK を使用している。ZeroMQ (
libzmq
) は以前 VMCI をサポートしていたが、GitHub の Pull Request #4822 で提案された実装を通じてネイティブな VSOCK サポートを持っておらず、
libzmq
に VSOCK を統合することで、Python、Java、Ruby および他の言語で Curve 認証や一般的なメッセージパターン(req/rep、pub/sub)といった標準的なパターンの利用が可能となる。VM がない環境でのテストは、Linux 5.6+ でループバック CID(例:
vsock://@
)にバインドするか、QEMU/libvirt に
vhost-vsock-pci
デバイスを設定することで可能である。asyncio および Curve などのセキュリティ機能を利用する本番用途には、
libzmq
バージョン 4.0 以上の使用が必要であり、例では認証が成功した場合に
ZAP reply code=b'200' text=b'OK'
が返され、失敗した試行では
DENIED (CURVE)
および
text=b'Unknown key'
が得られる。GitHub には最新の安定版
libzmq
コミットに対するビルドが可能であるフォーク
pyzmq-vsock
が公開されており、ドキュメントは https://github.com/zeromq/libzmq/blob/master/doc/zmq_vsock.adoc に存在する。

本文

AF_VSOCK と libzmq での実装ガイド

概要

AF_VSOCK は Linux カーネル 4.8 以降に導入された、仮想マシン(ゲスト)とハイパーバイザー(ホスト)間通信用のソケットアドレスファミリーです。

特徴

  • VMware 由来: 元々は「VMCI」として開発されました。
    AF_INET
    AF_UNIX
    に相当します。
  • 通信対象:
    • ホスト上の仮想マシン(ゲスト)同士
    • ゲストと基盤となるハイパーバイザー(ホスト)間
  • 機能: Unix ソケットの見た目ですが、TCP/UDP のようにアドレスとポートを設定でき、ストリーム型またはデータグラム型通信をサポートします。
  • 代替手段: シリアルポート利用(例:QEMU Guest Agent)に代わる高速な通信手段です。

詳細は Linux Vsock man ページ を参照してください。


アドレスとポートの構成

AF_VSOCK は 32 ビットのアドレス(コンテキスト ID: CID)を使用します。

リザーブ済み CID

  • VMADDR_CID_ANY
  • VMADDR_CID_HYPERVISOR
  • VMADDR_CID_LOCAL
    (Linux カーネル 5.6 以降)
  • VMADDR_CID_HOST

ポート番号

  • 32 ビットのポートを割り当て可能。
  • 1024 未満: ループバック用またはプリビレッジポートとして使用する場合、root アクセスが必要です(TCP/UDP と同様)。
  • 同じ CID でも異なるポートを使えば、複数の通信セッションを構築できます。

サポート状況とエコシステム

AF_VSOCK は以下の言語で公式にサポートされており、SDK が存在します。

  • Python
  • C
  • Go
  • Rust

主要なライブラリ・ドキュメント

ライブラリ/リポジトリリンク
socat (Vsock)stefano-garzarella.github.io
tokio-vsock (Rust)github.com/rust-vsock/tokio-vsock
Linux VM sockets in Gomdlayher.com
Python
socket.AF_VSOCK
docs.python.org
vsock リポジトリgitlab.com/vsock/vsock
AWS Nitro Enclavesaws.amazon.com/enclaves

libzmq (ZeroMQ) でのサポート

背景と対応策

libzmq は

poll
,
recv
,
send
などの低レベル操作を提供する基盤ライブラリですが、元々 VSOCK のバインディングはありませんでした。VMCI コードをほぼそのままコピーすることで VSOCK 対応を実現しました。

追加された利点

  • 多言語での利用: Python, Ruby, Node.js, Perl, Java など、libzmq バインドが存在する全言語で AF_VSOCK を利用可能。
  • 高度な機能の活用: ZeroMQ 固有の機能(Curve 認証、REQ/REP パターンなど)を VSOCK 上でそのまま使用可能。

導入方法

正式な安定版リリース前のため、フォーク版

pyzmq
(
pyzmq-vsock
) を利用します。

インストール例 (Python):

python3 -m venv venv
venv/bin/pip install \
    https://github.com/remijouannet/pyzmq-vsock/releases/download/27.2.0.dev0%2B4649337/pyzmq-27.2.0.dev0+4649337-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl

詳細ドキュメント: libzmq VSOCK ドキュメント (AOC)


Hello World 例:VSOCK ループバックテスト

Linux 5.6 以降では、仮想マシンを起動せずともループバック CID (

VMADDR_CID_LOCAL
) を使用して動作を確認できます。ZeroMQ の
@
スケマを使用して、ローカルループバックアドレスに直接バインド可能です。

環境構築

1. モジュールのロード

ループバックデバイスがない場合は、以下をロードしてください。

sudo modprobe vsock_loopback

2. 仮想マシンでの実装(オプション)

本番環境では

vhost-vsock-pci
デバイスを追加するか、libvirt の設定で
vsock
を有効にします。

QEMU 設定例:

/usr/local/bin/qemu-system-x86_64 \
    -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=$CID \
    ...

サーバーとクライアントの実装

1. REP ソケット(サーバー)

vsock://@:5555 にバインドし、クライアントから

b"Hello"
を受け取ると
b"World"
で返信します。

cat <<EOF > rep.py
import time
import zmq

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("vsock://@:5555")

while True:
    # クライアントリクエストの受信
    message = socket.recv()
    print(f"Received request: {message}")

    # 処理シミュレーション
    time.sleep(1)

    # レスポンズ送信
    socket.send(b"World")
EOF

2. REQ ソケット(クライアント)

サーバーに接続し、5 回分の

b"Hello"
を送信して返信を受信します。

cat <<EOF > req.py
import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
print("Connecting to hello world server…")
socket.connect("vsock://@:5555")

for request in range(5):
    print(f"Sending request {request} …")
    socket.send(b"Hello")
    
    # 返信の取得
    message = socket.recv()
    print(f"Received reply {request} [ {message} ]")
EOF

3. 実行結果の確認

サーバーをバックグラウンドで起動し、クライアントを実行します。

サーバー実行:

venv/bin/python3 rep.py &
# 出力: [1] 88069 (プロセス ID など)

クライアント実行:

venv/bin/python3 req.py 
# 出力例:
Connecting to hello world server…
Sending request 0 …
Received request: b'Hello'
Received reply 0 [ b'World' ]
... (5 回のループ完了)

Curve 認証と Asyncio の使用例

本番環境では、非同期処理(Asyncio)と Curve 認証 が必須となります。以下の例は ZeroMQ のセキュリティベストプラクティスに基づいています。

キー生成スクリプト

Curve 用の公開鍵・秘密鍵ペアを JSON ファイルに出力します。

#!/usr/bin/env python
import json
import zmq
import zmq.auth

keys_file = "keys.json"

client_pub, client_priv = zmq.curve_keypair()
client2_pub, client2_priv = zmq.curve_keypair()
server_pub, server_priv = zmq.curve_keypair()

with open(keys_file, "w") as f:
    json.dump(
        {
            "client": [client_pub.decode(), client_priv.decode()],
            "client2": [client2_pub.decode(), client2_priv.decode()],
            "server": [server_pub.decode(), server_priv.decode()],
        },
        f, sort_keys=True, indent=4
    )

サーバー実装 (REP) - 非同期 + Curve 認証

#!/usr/bin/env python
import asyncio
import json
import logging
import zmq
from zmq.asyncio import Context
from zmq.auth.asyncio import AsyncioAuthenticator

LOGGER = logging.getLogger(__name__)

async def run(keys: dict) -> None:
    ctx = Context.instance()
    
    # 認証機構の開始
    auth = AsyncioAuthenticator(ctx)
    auth.start()
    # クライアント(ドメイン "*")の許可
    auth.certs["*"] = {keys["client"][0].encode(): True}

    server = ctx.socket(zmq.REP)

    # 認証キーの設定 (バインド前に設定必須)
    server.curve_publickey = zmq.utils.z85.decode(keys['server'][0])
    server.curve_secretkey = zmq.utils.z85.decode(keys['server'][1])
    server.curve_server = True 
    server.bind('vsock://@:9000')

    msg = await server.recv()
    LOGGER.info(f"Received {msg!r}")
    
    if msg == b"Hello":
        LOGGER.info("Ironhouse test OK")
    await server.send(b"World")

    # クリーンアップ
    server.close()
    auth.stop()

if __name__ == '__main__':
    if not zmq.has("vsock") or not zmq.has("curve"):
        raise RuntimeError(f"セキュリティは libzmq バージョン < 4.0 ではサポートされていません。現在のバージョン:{zmq.zmq_version()}")

    logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] %(message)s")
    
    with open("keys.json") as f:
        keys = json.load(f)
        
    asyncio.run(run(keys))

クライアント実装 (REQ) - 非同期 + Curve 認証

サーバーと通信する際に、自身の鍵とサーバーの公開鍵をセットします。

#!/usr/bin/env python
import asyncio
import json
import logging
import zmq
from zmq.asyncio import Context
from zmq.auth.asyncio import AsyncioAuthenticator

LOGGER = logging.getLogger(__name__)

async def run(keys: dict) -> None:
    ctx = Context.instance()
    
    auth = AsyncioAuthenticator(ctx)
    auth.start()

    client = ctx.socket(zmq.REQ)
    
    # 自身の公開鍵と秘密鍵の設定
    client.curve_publickey = zmq.utils.z85.decode(keys['client'][0])
    client.curve_secretkey = zmq.utils.z85.decode(keys['client'][1])

    # サーバーの公開鍵設定 (サーバー側の検証用)
    client.curve_serverkey = zmq.utils.z85.decode(keys['server'][0])
    
    client.connect('vsock://@:9000')

    await client.send(b"Hello")
    reply = await client.recv()
    LOGGER.info(f"Received reply {reply!r}")

    client.close()
    auth.stop()

if __name__ == '__main__':
    if not zmq.has("vsock") or not zmq.has("curve"):
        raise RuntimeError(f"セキュリティは libzmq バージョン < 4.0 ではサポートされていません。現在のバージョン:{zmq.zmq_version()}")

    logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] %(message)s")
    
    with open("keys.json") as f:
        keys = json.load(f)
        
    asyncio.run(run(keys))

実行結果の確認

認証成功時の出力

正しいキーを使用することで通信が成立し、

Ironhouse test OK
が表示されます。

サーバー側ログ:

[DEBUG] Starting
[DEBUG] version: b'1.0', request_id: b'1', domain: '', address: '', identity: b'', mechanism: b'CURVE'
[DEBUG] ALLOWED (CURVE) domain=* client_key=b'HhdIwzo4=a}1F#eL{}rs4C1Hgx.Z4nd#/JqIasmP'
[DEBUG] ZAP reply code=b'200' text=b'OK'
[INFO] Received b'Hello'
[INFO] Ironhouse test OK

クライアント側ログ:

[DEBUG] Starting
[INFO] Received reply b'World'

認証失敗時の出力

不正なキー(または未認証のキー)を使用すると、サーバーが拒否し、クライアントは返信を受け取らない (

No reply
) ことが確認できます。

サーバー側ログ (DENIED):

[DEBUG] DENIED (CURVE) domain=* client_key=b'P4//#^+&*nKTcb]6*u:zy<blBUAX%IaSn=PLNG-/'
[DEBUG] ZAP reply code=b'400' text=b'Unknown key'

クライアント側ログ:

[INFO] No reply: server rejected this client key

同じ日のほかのニュース

一覧に戻る →

2026/09/10 3:15

iPhone デュオ

## Japanese Translation: アップルは、二画面デザインの画期的な初代折りたたみスマートフォン「iPhone Duo」の発売を予定しています。内蔵ディスプレイが 7.6 インチ、外側ディスプレイが 5.4 インチというこのデュアルディスプレイ構成は、どちらも Super Retina XDR テクノロジー、ProMotion(最大 120Hz)、そして最大 3,000 nits のピーク輝度を備えています。開いた状態での 7.6 インチ画面は iPhone 18 Pro Max よりも 50% も大きく、かつこれまで製造された中最薄の iPhone です。折りたたんだ状態ではポケットに収まるサイズのデバイスとなり、外側ディスプレイは iPhone 18 Pro の画面面積の 90% を超えます。本体フレームとヒンジカバーにはグレード 5 タイタンを使用し、IP68(防水・防塵)対応、また内蔵ディスプレイにノアノテクスチャ仕様にすることで反射を軽減しています。 性能は、高度な A20 Pro チップと二重 16 コアニュラルエンジンにより支えられ、集約的な AI タスクを効率的に管理します。これらのワークロードを処理しバッテリー寿命を延長するために、iPhone 初採用のデュアルバッテリーシステムを採用しており、内側ディスプレイでは最大 31 時間の動画再生、外側ディスプレイでは最大 44 時間の再生が可能です。電源供給オプションには、MagSafe ワイヤレス充電と、約 20 分で 50% までの給電可能な有線充電が含まれます。 カメラシステムは、48MP デュアルフュージョン構成(メインカメラと超広角カメラ)、48MP フュージョン遠望レンズ(最大 2 倍の光学的品質ズーム)、そして 12MPセンターステージ前面カメラを備えています。このハードウェアにより、近しい友人との Duo FaceTime、ハンズフリーでグループ写真を撮影する Smart Take、ライブでの外側ディスプレイによる構図表示のための Duo Preview、子供向けの Kid Cue アニメーションなどの新しいソフトウェア機能が実現します。本デバイスは Apple Intelligence と Siri AI を対応しています。 ストレージオプションには 256GB、512GB、1TB、および 2TB の構成が用意されており、eSIM 専用設計によって容量を最大化しています。2026 年 10 月 23 日に apple.com および一部のキャリアで発売予定であり、同時にはリデザインされた折りたたみデバイスの姿勢に最適化された iOS 27 が導入されます。iPhone Duo は技術ハードウェアの新たな基準を設定し、折りたたみデザインと AI インテグレーションを進化させながら、利用者に前例のないワークフローの柔軟性を提供します。

2026/09/09 22:27

Shopify が Tailwind を買収

## Japanese Translation: Shopify は、安定した長期的な据え場所を提供し、主要な商用エコシステム内でのアクティブなメンテナンスを確保することを目的として Tailwind CSS を買収します。この動きにより、両社のミッションが統合され、Tailwind の核心となる強みである「美しいインターフェースを簡素化する」ことと、Shopify の「エージェント型コマース」のビジョンが一致します。週間に 1 億 1000 万回以上のインストール数を持つ Tailwind は、ChatGPT、X、Cloudflare、Reddit、そして Shopify そのものを含む大手企業によって採用されており、すでに Shopify 自身の技術スタックの一部として不可欠な役割を果たしています。買収により、Tailwind 周辺の商用成長は停止し、新規顧客の登録も一時中断されますが、すべての既存ライセンス(Tailwind Plus および ui.sh 含まれる)は引き続き完全サポートされます。特に重要なのは、Tailwind が MIT ライセンスを維持し、開発者の自由を守りつつ、チームが Shopify のサポートの下でコミュニティプロジェクトを主導し続けることです。このパートナーシップにより、Tailwind は Shopify スタックの中核となるコンポーネントとしての将来性が確保され、9 年間のイノベーションに基づき信頼が強化されます。

2026/09/09 3:11

Visa とマスタカードは何をするか? カードネットワークの入門

## Japanese Translation: Visa および Mastercard は、従来の銀行ではなく、安全で両当事者を繋ぐカードネットワークとして機能します。これらはカードを発行することも、製造することも、POS ハードウェアを取り扱うことも、商取引業者(マERCHANT)のオンボーディングを管理することもしません。両者は通信手段を通じて発行者とマERCHANT を接続しており、認証(ルーティングのリクエスト/レスポンス)および清算(最終額面の提出)を行います。カード番号は IP アドレスのように利用されます。日常の決済処理を管理するため、Visa は 1,120 億ドルの流動性を保有しており、2024 年度における最大の daily 決済曝露額は 1,374 億ドルです。 収益は、地域によって異なる手数料分割から得られ、安全な支出や望ましい行動を促進することを目的としています。典型的なアメリカでの取引では、マERCHANT が約 2.5%(MDR)、プロセッサが約 0.35%、発行者銀行が約 2%(インターチェンジ)、Visa が約 0.15%(ネットワークアセスメント)をそれぞれ受取ります。欧州連合では、インターチェンジ手数料は 0.3%に上限が設けられており、これはアメリカモデルと比較して消費者の支払習慣を代替決済手段へと転換させる影響を与えています。 セキュリティは運営の中心です:バージニア州アッシュバーンにある Visa の旗艦オペレーションセンター・イーストでは、地震や時速 270 キロメートル(170 マイル)の風などの災害に耐えるために強化されたデータセンターを使用しており、時速 80 キロメートル(50 マイル)の車両を停止できる水力式bollard が備わっています。ガバナンスは、ブランドの使用、データ要件、紛争手続きを含む包括的な規則書を通じて強制され、違反には月間あたり 25,000 ドルから 100 万ドルまでの罰金が科される場合があります。紛争は 600 ドルの審査料(上訴では 1,000 ドル)がかかる強制仲裁によって解決され、当事者が合意しない場合、Visa は署名やセキュリティ映像などの証拠を頼りに介入します。世界的には、ネットワークは国際的な決済におけるアダプターとして機能し、銀行システム間で資金のルーティングを行い通貨変換を取り扱いながら、重大なペナルティを避けるために厳格な遵守が求められます。

Libzmq を使用した Vsock の活用 | そっか~ニュース