
2026/05/30 19:51
Openrsync: OpenBSD チームによる rsync の実装
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
中核となるメッセージは、openrsync が BSD 許 Cano の下で実装され、OpenBSD ベースシステムに公式にマージされており、厳密な移植性を確保しているという点である。当初は
rpki-client プロジェクト向けに開発され、NetNod や IIS.SE などの組織からの資金援助を受けており、パフォーマンスとクロスプラットフォームの整合性のために C で約 10,000 行書かれている。このソフトウェアは標準的な configure と make コマンドによるインストールが可能であり、既存の rsync インストールと競合しない。セキュリティが最重要であり、OpenBSD の固有の特徴である pledge(2) を利用してシステム操作を制限し、特に MD4 ハッシュシードが time(3) ではなく arc4random(3) を使用する際に、ファイルシステムへのアクセスを unveil(2) で制限する。標準クライアントとは異なり、openrsync は暗号化のために protocol 27 のサポートを厳密に要求し、コマンドライン引数の子集合のみを受け付ける。効率性については、ディレクトリをファイル前に処理するために共有されソートされたメタデータリストを利用して達成され、Adler-32 および MD4 を含むハッシュ戦略を用いる。技術的には socketpair(2) パイプまたはネットワークソケット上で通信を行い、最新の rsync(3.1.3 でテスト済み)との互換性を保ちつつ、特定のマニュアルページ (rsync(5), rsyncd(5), および openrsync(1)) による標準的なドキュメントを提供する。本文
openrsync システム解説
概要
- ベースシステム: OpenBSD ベース統合システム
- コントリビューション: OpenBSD へのパッチは
宛てにメール送信してくださいtech@openbsd.org - 役割: OpenBSD バージョンと移植性を確保するためのアダプタ(グルー)コードのみを含む
- ライセンス: **BSD(ISC ライセンス)**元の rsync 実装
- 互換性:
- 最新の rsync と互換性あり(テスト環境:バージョン 3.1.3)
- プロトコルバージョン 27 をサポートする任意のバージョンでも動作
- サポート対象:
- 公式:OpenBSD
- 他 UNIX システムでもコンパイル・動作可能(詳細は「移植性」参照)
- 文書情報:
- 公式ドキュメント:マニュアルページ(
、rsync(5)
、rsyncd(5)
)openrsync(1) - 「アーキテクチャ」と「アルゴリズム」の節は開発者向けの説明であり、公式文書ではありません
- 公式ドキュメント:マニュアルページ(
プロジェクト背景
- 起源: OpenBSD 用 RPKI バリデーター
プロジェクトの一部として記述rpki-client(1) - 資金源: NetNod, IIS.SE, SUNET, 6connect より提供
インストール方法
基本手順(最新 UNIX システム)
以下のコマンドを実行することでインストールできます。既存の rsync と併存可能です。
% ./configure % make # make install
- 結果:
ユーティリティおよびマニュアルページがインストールされるopenrsync - アップグレード時は上記手順を再実行してください
サーバー利用設定
以下のように
--rsync-path=openrsync を指定して実行します。
% rsync --rsync-path=openrsync src/* dst % openrsync --rsync-path=openrsync src/* dst
重要: 両方のツール(openrsync と標準 rsync)を使用する場合は、共通のコマンドラインフラグを必ず利用してください(一覧は
openrsync(1) を参照)。
アルゴリズムとブロック交換
アルゴリズム詳細
- 参照文献:
- Andrew Tridgell & Paul Mackerras: "The rsync algorithm"
- Andrew Tridgell 博士論文: "Efficient Algorithms for Sorting and Synchronization"(ソースコード理解に推奨)
- 構成要素:
- 送信側 (sender): ソースファイルを管理
- 受信側 (receiver): 宛先を管理
ブロック交換のフロー
ファイルリスト(名前・モード・変更時刻など)に基づき、両側でソートされた順序で処理します。
1. シンボリックリンク
- 送信側への更新要求が発生しません
- メタデータを確認し、正しい対象を修正
2. ディレクトリ
- 存在しない場合は作成しますが、送信側への更新要求は発生しません
3. 通常ファイル(regular file)
処理手順:
- 最新判定: サイズと変更時刻が一致すれば最新とする
- ブロック分割: ファイルを固定サイズブロックに分割(倍数でない場合は最終ブロックが小さくなる。空の場合はゼロブロック)
- ハッシュ計算(
実装):hash.c- 1 つ目:Adler-32(4 バイト・高速)
- 2 つ目:MD4(16 バイト・低速)
- 送信と照合(
実装):block.c- 受信側はハッシュを全て送信側に送る
- 送信側は各バイトに対し高速ハッシュを計算し、一致を探る
- 一致した場合は低速ハッシュで再確認(MD4 で完全一致か判定)
- データ転送:
- 一致点以前のデータをストリームとして受信側に送信
- ブロック識別子またはゼロ値を送信
- 受信側はストリームを破棄し、指定されたブロックのみコピー
- ファイル末尾の場合:
- ストリーム一括送信
- 全体を MD4 ハッシュ計算(一致すれば完了)
ブロックサイズ
- 計算式: ファイル全体の平方根(丸め上げ)
- 制限事項:
- 最小ブロックサイズ:700 バイト以上
- 計算結果が整数でない場合、不明な理由により8 の倍数に切り上げられる
- 例示定数としての「3」を使用する場合は
ceil(sqrt(3))
アーキテクチャ
プロセス構成
セッションは以下の 2 つのプロセスに分かれます。
- クライアントプロセス: ユーザー起動
- サーバープロセス: SSH を介したオンデマンド起動、または永続的に動作するネットワークデーモン
リストと役割の判定
コマンドライン引数から送信側/受信側を自動判定します。
# クライアントが送信側 (ローカルデータをサーバーへ) openrsync path/to/source host:destination # クライアントが受信側 (サーバーデータを受け取り保存) openrsync host:source path/to/destination
ホスト表記方法
- ローカル:
../path/to/source ../another - リモートサーバー:
host:path/to/source :path/to/another - リモートデーモン:
rsync://host/module/path ::another
制約: ソースと宛先はすべてローカル、または同一ホスト上のすべてがリモートである必要があります(両方リモートは非推奨)。
- リモートサーバーの場合: クライアントがフォークし、SSH でサーバー版を起動。双方は
パイプで通信。socketpair(2) - リモートデーモンの場合: フォークせず、ネットワークソケット (
) で接続。socket(2)
サーバーコマンドライン
SSH セッション上での起動やデモンモードでも以下の形式が使用されます。
openrsync --server [--sender] . files...
:受信モードは単一宛先ディレクトリ、送信モードはソースファイル一覧files- 句点(
)の存在理由は未確定.
実装担当ファイル
| 機能 | ファイル | 説明 |
|---|---|---|
| メイン制御 | | ローカル性判定・ルート処理 |
| サーバー機能 | | サーバー向けクライアントロジック |
| サーバー本体 | | サーバー実行主体 |
| ネットワーク | | デーモン向けクライアントソケット処理 |
| 子プロセス管理 | | リモートサーバー起動管理 |
| 受信処理 | | ファイル宛先の管理 |
| 送信処理 | | ソースファイルの管理 |
通信プロトコルと実装詳細
- 使用プロトコル:
(デーモン接続時はrsync(5)
の手話式プロトコル併用)rsyncd(5) - 受信側の役割:
- 送信側にブロックメタデータをアップロード
- 送信されたデータを書き込む
- 処理制御:
- マルチタスク動作: アップローダー兼ダウンローダーとして実装
- 実装ファイル:
- アップローダー:
uploader.c - ダウンローダー:
downloader.c
- アップローダー:
- 制御手法:イベントループと有限状態機(FSM)で入力/ディスク準備状況に応じた動作を管理
openrsync と標準 rsync の違い
- rsync: 「ジェネレーター」という別モードが存在し、独立プロセスとしてフォークして通信。
- openrsync: ジェネレーターと受信側を1 つのプロセスに統合。高速応答のためイベントループを使用。
セキュリティ
OpenBSD のネイティブ機能を活用した防御策を採用しています。
pledge(2) と unveil(2)
| 機能 | 役割 | 制限内容・例 |
|---|---|---|
| pledge(2) | システム操作権限の制限 | - 受信側:ディスク書き込みのみ許可 - dry-run モード ( ): 除外- デーモン:DNS/ネットワークアクセス必須 |
| unveil(2) | ファイルシステムアクセス範囲の限定 | - root プライビレッジ不要 - 脱出(break out)防止 - 受信側で目的地ディレクトリ内の対象のみアクセス可能 |
- chroot(2) との違い:
/pledge
は root でも動作し、より軽量な制限が可能。unveil
ハッシュ計算の安全性
- サーバーモードでのみ適用
- シード値生成のため**
**を使用(時間ベースのarc4random(3)
不使用)time(3)
移植性
公式サポート OS は OpenBSD ですが、他 OS への移植が積極的に行われています。
サポート状況と強制テスト
- 対象 OS: Linux (glibc, musl), FreeBSD, NetBSD, Mac OS X, OmniOS
- アーキテクチャ: x86_64, aarch64, s390x
- 品質保証: GitHub CI メカニズムによる自動テストで対応が強制
移植上の課題
- 核心的な問題: OpenBSD の
およびpledge(2)
との適合性確保unveil(2)- これらの機能が欠けると、公開ネットワークから任意のデータを受け入れるリスクが生じる
- (代替案として FreeBSD の Capsicum などが考えられるが、複雑度が高い)
- Linux: セキュリティインフラが複雑で、適切にセキュア化するには専門的な知識が必要
コード量と信頼性について
openrsync は約 10,000 ラインの C コードですが、以下の問いかけと共に提供されています。
「私に間違いがないことを信じていただけるでしょうか?」