Article:

サマリ

ActivityPubは連合でやり取りする際のHTTPリクエストにはSignatureヘッダがついています。 Signatureヘッダは、いくつかの他のHTTPヘッダを対象に取って、それらの内容を結合したものの署名を作成するというものです。 misskeyではこの署名範囲を(request-target) date host digestと指定しているので、このどれかの内容が途中で書き換えられてしまうと署名が無効になってしまいます。

apacheでリバースプロキシを組むと、デフォルトでHostヘッダが書き換わり、元の内容が X-Forwarded-Hostに入ります。 ので、misskeyが作る署名のhostが、リバースプロキシのhostのまま署名され、そのhostがリバースプロキシにより本来のhostへ書き換えられるため、署名が無効になっていたようです。

misskey側でX-Forwarded-Hostをうまく解釈してくれればいいのですが、そういうのは今のところないみたいです。

なので、apacheの設定の、このmisskeyインスタンスのVirtualHostディレクティブに対しProxyPreserveHost onを指定したところ、無事連合が動くようになりました。

経緯

Gammalab(自宅のこと)では1台リバースプロキシとしてapacheを置き、その配下に他の仮想マシン・kubernetes loadbalancerを指定しています。

今回misskey用のhelmチャートを作成し、試験的にサービスを起こしてみました。

無事にアクセスできるようになり投稿も自由にできるようになったのですが、どうも他インスタンスのユーザーを見ることはできてもフォローを押すとどうも処理が完了しない・・・ 連合ステータスを見てみても、認識こそされてるもののなかなか連合中にならない・・・。といった状態に陥りました。

テスト用にもう一台misskeyインスタンスを構築し、相互にフォローを飛ばしてみてエラーログが落ちないかを凝視してみましたが、これがダンマリで…

misskeyのエラーログには例えばwebfingerがなんかおかしいとか、そういったことまで事細やかなことが落ちるので何も出て来ないのは想定外で、解決は困難を極めました。

ちょっと前にサマリで紹介したブログをたまたま見ていたので「もしかして!」と気づきましたが、これを見てなかったら一生気づかなかったかもしれません…。

おまけ

misskeyではリバースプロキシとしてNginxが推奨されておりコンフィグ例もおいてありますがapache版はありませんので、僕のapacheの設定を参考として紹介しておきます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<VirtualHost *:443>
  ServerName example.tld
  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/example.tld/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.tld/privkey.pem

  RewriteEngine on
  RewriteCond %{HTTP:Upgrade}    websocket        [NC]
  RewriteCond %{HTTP:Connection} upgrade          [NC]
  RewriteRule ^/?(.*) "ws://misskey.internal/$1"  [P]

  ProxyPreserveHost on
  ProxyPass / http://misskey.internal/
  ProxyPassReverse / http://misskey.internal/
  CustomLog ${APACHE_LOG_DIR}/exampletld_access.log vhost_combined
  ErrorLog ${APACHE_LOG_DIR}/exampletld_error.log
  LogLevel notice
</VirtualHost>

参考リンク

SignatureヘッダについてはこちらのブログHTTPメッセージに署名をするSignatureヘッダの標準化が詳細に解説してくださっています。RFCを読むのは大変骨が折れるため、こうして簡単に説明してくださる方には頭が上がりません…。ありがとうございます。