世界を動かす技術を、日本語で。

Openrsync: OpenBSDチームによるrsyncの実装

概要

  • openrsync はOpenBSDベースシステムに統合された BSDライセンスのrsync実装
  • rsyncプロトコル(バージョン27)互換 で、コマンドライン引数は一部のみ対応
  • OpenBSD公式サポート だが、他のUNIX系OSにも移植可能
  • セキュリティ強化 として、OpenBSDのpledge(2)とunveil(2)を活用
  • rsyncとの主な違い やアルゴリズム、アーキテクチャも解説

openrsync概要

  • openrsyncOpenBSD ベースシステムに組み込まれた rsync互換ユーティリティ
  • BSD (ISC) ライセンス 採用、オープンソースプロジェクト
  • rsyncプロトコル27 に対応、rsync 3.1.3で動作確認
  • コマンドライン引数 はrsyncの一部のみサポート
  • OpenBSD が公式サポート対象だが、他UNIX系OSにも移植可能
  • 公式ドキュメント はマニュアルページ(rsync(5), rsyncd(5), openrsync(1))
  • 開発背景 :rpki-client(1)プロジェクトの一環として開発
    • NetNod, IIS.SE, SUNET, 6connect による資金提供

インストール・アンインストール

  • UNIX系OS でのインストール手順
    • ./configure
    • make
    • make install
  • rsyncとの共存 可能、競合なし
  • アンインストールmake uninstallで対応
  • サーバーとしての利用openrsync --rsync-path=openrsync src/* dstなどで起動
  • openrsyncとrsyncの相互運用 は、両方がサポートするフラグを利用

アルゴリズム概要

  • rsyncアルゴリズム送信側(sender)受信側(receiver) で構成
    • 送信側:ソースファイル管理
    • 受信側:宛先ファイル管理
  • ファイルリスト (名前・メタデータ)を共有し、両者でソート
    • ディレクトリ優先順で処理
    • ファイルリストはflist.cで実装
  • ブロック交換 (block exchange)がアルゴリズムの中核
    • receiverがファイルごとに情報をsenderへ送信
    • senderは更新指示に従い、必要なデータブロックを送信
    • 完了後、ファイルが最新化

ブロック交換詳細

  • シンボリックリンク :メタデータのみで更新、データ転送不要
  • ディレクトリ :未存在時のみ作成、データ転送不要
  • 通常ファイル
    • サイズ・mtimeが一致すれば転送不要
    • 一致しない場合、固定サイズブロックごとにハッシュ(Adler-32とMD4)計算
    • receiverがブロックハッシュをsenderへ送信
    • senderは一致するブロックを探索し、差分データのみ送信
    • receiverはデータストリームとブロックでファイルを再構築
    • 新規ファイルは全データ送信
    • 完了後、MD4ハッシュで検証

ブロックサイズ

  • ブロックサイズ はファイルサイズの平方根を切り上げ
  • 最小ブロックサイズ は700バイト
  • 8の倍数 に切り上げる仕様

アーキテクチャ

  • openrsyncセッションクライアントサーバー プロセスに分割
    • クライアント:ユーザーが実行
    • サーバー:リモートホストでssh(1)経由またはデーモンとして実行
  • --server フラグでサーバープロセスを識別
  • 送信/受信モード はコマンドライン引数で自動判別
  • ローカル・リモート判定 :パス指定形式で判断
    • 例:host:path/to/source
    • ソース・宛先が同時にリモートは不可(設計上の制限)
  • リモートサーバーの場合、クライアントがfork(2)してssh経由でopenrsyncを起動
  • ネットワークデーモン の場合はsocket(2)で接続
  • クライアント・サーバー実装 :client.c, server.c, socket.c, child.c
  • プロトコル通信 はrsync(5)、デーモン時はrsyncd(5)も利用
  • 受信側 はアップローダー・ダウンローダーの2役を持ち、イベントループで非同期処理
    • uploader.c:ファイルを開き、ブロックをハッシュ化して送信
    • downloader.c:データ受信、既存ファイルに書き込み

rsyncとの違い

  • rsyncgeneratorプロセス をreceiverとは別にfork(2)して実行
  • openrsyncgeneratorとreceiverを同一プロセス で実装し、イベントループで高速応答
  • プロセス構成の簡素化 によるパフォーマンス・保守性向上

セキュリティ

  • OpenBSDのpledge(2) で実行権限を最小化
    • モードごとに必要な権限のみ付与(例:受信側は書き込み権限のみ)
  • unveil(2) でファイルアクセス範囲を制限
    • 宛先ディレクトリ以下のみアクセス可能
    • chroot(2)不要、root権限不要
  • MD4ハッシュ のシード値をランダム化し、セキュリティ強化

貢献方法

  • パッチ送付先 :tech@openbsd.org
  • 開発・移植用リポジトリ :OpenBSDバージョン+移植用の補助コードを含む

この内容はopenrsyncの全体像、インストール方法、アルゴリズム、設計、rsyncとの違い、セキュリティ、貢献方法を簡潔にまとめたものです。詳細は各マニュアルページやソースコードを参照してください。

Hackerたちの意見

正気の人のためのノースロップ版 コンテキスト: https://mastodon.gamedev.place/@JeremiahFieldhaven/116654345...

https://social.treehouse.systems/@thesamesam/116662824873341...

OpenBSD 7.9では確認してないけど、7.8の時点では --exclude や -z はサポートされてなかった。でもそれ以外はopenrsyncはすごく良く動いてるよ。(編集: --excludeは7.9でサポートされるようになったみたい。いつ追加されたかはわからないけど、いいね!) でも「スロップ」を避けるのがすごく難しくなってきてるみたい。postfixにちょっとAIのコードが入ってるのを見たよ。 https://mastodon.sdf.org/@mrmasterkeyboard@mastodon.social/1...

皮肉なことに、Postfixはデフォルトインストールでroot/RCEの記録がないけど、opensmptdにはある(CVE-2020-7247)。今後どうなるかは時間が教えてくれるだろうね。

excludeは自動化ジョブで大きなgitリポジトリや他の大きなファイルを重複させないために非常によく使われる。これがあると多くの人にとっては致命的な問題になると思う。

Postfixについてどこにそれが書いてあるの?リンクを辿ったけど、見えるのはAIがバグを見つけるために使われてるだけで、コードを書くためじゃないよね。

AIを使ってるものを避けようとする試みが、逆に奇妙な逆ワック・ア・モールみたいになってきてる。狙った穴が放射能を帯びる感じ。ポップコーンでも用意して観戦するわ。

クロードって名前の人には申し訳ない気持ちになる。

ありがとう!TridgeがClaudeを使ってるなんて知らなかった。これからはOpenrsyncを使うことにするよ。

実際のポーティング作業は、OpenBSDのpledge(2)とunveil(2)が提供するセキュリティ機能を一致させることだよ。これらはシステムの機能にとって重要な要素なんだ。これがないと、システムは公共ネットワークからの任意のデータを受け入れちゃう。 https://justine.lol/pledge/ Alpine Linuxのedgeではpledgeが見当たらないんだけど、LinuxでPledgeをテストしてる人はいるのかな?Openrsyncをpledgeなしで使うリスクを誤解してたのかな?それともこの記事はOpenBSDユーザー向けなの?

あなたの引用の上から: > 公式にサポートされているオペレーティングシステムはOpenBSDだけで、これはかなりのセキュリティ機能を持っている。あなたの引用の下から: > これはFreeBSDのCapsicumで可能だと思うけど、Linuxのセキュリティ機能はめちゃくちゃで、適切にセキュリティを確保するには専門家の手が必要だよ。コンパイルして動くという意味ではポータブルだけど、同じセキュリティ機能を持っているわけではない。Linuxの(アップストリームの)上でpledge/unveilを見てみたいけど、期待はしてないよ。

その引用はちょっと単純化しすぎてて、完全に間違ってると思う。> それがないと、あなたのシステムは公共のネットワークから任意のデータを受け入れる。これらの機能は、公共のネットワークから任意のデータを受け入れる場合でも変わらないよ。彼らは、悪用されたプロセスができることを制限するんだ。『セキュリティ』セクションでちゃんと説明されてるから、これがどこから来たのかは分からないな。

Linuxにはpledgeやunveil、capsicumみたいな機能はないよ。cgroupsやnamespaces、他にもいろいろなものを組み合わせて似たようなことをしようとする必要がある。最初から「サンドボックス」や能力の制限を形成するために、いろんなシステムが相互作用して組み合わさる形で作られてきたから、特定のシステムコールやカーネルパスで実現するような完全な隔離とは違うんだ。最近はlandlockについてのコメントも見かけるけど、あれは新しいものを作るんじゃなくて、Linuxのプリミティブを再利用するんじゃないかな。まあ、これは完全な推測だけど、新しいものを作るより再利用する方が論理的だと思う。「めちゃくちゃ」って言ってるのは、いろんな方法があって、どれがベストか選ぶのが難しいってことだと思う。いろんなサブシステムを徹底的に調べないといけないからね。(1つか2つの比較的シンプルなシステムコールだけじゃないから)

rsyncにはスーパーユーザー用の特定の実行モードがあるんだ。それに、ネットワークから任意のデータをファイルシステムに流し込むしね。openrsyncは約1万行のCコードで構成されてるけど、俺を信じてミスしないと思う?いや、だからほとんど誰も厳格な信頼の境界の外でそれを使わないんだ。このセキュリティセクションは、rsyncがcurlみたいに敵対的な相手とやり取りするならもっと意味があると思う。もしrsyncの相手が敵対的なら、もっと大きな問題があるかもね!(俺はrpkiの専門家じゃないから、この問題領域のどこかにこの方程式を変える要素があるかは分からないけど。プロジェクトを批判してるわけじゃなくて、READMEでこれに引っかかったって言ってるだけだよ。)

いや、だからほとんど誰も厳格な信頼の境界の外でそれを使わないんだ。このセキュリティセクションは、rsyncがcurlみたいに敵対的な相手とやり取りするならもっと意味があると思う。もしrsyncの相手が敵対的なら、もっと大きな問題があるかもね!俺は違うと思う。rsyncは「友好的」なシステム間でデータを転送するために最もよく使われるけど、実際にはセキュリティの境界を越えているんだ。攻撃者がそれを利用して一つのシステムの侵害を複数のシステムの侵害に変えることができないようにすることが重要だよ。

ほとんど誰も厳格な信頼の境界の外でそれを使わない。 「厳格」をどう定義するかは自由だけど、10年前に見た限りでは、ほとんどのLinuxディストリビューションはrsyncでミラーリングを扱ってたよ。それってオープンソースエコシステムのかなりコアな部分での多くの使用例だね。

Michael Stapelberg / GokrazyチームによるGo実装もあるよ: https://github.com/gokrazy/rsync

これはmacOS 15.0以降で使われているバージョンだよ。

15.0だったかな?15.xラインのマイナーポイントリリースのどれかで出た気がするし、いくつかのスクリプトが謎に壊れたのを覚えてる。追記: ああ、面白いことに、15.0に含まれてたけど、後方互換性を壊す変更は15.4に回されたんだね。 https://apple.stackexchange.com/a/479297

ここに(スタブ)ウェブページもあるよ: https://www.openrsync.org/ rsyncのこういう分断の問題は、AppleやAndroidはこれを好むけど、LinuxやGPLの世界は元の実装に固執しちゃうってことだね。パワーユーザーはそれぞれのバージョンのクセを理解する必要がある。これを止める唯一の方法は、元の作者がBSDライセンスでリリースすることだね。追記: 同等の動作を想定している人は、これらの言葉をよく考えてみて: 「rsyncのコマンドライン引数のサブセットしか受け付けない。」

基本的にはGNU Tar/CPIOとBSD Tar/CPIOみたいな感じだね。僕はほとんどどこでもBSDバリアントを使うように標準化してるよ(特に今はWindowsでも搭載されていて、tarコマンドで他のアーカイブ形式も扱えるから)。でも、どこにでもインストールするのは本当に面倒だね。

他のBSDユーティリティ(SysVユーティリティを使ってるならそっちも)とGNUのものが違うのと、全く変わらないよ。もう50年もこれに慣れてるからね。

これを止める唯一の方法は、元の著者がBSDライセンスでリリースすることだね。それで止まるのかな?私の理解では、少なくともOpenBSDはライセンスだけじゃなくて技術的な理由で物事をやり直す傾向があるみたい。

AppleやAndroidはそれを好むだろうね。これを読んで思ったのは、なんでAppleやAndroidがrsyncをわざわざ含めるんだろう?DebianやFreeBSDの新規インストールでは手動でインストールしなきゃいけなかったことに気づいたんだけど、最近あまり使ってないMacをチェックしたら、ちゃんとインストールされてた。

openrsyncは発表されて以来、ちょこちょこ使ってるけど、確実に進化してるよ。いつか専ら使えるようになるのが楽しみ。僕の使い方でSamba rsyncと合わないのは、次のコマンドの部分だね: openrsync --rsync-path=openrsync -av -e ssh /etc/services example.com:/tmp/services。openrsyncがリモートファイル/tmp/servicesを作ると思ってたけど、実際には/tmp/services/servicesが作られちゃった。通常のディレクトリミラーリング、つまり-av -e ssh /path/to/src/ example.com:/path/to/dst/はSamba rsyncと同じように動作するよ。

すでに宛先に/tmp/servicesディレクトリがあったのかな?rsyncでよくある混乱の一つは、ディレクトリとトレーリングスラッシュの扱いなんだよね。

openrsyncがリモートファイル/tmp/servicesを作成すると思ってたんだけど、実際には/tmp/services/servicesができちゃった。rsyncに何年も苦しめられた身として、その気持ちはわかるけど、2つ目の「services」を作る方がずっと理にかなってるし、安全なデフォルトだと思う。rsyncのデフォルトをもう少し常識的なものに変えて、未来の世代をこの混乱から救えるチャンスがあるなら、やるべきだと思う。

このパッケージの開発の背景が必要な人へ; このプロジェクトは現在、RPKIバリデーターの一部として開発されているよ。 https://medium.com/@jobsnijders/a-proposal-for-a-new-rpki-va...