Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

テスト環境で(httpsではない)httpで公開されているサーバー同士でもActivityPub通信がしたい #10716

Closed
tamaina opened this issue Apr 25, 2023 · 53 comments · Fixed by #10717
Labels
⚠️bug? This might be a bug

Comments

@tamaina
Copy link
Member

tamaina commented Apr 25, 2023

  • WebFingerをhttpsで参照するため失敗する
    return `https://${hostname}/.well-known/webfinger?` + urlQuery({ resource: `acct:${query}` });
  • ApPersonServiceのcreatePerson, updatePersonでstartsWith('https://')で弾かれる
@tamaina tamaina added the ⚠️bug? This might be a bug label Apr 25, 2023
@tamaina
Copy link
Member Author

tamaina commented Apr 25, 2023

WebFingerをhttpsで参照するため失敗する

production以外ではhttpでリクエストする?

startsWith('https://')で弾かれる

production以外ではhttpも許可する?

@rinsuki
Copy link
Contributor

rinsuki commented Apr 25, 2023

その辺考えるのだるいので証明書検証無効化(もしくはちゃんとmitmのCA読ませる or 適当にワイルドカードの証明書をLEとかで取って使う) + mitmproxy の forward proxy モードあたりで誤魔化したほうがよさそう (ついでにサーバー間通信が見れてお得)

@tamaina
Copy link
Member Author

tamaina commented Apr 25, 2023

@tamaina
Copy link
Member Author

tamaina commented Apr 25, 2023

プロキシをセットアップするのはテストに組み込みたい時に面倒そう

(サーバー間通信はFastifyみたいにdevelopment時に電文をログさせればよさそう)

@tamaina
Copy link
Member Author

tamaina commented Apr 25, 2023

CA証明書を読ませて〜とかすると(また)Misskeyをスタンドアロンでhttps待受する機能を復活させないとならず面倒

