たくさんの自由帳

curl で 200 返ってくるのに、Node.js でリクエストすると 403 が返ってくる件の調査

投稿日 : | 0 日前

文字数(だいたい) : 3533

タイトル通りで、curlだと200で成功するリクエストが、適当な言語(今回はNode.js)のHTTP クライアントを使ってリクエストしようとすると、なぜか403でエラーになる件の調査をしました。

結果は...

Node.jsのバージョンが古かった...
Node.js 16だとリクエストに失敗しますが、18にしたら治りました。なぜ...

この件の経緯

  • お一人様Misskeyを建てた
  • お一人様Misskeyから一部のサーバーのユーザーを検索できない事がわかった
    • ログを見ると403エラーになっている
    • VPScurlでも失敗している
  • 手元のWindowsマシンではリクエストが成功する
    • 手元でも失敗か~と思いきやユーザーエージェント付けたら動いた
      • curl -H 'User-Agent: @takusan_23' https://example.com
  • VPSIPアドレスがブラックリスト入りしてると考える
  • 大体MisskeyサーバーはCloudflareでプロキシしているはず...
    • Cloudflareを疑う
  • しかしmisskey.ioなど、Cloudflareを使っている(であろう)サーバーのユーザーをフォローできている
    • 今度は繋がらないサーバーを疑う
      • 意図的に弾いているとかは考えにくいが
  • と思ったが、他にもお一人様サーバーから繋がらないサーバーが出てくる
    • 知ってる限り二件ぐらいある
    • 流石に複数のサーバーからIPアドレスを狙い撃ちでブロックされているとは考えにくい
      • じゃあCloudflareか?
        • でも繋がるサーバーあるんだよな
  • グローバルIPアドレスを変更してみる
    • AWS Lightsailなら静的IPのデタッチしてアタッチすると新しいのが降ってくる
      • しかしダメ
      • ここでAWSが狙い撃ちされているのではと考える

--- 挫折 ---

  • ふと、AWS CloudShellというサービスがあることに気付く
    • すぐに使えるLinuxマシンみたいなやつ
      • Linuxしか用意されてないアプリとかを入れておくと良さそう
        • Windowsだと使えないから~EC2 / Lightsail建てて使いたいLinuxアプリを入れる!みたいなことが回避できる
    • curlとか検証用のツールを入れておくと良いのかな
  • AWS CloudShellcurlしてみる
    • リクエストが通る!!!
    • やっぱAWS Lightsailが狙い撃ちされているのではと考える

他に案がないため一旦あきらめる

  • Cloudflare.dev のトップレベルドメインをサポートする
  • 私のお一人様もCloudflareでプロキシ(Cloudflare DNSを使う)すればIPアドレスがブラックリスト入りされてるのも治るのではと予測
    • 失敗
    • まぁそれはそう。関係ないよな

挫折。ぐぬぬ

  • ふと、EC2で建てたらどうなるのか試したくなる
    • 他にもAWSで動かしているサーバーがあってもおかしくないはず
  • ちょうど無料枠がある
    • VPCとかサブネットマスクとかCIDRとか意味わかんないから避けてた
      • が、デフォルト VPCがあるのでそれにEC2を追加すれば良いことが判明
      • デフォルトを使うのはあんまり良くないらしい
        • セキュリティグループで必要最低限のポートだけ開けるようにする など
  • Ubuntu 20.04で借りてみる
    • Amazon LinuxCentOS系列?らしくパッケージマネージャーがaptじゃないらしい。ので選ばなかった
  • 結果としては失敗だった。
    • 同じエラーが帰ってきた
      • やっぱりAWSが狙い撃ちされているのではとまた考える
  • ここで、別のLinux ディストリビューションを選ぶとどうなるか見てみる
    • Linux ディストリビューションUbuntuだとアクセスできないIPアドレスが払い出されるのではと考えた
    • というわけでAmazon Linuxにしてみました。最新版で
  • Amazon Linux 最新版だとcurlのリクエストが通ることが判明
    • !!!
    • ??????
    • 流石にOSの違いでリクエストの成功に影響するのか...?と考える
  • Ubuntu 22.04 (記述時時点最新版)で試す
    • curlのリクエストが通る
    • この環境にNode.js 16を入れて、リクエストするコードを試してみる
      • 通らない...!!
  • ここで curl だと 200 なのに HTTPクライアント だと 403 になる話が始まる
    • つまり、リクエストの成功にIP アドレスは関係ない。事が判明
      • AWSだからダメではない
  • curlリクエストと同じようにHTTP クライアントのリクエストヘッダーを書いた
    • curl-vをつけるとリクエストの詳細が見えます
      • IP アドレスがブロックされていないことがわかったため、今度はリクエストヘッダーが悪いのではと
        • リクエストヘッダーをcurlが付けているものと同じにしてみる
  • が、、だめ
    • 今度はNode.jsHTTPクライアントライブラリが悪いのではと疑い始める
      • axiosnode-fetchgotNode.js に最初からあるやつを試すも403になる
        • requestってもう非推奨だったんですね... ;;
      • curlでは通ってるのに...!

--- 挫折 ---
いや、流石にこんな事あるか?でもMastodon / MisskeyIssueも見たけどないんだよな。(webfingerとかいうユーザーを探すプロトコルがあるらしい)
Cloudflareがどうやら弾いてるらしい?のでMastodon / Misskeyは関係ないやろと思ったけどなんか1件くらいヒットしてもおかしくないと思うんだけどな...

  • ふと、Node.jsのバージョンを疑い始める
    • きっかけはMisskeyバージョンアップの記事(忘れた...)
    • Ubuntu 20 -> 22にしたらcurlのリクエストが通るようになったのはネットワークスタック周りで更新があったのではと考える
    • Node.jsも更新すれば内部のネットワークスタックが更新され通るようになるのではという予測
      • というかこれしかない
        • 似たようなIssueがないの、私のお一人様はUbuntu 20 / Node.js 16で古いバージョンを使ってる説がある
  • Node.js を 18 にしたら通るようになった!
    • Imgur
    • IP アドレスが狙い撃ちされてるとかAWSだからダメとかCloudflareに嫌われているとかではなく、単に私のサーバーのバージョンが古いからUbuntu 20 / Node.js 16)一部のサーバーのリクエストが403になるみたいでした。
      • ごめんなさい

おわりに

なおってよかった