From 3490249da5a5a7f6cca7e95f74674a7e7f7a4bc3 Mon Sep 17 00:00:00 2001 From: usbharu <64310155+usbharu@users.noreply.github.com> Date: Sat, 23 Dec 2023 14:18:06 +0900 Subject: [PATCH] =?UTF-8?q?2023-12-24=E3=81=AE=E8=A8=98=E4=BA=8B=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/posts/2023-12-24/image.png | Bin 0 -> 32488 bytes content/posts/2023-12-24/index.md | 164 +++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 content/posts/2023-12-24/image.png create mode 100644 content/posts/2023-12-24/index.md diff --git a/content/posts/2023-12-24/image.png b/content/posts/2023-12-24/image.png new file mode 100644 index 0000000000000000000000000000000000000000..641a2eecdabade7cea54b54c5c7be68254b23889 GIT binary patch literal 32488 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

Q`LAD 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 DZB|1n literal 0 HcmV?d00001 diff --git a/content/posts/2023-12-24/index.md b/content/posts/2023-12-24/index.md new file mode 100644 index 0000000..7088a62 --- /dev/null +++ b/content/posts/2023-12-24/index.md @@ -0,0 +1,164 @@ +--- +author: usbharu +draft: false +categories: + - 技術 +date: 2023-12-23T10:47:05+09:00 +tags: + - ActivityPub +keywords: + - ActivityPub +title: ActivityPub実装SNSを作っている。その感想 +relpermalink: posts/2023-12-24/ +url: posts/2023-12-24/ +decription: +--- + +{{< alert icon="circle-info" >}} +この記事は [Fediverse (3) Advent Calender 2023](https://adventar.org/calendars/8730) 24 日目の記事です。 +{{< /alert >}} + +私は、去年の 11 月ごろに自分の Mastodon と Misskey サーバーを建てて、 Fediverse に移住してきました。 + +なんだかんだあって Kotlin+Spring Framework で ActivityPub 実装 SNS を作って遊んでいます。こういう文章を書くのは苦手なので、本題に移ります。 + +## JSON のシリアライズ/デシリアライズが難しい + +初っ端から何を言っているんだ感がありますが、ActivityPub で送られてくる JSON は[Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)と言ってかなり(Json デシリアライザー から見て)複雑な JSON が送られてきます。この内`type`と`object`というプロパティが鬼門で、ここさえなんとかなれば後はなんとかなります。 + +### type + +この`type`というプロパティ、配列だったり単純な文字列だったりします。最初は`type`を読んで Jackson の`@JsonTypeInfo`などを使ってデシリアライズすればいいやなどと考えていましたが、この甘い考えはすぐに打ち砕かれました。`type`の種類がものすごく多い上に配列だったときに問答無用でエラーが起きます。実際に配列が送られてくることがあるのかは知りませんが、ともかく`@JsonTypeInfo`は使えませんでした。 + +結局`type`だけ読み取り、`type`に応じて処理する対象を変えることで対処[^1]しました。`type`が配列だった場合は要素で最初の有効なものを使用します。[^2] + +[^1]: https://github.com/usbharu/Hideout/blob/4ceb42728d139fb4306713e5d49468e24509a8bc/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/ActivityPubProcessor.kt +[^2]: https://github.com/usbharu/Hideout/blob/4ceb42728d139fb4306713e5d49468e24509a8bc/src/main/kotlin/dev/usbharu/hideout/activitypub/service/common/APService.kt#L204-L218 + +### object + +`object`はアクティビティの対象を示すプロパティで、文字列だったり、JSON のオブジェクトだったりします。これも悩みの種で、例えば`Undo`アクティビティの`object`には`Like`や`Follow`、`Accept`、`Block`などが入ります。これらを安全にデシリアライズすることに苦労しました。結局想定されるすべてのオブジェクトをベタ書きしたカスタムデシリアライザーを作成することで解決しました。[^3] + +[^3]: https://github.com/usbharu/Hideout/blob/b0f3ae4d8d319f39e7127064319bd62dc7a6f672/src/main/kotlin/dev/usbharu/hideout/activitypub/domain/model/objects/ObjectDeserializer.kt#L12 + +## HTTP Signature に悩ませられ続ける + +Mastodon や Misskey、最近連合できるようになった Threads などのほとんどの ActivityPub 実装は HTTP Signature でアクティビティを署名することでサーバー間での通信をある程度安全にしていますが、これも悩みの種でした。 + +### そもそも情報がない + +ActivityPub 実装を初めた頃、今ほど情報がなく HTTP Signature は IETF の文書を読むか、既存の実装を解読するしかありませんでした。そもそも署名に必要な知識が不足していたのもあり、かなり苦労しましたがとりあえず Misskey で署名を検証できる様になりました。 + +HTTP Signature の署名に関する解説だけで 1 記事書けてしまうのでこの記事をを読んでください。なお、Misskey は割と頻繁に破壊的変更をするので書いてある内容だと連合できないことがあります。その時は教えてくれたら直します。 + +{{< article link="/posts/2023-07-23/" >}} + +### GET リクエストへの署名 + +最初期の実装では GET リクエストに対して署名することを考慮しておらず、 GET リクエストにも署名が必要な部分があることに気付いたときには主要部分がほぼ完成していました。そのためかなり雑な対応をすることになり、現在でも無茶苦茶な実装として技術的負債になっています。 + +なのでもし ActivityPub 実装 SNS を作ることがあるなら、最初から GET リクエストへの署名について考えておく必要があります。 + +### 不安定すぎる連合 + +#### Misskey にあった脆弱性と破壊的変更 + +脆弱性があったことはともかく、その後の対応で連合に関して破壊的変更が入りました。具体的には`Digest`ヘッダのアルゴリズム名が大文字のみ受け付けられるようになりました。 + +`Digest: sha-256=hogehoge` + +でも受け付けられていたものが + +`Digest: SHA-256=hogehoge` + +でしか受け付けられなくなった。 + +私はかなり焦りました。昨日まで連合できていたインスタンスと急に連合できなくなるのです。署名や連合に関する全てのテストをパスし、自分でも色々確認しましたが何もおかしいところはありません。そもそも自分は署名に関して一切手を加えていませんでした。あれやこれやと 1 時間ほど悩んだところで、そういえば Misskey の署名周り、脆弱性の修正で変更が入っていたよな…と気づくことができたのでした。 + +#### HTTP Signature が複雑すぎる + +1 つのバージョンの規格自体は理解すれば簡単です。しかし 10 年も色々いじくり回されているドラフト段階の規格だと話は違います。初期の規格と最新の規格があまりにも違いすぎました。私は完全に諦めて、Misskey と Mastodon と連合できれば OK ということにしています。 + +### 連合に必要なヘッダー + +いまのところ自分の実装では + +GET リクエストで + +- (request-target) +- date +- host +- accept + +POST リクエストで + +- (request-target) +- date +- host +- digest + +をヘッダーに含めて署名しています。 + +## SharedInbox を作らなかったら重複まみれになった + +最初めんどくさがって SharedInbox を作らなかったのですが、現在進行系でエラい目にあっています。SharedInbox がない場合フォロワーの数だけそれぞれの actor の inbox にアクティビティが飛んでくるため重複まみれになります。自分のサーバーとしか連合していないので対症療法的な対処は可能ですが、sharedInbox は最初から作っておきましょう。 + +![actor-inboxに来る大量のリクエストのログ](image.png "1アクティビティにつきこれだけのリクエストが飛んでくるようになってしまった") + +尤も、ユニーク制約やアプリケーションでの重複排除をしているため最終的には重複は発生しませんが、無駄ですし追加でリソースを取得する必要が出たとき逆にリモートサーバーに DoS じみたリクエストを送ってしまいます。 + +## 常に性悪説をとる必要がある + +ActivityPub って結構ガバガバなので色々攻撃できちゃいます。なので常に性悪説をとって防衛する必要があります。自分の AP 実装では全く実現できておらず、基本機能実装完了後の課題となっています。 + +### 無限再帰、無限ループアクティビティ + +大抵の実装ではメンションなどがあった際 actor を取得し、固定 Note を取得すると思います。 + +例えばアクティビティを辿るたびに違う actor や Object のリンクを返された場合、無限ループに陥ります。制限をかけるなどで対処する必要があります。 + +### めちゃくちゃ遅いがタイムアウトしないリモートのリソース + +リモートのリソースを取得する際、意図的に遅くすることで簡単に DoS が出来てしまいます。 + +### 純粋に大量のアカウントでフォロー + +上に書いた通り sharedInbox を実装せず、大量のアカウントを作ってフォローするだけで配送先が増えます。配送先が増えるということは単純に負荷が増えるため、ドメインブロックなどの機能を実装する必要があります。 + +## アカウント削除 + +ActivityPub では同じドメイン、同じ ID でアカウントを 2 回作ることが出来ません。作っても連合出来ないことが多いです。あまり有名ではないのか、Misskey の GitHub には時々連合に失敗する旨の Issue が建てられ、「仕様です」と速攻で Close されている光景を見ることが出来ます。 + +逆にリモートからアカウント削除のアクティビティが来た際にどうするかが問題になります。アカウント削除アクティビティを受診したあと、(エラーのリトライなどで)アクティビティがきた場合もう一度 actor を取得し、アカウント削除がなかったことになるようでは全く意味がありません。 + +そこで削除済み actor だけ保持するテーブルを作り、アカウント削除アクティビティを受信した actor を移動します。actor 取得時、削除済み actor にある actor は取得せず破棄することでこれを実現しています。 + +## actor を取得するまでわからない不正なアクティビティ + +Spring Security で HTTP Signature を使って認可制御していたとき + +1. 未知の actor のアクティビティを受信 +2. DB から鍵を探す +3. 鍵がないので不正!! + +ということが起こりました。これを解決するには + +1. 未知の actor のアクティビティを受信 +2. DB から鍵を探す +3. なければ actor を取得 +4. 検証 + +というフェーズを踏む必要があり、 + +1. 不正なアクティビティを受信 +2. actor を取得 +3. 検証 +4. 不正発覚!! + +というように Spring Security でアクティビティ受信時にチェックしようとすると actor を取得する必要があるという罠にハマりました。 + +actor の取得は失敗する可能性があり、ジョブキューなどでリトライの制御をする必要があります。結局 Spring Security での HTTP Signature の検証は限定的な状況でしか行えませんでした。 + +## ActivityPub 実装は楽しいぞ + +いい感じの締めが思いつかなかったのでこんな感じで終わりです。下手くそな文章ここまで読んでいただいて嬉しいです。本当は ActivityPub の実装ハンズオン的な記事を書きたかったのですが、試験勉強が忙しすぎてそれどころではありませんでした。どうも合格してそうなのでそのうち書きたいと思います。