で、node-fetchでhttps通信できてもブラウザからのアクセスはMisskey自体の待受がhttpsにできない(config.urlをhttps:// にできない)ためhttpで通信できるようにするのが面倒臭くなさそう

@rinsuki
Copy link
Contributor

rinsuki commented Apr 25, 2023

  • 結局ローカルでの他実装との連合テストを(やりたい人がいるなら) 証明書の検証無視はあると便利
  • productionじゃない時に HTTP webfinger 強制はナンセンス
  • 自動テストに組み込む目的なら適当にプロキシするHTTPSサーバーを書いたらいいのでは、ライブラリ一発で行けそうな気がする (そもそも443 or 80 listen 想定≒Linuxで特権or設定変更必須にするのマジ?って感じかなりするけど、ポート番号とか指定できるんでしたっけ)

@rinsuki
Copy link
Contributor

rinsuki commented Apr 25, 2023

node-fetchでhttps通信できてもブラウザからのアクセスはMisskey自体の待受がhttpsにできない(config.urlをhttps:// にできない)

node-fetchでHTTPS通信できる状態ならブラウザでも証明書エラー無視すれば見られるのでは?

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 25, 2023

これ用に実際のホスト認証部分を変えちゃうのはあんま好ましくない気がする

テスト環境なのであれば
NODE_TLS_REJECT_UNAUTHORIZEDNODE_EXTRA_CA_CERTS と 適当に alice.local, bob.local とかを hosts 登録+セルフサインSSL作ってーでいいんじゃないかな

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

証明書エラー無視

ブラウザの設定変えたらいけた

認証部分を変えちゃうのはあんま好ましくない

証明書検証を何らかの拍子にオフにできるほうがまずいのでは

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

他実装との連合テスト

あー

productionじゃない時に HTTP webfinger 強制はナンセンス

これはわかる

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

docker的解決策とかあるかしら

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

証明書検証を何らかの拍子にオフにできるほうがまずいのでは

手動開発の事はとりあえず考えないとすると、自動テストであれば本体側にそういうのは含めず (少なくとも https.Agent を生成する関数をmockできるように分離くらい?)していい感じにmockなりすればよさそう

…というか普通に NODE_TLS_REJECT_UNAUTHORIZED=0 で行けたりしませんか?

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

手動開発の事はとりあえず考えない

考えたい

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 26, 2023

証明書検証を何らかの拍子にオフにできるほうがまずいのでは

NODE_TLS_REJECT_UNAUTHORIZEDはそもそもnodeの機能なので(mitmしてる社内ネットワークでは仕方なく使わざるを得ない場合もある)そこは大丈夫ではと思ってる

dockerにもあの環境変数で動くはず、ブラウザにもセルフサインCAで対応したほうがいいかと

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

httpでさほど問題があるように見えないのでhttp使う方針で行きたい

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

よくよく考えるとprd以外でhttp許容するといざprdに載せた時うっかりhttpのURL書いててダメでしたということが起こりうるので無闇にprdかどうかで挙動変えるのはやめた方がいい、というかNODE_TLS_REJECT_UNAUTHORIZED=0じゃだめだったんですか

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 26, 2023

NODE_TLS_REJECT_UNAUTHORIZED=0でダメだったとしてもこれでできるように修正したほうがいいと思います

PROD環境にDEVビルドを間違ってデプロイしちゃった際に他のAPインスタンスに変なリクエストを飛ばしまくるなどリスクがないとは言えないかも

HTTP通信だとそもそもスペック外の挙動になるのと、
↑APのスペックを再度確認したらSHOULDでした

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

WebFingerってhttps必須なのか
(今規格書を斜め読みした)

@tamaina

This comment was marked as outdated.

@tamaina

This comment was marked as outdated.

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

mitmproxyとかいうのを使えばいいのかしら(ミリしらだけど)

@tamaina

This comment was marked as outdated.

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

node-fetchでhttps通信できても...

node-fetchでHTTPS通信できる状態

できた試しはなかった

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

NODE_TLS_REJECT_UNAUTHORIZED=0でd22@localhost:3001を照会した結果

INFO *  [remote resolve-user]   WebFinger for d22@localhost:3001
(node:1019758) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
ERR  *  [remote resolve-user]   Failed to WebFinger for d22@localhost:3001: request to https://localhost:3001/.well-known/webfinger?resource=acct%3Ad22%40localhost%3A3001 failed, reason: write EPROTO 20B06AB6FFFF0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:355:

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

httpsにhttp/2が必須なのはFastifyの仕様(そのせいでWebSocketは出来なさそう?)

@tamaina

This comment was marked as off-topic.

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

(そのせいでWebSocketは出来なさそう?)

https://tex2e.github.io/rfc-translater/html/rfc8441.html でhttp2でのWebSocketブートストラップは定義されており、Node.jsは一応できるっぽい nodejs/node#23284

https://github.com/theturtle32/WebSocket-Node で使えるかはわからない

wsでもまだ実装されていない模様 websockets/ws#1458

@acid-chicken
Copy link
Member

実在ドメインに A レコードで 127.0.0.1 に向ければ Let's Encrypt とかから発行された証明書で接続できるけどそれじゃダメ?

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

ERR  *  [remote resolve-user]   Failed to WebFinger for d22@localhost:3001: request to https://localhost:3001/.well-known/webfinger?resource=acct%3Ad22%40localhost%3A3001 failed, reason: write EPROTO 20B06AB6FFFF0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:355:

それそもそもちゃんとSSLしゃべれてないのでは (self-signed でコケる時は reason: self signed certificate とかになるはず)
参考: https://www.google.com/search?q=SSL%20routines:ssl3_get_record:wrong%20version%20number

実在ドメインに A レコードで 127.0.0.1 に向ければ Let's Encrypt とかから発行された証明書で

CIの自動テストにvalidな証明書持たせるのは非常に面倒…というのと証明書無視はなんか手元で試した限りでは行けそうなのでそこは問題ではない

FastifyがHTTP2強制+WSがHTTP2でうまくいかんというのは

適当にプロキシするHTTPSサーバーを書いたらいいのでは、ライブラリ一発で行けそうな気がする

で行けたりしませんか

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

それそもそもちゃんとSSLしゃべれてない

そらしゃべらせる手続きを何もしてないし…

ライブラリ一発で行けそう

私はアイデアを持っていない

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 26, 2023

image

普通にNODE_TLS_REJECT_UNAUTHORIZED=0だけでできた
TLS周りは面倒なのでtraefikに全部任せる形でやった
dockerに他のコンテナー走ってたらちょっと設定変えてあげる必要あるかも
↑とりあえず変えておいた

https://gist.github.com/u1-liquid/bc4677830c1ed5fd4f654012b9810d36

@tamaina

This comment was marked as off-topic.

@u1-liquid

This comment was marked as off-topic.

@tamaina

This comment was marked as off-topic.

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 26, 2023

一応挙動について書いておくと

NODE_TLS_REJECT_UNAUTHORIZED=0 無しだとリモートのユーザー照合時にえらーになる、NODE_TLS_REJECT_UNAUTHORIZED=0 あるとサーバーサイド通信はできるようになる。
ブラウザでは普通にself signed certificate許可してくれりゃ開ける

関係とは…?

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

traefikを挟んだら検証は置いておいてhttpsで喋れるようになったねという話を言いたかった()

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

なんか適当にこういうノリで

const tls = require("node:tls")
const net = require("net")
const fs = require("node:fs")

const server = tls.createServer({
    cert: fs.readFileSync("./cert.pem"),
    key: fs.readFileSync("./key.pem"),
}, socket => {
    const dest = net.createConnection({
        host: "127.0.0.1",
        port: "80",
    })
    socket.pipe(dest)
    dest.pipe(socket)
})
server.listen(443)

証明書は適当にこんな感じで

#!/bin/bash
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -nodes -subj "/CN=misskey.localhost"

@fruitriin
Copy link
Contributor

素朴な疑問なんだけどどういうモチベーションでhttpで連合したいのかよくわからない
開発者が手元で連合しながら開発する用?

@u1-liquid
Copy link
Contributor

# Misskey requires a reverse proxy to support HTTPS connections.
#
# +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# +------+ |+-------------+ +----------------+|
# +---------------------------------------+
#
# You need to set up a reverse proxy. (e.g. nginx)
# An encrypted connection with HTTPS is highly recommended
# because tokens may be transferred in GET requests.

👀

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

モチベーション

  • 連合機能の開発
  • 可能ならJestおよびGitHub Actionsで連合のテストをしたい

@u1-liquid
Copy link
Contributor

#10716 (comment)
で両方できるかも

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

(httpsが面倒な場面で避難的に使えてもいいかなと思ったがあんまりないか)

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

traefik持ってくるのはちょっと面倒かもしれないがまあ GH Actions で使うだけならそれでもいいかも

@u1-liquid
Copy link
Contributor

(nginxにopensslで作ったself signed certificateつけてあげるなどよりずっとマシでもある)

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

hostsファイルいじったりブラウザの設定をいじったりdockerを導入したりするのが面倒(などと発言しており)

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

あ〜いける

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

(そういえば証明書は一度作ったら使いまわして問題ないわね)

@tamaina
Copy link
Member Author

tamaina commented Apr 26, 2023

(なんかでもそこで一手間加えてhttpsでテストしたいことってある?とまだ思っている)

@u1-liquid

This comment was marked as outdated.

@rinsuki
Copy link
Contributor

rinsuki commented Apr 26, 2023

そこだけ出されても何でコケてるかわからない…

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 26, 2023

これはMisskeyの方でだめかも

ログ見たら普通に設定ミスだった(それはそう)docker使わない環境にするかhost ネットワーク使うと解決しそう

INFO *  [remote resolve-user]   WebFinger for admin@localhost:3001
ERR  *  [remote resolve-user]   Failed to WebFinger for admin@localhost:3001: request to https://localhost:3001/.well-known/webfinger?resource=acct%3Aadmin%40localhost%3A3001 failed, reason: connect ECONNREFUSED 127.0.0.1:3001
WARN *  [api]   failed to resolve remote user: Error: Failed to WebFinger for admin@localhost:3001: request to https://localhost:3001/.well-known/webfinger?resource=acct%3Aadmin%40localhost%3A3001 failed, reason: connect ECONNREFUSED 127.0.0.1:3001

@u1-liquid
Copy link
Contributor

u1-liquid commented Apr 26, 2023

localhost にするとなぜかcacheableLookup ENOTFOUND localhostというWebFinger照会エラーでWindowsでは動かなかったけど、IPでは動いた(ブラウザは文句言うけど)
たぶんおそらくLinuxだとlocalhostでも動くと思う
↑だれもlocalhostに対するDNS応答してくれないと動かないのが仕様らしい(hostsファイルは参照しないみたいなので)
https://nodejs.org/api/dns.html#dns_implementation_considerations

image

https://gist.github.com/u1-liquid/b15a3d97bf09dc8b4c813d7e23f038ea

ちなみにサーバー立ち上げに使ったコマンド

traefik --configFile=./.config/traefik.yaml
cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 MISSKEY_CONFIG_YML=alice.yml pnpm run migrateandstart
cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 MISSKEY_CONFIG_YML=bob.yml pnpm run migrateandstart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚠️bug? This might be a bug
Projects
None yet
5 participants