Misskey を Tor でも連合できるようにしてみた
前回の記事 (Tor 上に Misskey インスタンスを立ててみた)の続きみたいな感じです。
前回の状態では、 .onion
ドメインで公開できても他のインスタンスと連合することはできませんでした。
今回はその問題を解決していきます。
連合できない理由
まず、なぜ連合できないかというと、Misskey のバックエンドで行われている通信が Tor を経由していないため、他の Tor 上のインスタンスを見つけられないからです。
そのため、Tor から生えてくる SOCKS5 プロキシを使うように変更することで解決できます。
SOCKS5 プロキシを使えるようにする
Misskey ではもともと HTTP プロキシは使えているので、そこの部分に機能追加して SOCKS5 プロキシに対応させれば OK です。
具体的には、packages/backend/src/core/HttpRequestService.ts
にプロキシの設定があるため、socks-proxy-agent
を使って SOCKS5 が指定されたときにそっちを使うように設定します。
import { SocksProxyAgent } from 'socks-proxy-agent';
function getHttpProxyAgent({proxy, ...config}: any): http.Agent {
const url = new URL(proxy);
switch (url.protocol) {
case 'socks5:':
case 'socks5h:':
return new SocksProxyAgent(proxy, config);
default:
return new HttpProxyAgent({
proxy: proxy,
...config,
});
}
}
function getHttpsProxyAgent({proxy, ...config}: any): https.Agent {
const url = new URL(proxy);
switch (url.protocol) {
case 'socks5:':
case 'socks5h:':
return new SocksProxyAgent(proxy, config);
default:
return new HttpsProxyAgent({
proxy: proxy,
...config,
});
}
}
を追加して、
this.httpAgent = config.proxy
- ? new HttpProxyAgent({
+ ? getHttpProxyAgent({
keepAlive: true,
keepAliveMsecs: 30 * 1000,
maxSockets,
...
this.httpsAgent = config.proxy
- ? new HttpsProxyAgent({
+ ? getHttpsProxyAgent({
keepAlive: true,
keepAliveMsecs: 30 * 1000,
maxSockets,
みたいな感じにしました。
詳細: https://github.com/p1atdev/onionskey/commit/355c5e9d91f8765e085895d06986bb664b6cb3eb
ついでに、torrc
も編集して SOCKS5 プロキシを有効にし、Misskey の設定ファイルのプロキシ URL も変更します。
HiddenServiceDir /etc/tor/hidden_service/
HiddenServicePort 80 web:3000
- HTTPTunnelPort 0.0.0.0:8118
+ SOCKSPort 0.0.0.0:9050
ExitPolicy reject *:*
にすると、 9050 ポートで Tor の SOCKS5 プロキシが使えるようになります。
Misskey の設定も以下のようにします。
proxy: socks5h://tor:9050
socks5h
は socks5
と異なり、名前解決もプロキシサーバーに任せます。.onion
ドメインは Tor じゃないと解決できないので socks5h
にする必要があります。
HTTP を許可する
普通ならありえないのですが、Tor では普通に HTTP で通信するため HTTP での通信を許す必要があります。
コードにところどころ強制 HTTPS を使うところや HTTP を許さない処理があるのでそこを編集します。
packages/backend/src/core/FetchInstanceMetadataService.ts
、packages/backend/src/misc/check-https.ts
、packages/frontend/src/scripts/lookup.ts
を編集しました。
const url = 'https://' + instance.host;
というようなコードがあるので、
function prependProtocolScheme(host: string): string {
const tld = host.split('.').pop();
switch (tld) {
case 'onion':
return 'http://' + host;
default:
return 'https://' + host;
}
}
みたいな関数を作って
const url = prependProtocolScheme(instance.host);
に変更しました。.onion
ドメインが全て HTTP というわけではないのですが、別に大きな問題もない気がするので .onion
なら問答無用で htpp://
を付与しています。
packages/backend/src/misc/check-https.ts
には https://
かどうかを判定する関数
export function checkHttps(url: string): boolean {
return url.startsWith('https://') ||
(url.startsWith('http://') && process.env.NODE_ENV !== 'production');
}
があるので、こちらも同様に .onion
だったら http://
でも OK になるようにします。
export function checkHttps(url: string): boolean {
if (url.startsWith('https://')) {
return true;
}
if (url.startsWith('http://') && process.env.NODE_ENV !== 'production') {
return true;
}
// Allow http for .onion
const tld = new URL(url).hostname.split('.').pop();
switch (tld) {
case 'onion': {
return url.startsWith('http://')
}
default: {
return false;
}
}
}
packages/frontend/src/scripts/lookup.ts
は照会操作の部分で https://
のみを許可していたので、ここはもうめんどいので http://
も普通に通すようにしました。(本当は上みたいに個別に許可したほうがよさそう)
詳細: https://github.com/p1atdev/onionskey/commit/39a4dab750634b7479b95131df9d56d6fdab4183
連合できるようになった
これで連合できるようになりました。現状連合できるインスタンスは以下くらいです。
- Mitra Social: https://mitra.social
- Misskey(Tor): http://misskey6c32sh6c4hmq6tzd6k2pafovzfoxd3jpujcfpofymy524o6ad.onion/instance-info/5z5ce433e2yp73jqm3yxmyh2yvcn33venhnm5trqde6uwjysxyy3gbad.onion
デフォルトで Tor に対応している[1] mitra.social というインスタンスがあるのですが、そことの連合にはバグがあるので個別で修正する必要があります:
詳細:
- https://github.com/misskey-dev/misskey/pull/11791/files
- https://github.com/p1atdev/onionskey/commit/e121a90b87c94edb4298dd74c7f4754b631bccac
まとめ
SOCKS5 プロキシを使うにようして、HTTP も許可したら連合できるようになりました。
こまかいコードとかは GitHub に上がっているのでコミット履歴を見るといいと思います。
全体のコードはこちらです:
参考
Discussion