ウェブスクレイピングのためのNode-Unblocker: セットアップ、セキュリティリスクとより良い代替手段
Senior Cybersecurity Analyst
TL;DR:
- Node-UnblockerはExpress互換のライブラリで、リモートウェブページをプロキシおよび書き換えします。シンプルなページでのURL書き換えを示すことができますが、現代のアンチボットソルバーや一般的なJavaScriptブラウザではありません。
- 現在のデプロイメントのベースラインとしてNode.js 24 LTSを使用してください。オンラインにまだ存在する古いNode.js 16の例はサポート終了です。
- デモサーバーを
127.0.0.1にバインドし、ホワイトリストを要求し、認証されていないオープンプロキシを決して公開しないでください。ユーザー制御の宛先はサーバーサイドリクエストフォージェリ、内部ネットワーク、資格情報、悪用、ログ記録のリスクを生み出します。 - OAuth、
postMessage、オリジンに敏感なコード、複雑なサイト、および現代のアプリケーションの動作は失敗する可能性があります。レスポンスの書き換えは、ターゲットを元のブラウザのオリジンで実行するのとは異なるためです。 - 認可を受けたスクレイピングの場合、Node-Unblockerの書き換えモデルが本当に適合する場合にのみ選択してください。希望する結果がページデータである場合、管理されたスクレイピングAPIの方が通常は良い境界です。
Node-Unblockerは簡単にデモできます:Expressをインストールし、ミドルウェアオブジェクトをマウントし、リモートURLをローカルパスで接頭辞を付けます。そのシンプルさは、本当のエンジニアリングの問題を隠すことがあります。
このプロジェクトはウェブプロキシおよびレスポンス書き換えライブラリです。完全な現代ブラウザのセキュリティモデルを再現したり、現代のアンチボットシステムを解決するために設計されたものではありません。任意の宛先URLを受け入れるサービスになると、高リスクのネットワーク境界にもなります。
このガイドは、ローカルホスト専用のセットアップを示し、Node-Unblockerが失敗する場所を説明し、ウェブスクレイピングのためのセキュリティおよびビルド対管理の意思決定モデルを提供します。
Node-Unblockerとは?
Node-Unblockerは、unblockerとしてnpmに公開されているNode.jsライブラリで、リモートウェブページをプロキシおよび書き換えます。ブラウザがプロキシパスを通じてナビゲーションし続けるように、リンクやリソースURLを変更できます。
プロジェクトの公式リポジトリは、一般的なプロキシおよびページ書き換えライブラリとして説明しています。文書化された制限にはOAuthフロー、postMessage、およびいくつかの複雑なウェブサイトが含まれます。このパッケージはAGPL-3.0の下でリリースされているため、プロダクションチームは法律顧問と共にライセンス義務を確認するべきです。
現在のnpmパッケージレコードにはバージョン2.3.1がリストされています。レジストリアクティビティとメンテナンスのペースも採用レビューの一部とするべきです。成功したインストールはプロキシが製品準備完了であることの証拠ではありません。
Node-Unblockerは以下を行うことができます:
- HTTPリクエストをリモートページに転送する;
- レスポンスの部分をリレーおよび書き換える;
- リンクを接頭辞付きで提供し、後のナビゲーションがプロキシパス下に留まるようにする;
- Expressミドルウェアと統合する;
- 一部のWebSocketアップグレードを処理する。
自動的には以下は行いません:
- クライアントサイドのJavaScriptをサーバー上で実行する;
- すべてのブラウザオリジンおよびセキュリティ仮定を保持する;
- CAPTCHAや高度なトラフィック検証を解決する;
- 宛先を制限する;
- テナント認証を追加する;
- ユーザー制御のURLから内部ネットワークを保護する;
- 住宅プロキシプールや地域ターゲティングを提供する;
- 戻ってきたページが望ましいデータを含んでいることを検証する。
現在のNode.jsベースラインを使う
古いデプロイメントファイルをコピーするのではなく、サポートされているLTSリリースを使用してください。公式Node.jsリリーステーブルによれば、執筆時点でNode.js 24はLTSであり、Node.js 16はサポート終了しています。
このチュートリアルでは以下を使用します:
- Node.js 24 LTS;
- Express 5.2.1;
unblocker2.3.1;- localhostバインディング;
- 固定の宛先ホワイトリスト。
プロジェクトを作成します:
bash
mkdir node-unblocker-local-demo
cd node-unblocker-local-demo
npm init -y
npm install express@5.2.1 unblocker@2.3.1
npm pkg set private=true
npm pkg set engines.node=">=24 <25"
バージョンピンニングにより、デモが再現可能になります。npm auditを実行し、依存関係グラフを確認し、各デプロイメントイメージが昇格される前にレビューを繰り返します。
ローカルホスト専用のNode-Unblockerデモを作成する
以下のコードは意図的に制約を設けています。ループバックにバインドし、2つのドキュメンテーションドメインのみを許可し、非HTTPプロトコルを拒否し、URLの長さを制限し、Expressの識別ヘッダーを無効にします。
これは実行中のローカルデモであり、完全なプロダクションのSSRF防御ではありません。プロダクションプロキシには、認証、出口ファイアウォールルール、DNSコントロール、リソース制限、モニタリング、および悪用応答も必要です。
javascript
"use strict";
const express = require("express");
const Unblocker = require("unblocker");
const app = express();
const port = Number(process.env.PORT || 8080);
const prefix = "/proxy/";
const allowedHosts = new Set(["example.com", "www.iana.org"]);
const unblocker = new Unblocker({ prefix });
app.disable("x-powered-by");
app.get("/healthz", (_req, res) => {
res.json({ status: "ok" });
});
app.use((req, res, next) => {
if (!req.originalUrl.startsWith(prefix)) {
return next();
}
ja
const rawTarget = req.originalUrl.slice(prefix.length);
if (rawTarget.length > 2048) {
return res.status(414).send("ターゲットURLが長すぎます");
}
let target;
try {
target = new URL(rawTarget);
} catch {
return res.status(400).send("無効なターゲットURLです");
}
if (!["http:", "https:"].includes(target.protocol)) {
return res.status(400).send("プロトコルは許可されていません");
}
if (!allowedHosts.has(target.hostname)) {
return res.status(403).send("ターゲットホストは許可されていません");
}
return next();
});
app.use(unblocker);
app.use((_req, res) => {
res.status(404).send("見つかりませんでした");
});
const server = app.listen(port, "127.0.0.1", () => {
console.log(`ローカルプロキシ: http://127.0.0.1:${port}${prefix}`);
});
server.on("upgrade", unblocker.onUpgrade);
ファイルを server.js として保存し、次のように実行します:
bash
node --check server.js
node server.js
ループバックバインドは見た目上のものではありません。 app.listen(port) は、環境によっては利用可能なすべてのインターフェイスでリッスンでき、これによりプロキシがローカルネットワークやコンテナのインパクトにさらされる可能性があります。
プロキシをローカルでテストする
2つ目のターミナルを開きます:
bash
curl --fail http://127.0.0.1:8080/healthz
curl --fail "http://127.0.0.1:8080/proxy/https://example.com/"
curl -i "http://127.0.0.1:8080/proxy/https://invalid.example/"
ヘルスチェックはJSONを返すべきです。許可リストに載っている例のページは中継されるべきです。承認されていないホスト名はHTTP 403レスポンスを受け取るべきです。
ブラウザの開発者ツールを使用して検査します:
- どのリンクが書き換えられたか;
- スタイルシートや画像がまだ読み込まれるか;
- リダイレクトが範囲内にあるか;
- クッキーや認証ヘッダーがあるか;
- ページがクライアントサイドのAPI呼び出しに依存しているか;
- 最終的なコンテンツが期待されるページと一致するか。
アカウントの資格情報を使用してテストしないでください。プロキシはヘッダー、ボディ、クッキー、クエリパラメータ、宛先URLを観察することがあります。
Node-Unblockerの書き換え動作
高いレベルでは:
- Expressが構成されたプレフィックスの下でリクエストを受け取ります。
- Node-Unblockerがリモートターゲットを抽出します。
- サーバーがそのターゲットにリクエストを送信します。
- ライブラリがレスポンスヘッダーとコンテンツを中継します。
- サポートされているコンテンツの場合、後でブラウザのリクエストが同じプレフィックスを通過できるようにURLを書き換えます。
このモデルは、通常のリンクやフォームを持つ従来のページに最も適しています。ページが次のことに依存すると脆弱になります:
- 厳格なコンテンツセキュリティポリシー;
- オリジンチェック;
- 署名済みまたは期限切れのリソースURL;
- サービスワーカー;
- クロスウィンドウメッセージング;
- 動的に構築されたエンドポイント;
- 複雑なWebSocketの動作;
- 元のオリジンに結びつくブラウザストレージ;
- OAuthリダイレクト;
- ネットワーク、TLS、JavaScript、動作をまとめて評価するボット防止システム。
レスポンス内のテキストを書き換えることでこれらの関係を再現することはできません。
WebスクレイピングにおけるNode-Unblockerの制限
ブラウザレンダラーではない
Node-Unblockerはコンテンツを中継して書き換えます。クライアント側のJavaScriptはユーザーのブラウザで実行されるかもしれませんが、プロキシサーバーはデータパイプラインのためのレンダリングされたDOMを生成する孤立したブラウザランタイムを提供しません。
スクレイパーがJavaScriptの実行後に生成された製品グリッドが必要な場合、プレーンなプロキシのレスポンスにはアプリケーションシェルしか含まれていない可能性があります。
OAuthとpostMessageが壊れることがある
OAuthは登録されたリダイレクトURL、オリジンチェック、クッキー、およびクロスサイトルールに依存しています。 postMessageはウィンドウのオリジンに依存します。プロキシオリジンの下でページを書き換えることで、それらの仮定が変更されるため、認証および埋め込まれたアプリケーションが失敗する可能性があります。
複雑なサイトは不完全な場合がある
現代のアプリケーションはHTML、JavaScriptバンドル、API呼び出し、ワーカー、ストレージ、およびWebSocketにわたって作業を分散させています。一部のURLは書き換えられるかもしれませんが、他のランタイム生成リクエストはプロキシパスを逃れるか、ターゲットのポリシーに違反します。
IPの多様性を供給しない
自己ホスト型のNode-Unblockerインスタンスは、他のルーティング層が追加されない限り、そのホストのネットワークIDを使用します。これは、住宅用、モバイル、ISP、地域ターゲットのIPプールを含みません。
メンテナンスはオペレーターの責任
オペレーターはNode.jsのセキュリティ更新、npmの依存関係、プロキシ容量、宛先ポリシー、TLS構成、認証、ログ、インシデント対応、クラウドプロバイダーの条項、および悪用報告を管理します。これは、ミドルウェアが小さい場合でも、重要なサービスです。
オープンプロキシおよびSSRFリスク
ユーザー提供のURLを取得するサービスは、ユーザーが直接アクセスできない場所に到達するために使用される可能性があります。これが、サーバーサイドリクエストフォージェリの中心的なリスクです。
OWASP SSRF防止チートシートは、目的地が知られている場合に許可リストを推奨し、アプリケーションとネットワークの両方の層での防御の深さを推奨しています。また、ループバックプライベートアドレス範囲、リンクローカルアドレス、およびクラウドメタデータサービスを強調しています。
公開されたプロキシは次のように悪用される可能性があります:
- プライベートサービスをスキャンすることができます;
- クラウドインスタンスメタデータにアクセスする;
- 認証情報やアクセストークンを盗む;
- 操作員のIPの背後に悪用トラフィックを隠す;
- 帯域幅とコンピュータリソースを消費する;
- 禁止されたコンテンツを中継する;
- 敏感なリクエストとレスポンスデータをキャプチャする;
- 操作員に法的およびクラウドアカウントのリスクをもたらす。
ホスト名の拒否リストは不十分です。DNSは検証と接続の間に変更される可能性があり、リダイレクトは別のホストに移動することができます。また、異常なIP表記は単純な文字列チェックを回避することができ、IPv6は扱うべきアドレス形式を拡張します。
## セキュアなデプロイメントチェックリスト
プロダクションユースケースがNode-Unblockerの使用を正当化する場合、セキュリティに敏感なネットワークサービスとして扱います:
- **デフォルトではプライベートに保つ。** ループバックまたはプライベートインターフェースにバインドします。
- **強力な認証を要求する。** 短命のサービス認証情報とテナント認可を使用します。
- **宛先の許可リストを優先する。** ビジネスワークフローが必要とする正確なホストとポートを定義します。
- **アウトバウンドポリシーを強制する。** ネットワーク層でループバック、プライベートネットワーク、リンクローカルレンジ、メタデータサービスをブロックします。
- **DNS解決の後に検証する。** すべての解決されたアドレスがグローバルにルーティング可能で承認されていることを確認します。
- **リダイレクトを制御する。** 各リダイレクトで宛先を再評価します。
- **メソッドとプロトコルを制限する。** ワークフローが必要としないものは拒否します。
- **ボディ、ヘッダー、URL、時間、および同時実行制限を設定する。**
- **認証情報を保護する。** 明示的に必要とされない限り、受信認証ヘッダーを削除します。
- **ログを最小限に抑える。** デフォルトではトークン、クッキー、完全なクエリ文字列、またはレスポンスボディを保存しないでください。
- **テナントを分離する。** 1つの顧客のセッションやクッキーが他の顧客に届くことは決してありません。
- **ランタイムと依存関係をパッチする。**
- **クラウドプロバイダーの適正使用方針を見直す。**
- **不正使用検出とシャットダウン経路を追加する。**
JavaScriptの許可リストは一層に過ぎません。アプリケーションの検証が失敗した場合でも、ネットワークポリシーは有効でなければなりません。
> 目的がプロキシサービスの運営ではなく認可されたページデータである場合、Node-Unblockerをセキュリティと維持の全コストと比較してください。
## Node-Unblockerと管理されたスクレイピングAPIの比較
| 決定領域 | Node-Unblocker | 管理されたスクレイピングAPI |
|---|---|---|
| プライマリモデル | 自己ホスティングのプロキシとレスポンスの書き換え | APIを通じたページ取得リクエスト |
| JavaScriptレンダリング | サーバー自体では提供されていない | 選択したAPI機能がサポートしている場合に利用可能 |
| IPプール | 別途設定しない限りホストIP | プロバイダー管理のルーティングオプション |
| 宛先のセキュリティ | 操作員の責任 | プロバイダーがそのサービスを確保; クライアントはターゲット範囲を制御 |
| ブラウザ互換性 | 書き換えモデルに制限される | レンダリングされたページ取得により適している |
| インフラストラクチャの所有権 | Nodeサービス、ネットワーク、スケーリング、ログ、インシデント | API統合、検証、使用管理 |
| ベストフィット | プライベート、狭い、許可リストに載せられた書き換えユースケース | アウトプットがプロキシ操作よりも重要な認可されたデータ収集 |
Node-Unblockerを選択するのは次の場合です:
- 宛先セットが小規模で固定されている;
- 書き換え動作がサポートされるすべてのページに対してテストされた;
- サービスがプライベートに保持される;
- チームがネットワークセキュリティとインシデント対応を所有できる;
- 従来のプロキシページが実際の製品要件である。
管理された取得レイヤーを選択するのは次の場合です:
- 希望する成果物がHTML、Markdown、または構造化されたページデータである;
- ターゲットがレンダリングまたは特化したトラフィック処理を必要とする;
- 地域とネットワークの選択が重要;
- セキュアなプロキシの維持が製品のコアバリューの範囲外;
- チームが明示的な検証を伴うAPI契約を望む。
## Universal Scraping APIを通じてScrapeless Web Unlockerを利用する
Scrapelessは、[Universal Scraping APIのドキュメント](https://docs.scrapeless.com/en/universal-scraping-api/quickstart/introduction?utm_source=website&utm_medium=blog&utm_campaign=universalscrapingapi&utm_term=node-unblocker)を通じてWeb Unlockerアクターを公開しています。このアプリケーションは、認可されたターゲットURLを送信し、返されたペイロードを検証します。
このリクエストには、リーダー所有の`SCRAPELESS_API_KEY`と`TARGET_URL`が必要です:
```bash
curl --request POST "https://api.scrapeless.com/api/v1/scraper/request" \
--header "Content-Type: application/json" \
--header "x-api-token: ${SCRAPELESS_API_KEY}" \
--data "{
\"actor\": \"unlocker.webunlocker\",
\"input\": {
\"url\": \"${TARGET_URL}\"
}
}"
クライアントはまだ以下が必要です:
- ユーザーが送信できるURLを制限する;
- APIキーをブラウザコードから外に保持する;
- リクエストと費用の予算を設定する;
- ページのアイデンティティと必要なフィールドを検証する;
- 予期しない出力を検疫する;
- 法律、サイト条件、ロボット指令、プライバシー要件に準拠する。
防御的な取得アーキテクチャの概要については、分散型ウェブクローラーの構築方法を読んでください。ルーティングの基本については、プロキシが使用される理由をご覧ください。
展開の意思決定フレームワーク
5つの質問を使います:
- 出力は何ですか? ブラウザで表示できる再構成されたページ、生データのHTML、レンダリングされたコンテンツ、または構造化されたレコードですか?
- 行き先を選べるのは誰ですか? 固定内部ジョブまたは信頼できない外部ユーザーですか?
- 必要なブラウザの動作は何ですか? 静的リンク、JavaScriptレンダリング、OAuth、WebSockets、または元のオリジンの実行ですか?
- セキュリティ操作を所有しているのは誰ですか? アプリケーションエンジニア、プラットフォームチーム、またはマネージドプロバイダーですか?
- 成功はどのように測定されますか? プロキシの稼働時間または受け入れられた、検証済みのレコードですか?
ほとんどのスクレイピングチームにとって、5番目の質問が決定的です。ビジネスの指標が完全なレコードであるならば、オープンエンドのプロキシサービスを運営することは作業を増やすだけで、データ契約を改善することにはつながりません。
業務に合った境界を選ぶ
Node-Unblockerは、プロキシの書き換えを理解し、狭いプライベートワークフローに役立ちます。普遍的なアンブロッカー、ヘッドレスブラウザー、または安全なパブリックプロキシとして提示すべきではありません。
デモはローカルホストで行ってください。実際のアプリケーションで必要な場合は、デプロイ前に認証、厳格な行き先、ネットワーク出口ポリシー、制限されたリソース、安全なログ、インシデント計画を追加してください。
望ましい結果が認可されたウェブデータである場合は、Scrapelessの価格を比較し、その後、Scrapelessアカウントを作成し、ユニバーサルスクレイピングAPIを通じて一つの代表的なターゲットをテストしてください。リクエストがHTTP 200を返したかどうかだけでなく、コンテンツ受け入れとエンジニアリングの所有権を測定してください。
よくある質問
Node-Unblockerは何に使われますか?
Node-Unblockerは、リクエストを転送し、リモートページを書き換えるNode.jsウェブプロキシを構築するために使用されます。制御されたプライベートな使ケースに最適です。
Node-Unblockerはヘッドレスブラウザーですか?
いいえ。プロキシと書き換えのミドルウェアです。ページを実行してレンダリングされたDOMを返すサーバーサイドブラウザーは提供しません。
Node-Unblockerは現代のアンチボットシステムに対応できますか?
信頼性はありません。現代の防御はIPの評判、TLSの詳細、ブラウザの状態、JavaScriptの信号、クッキー、および動作を評価できます。Node-Unblockerはその完全なシステムを管理しません。
Node-Unblockerを公開するのは安全ですか?
認証されていないオープンプロキシを公開するべきではありません。ユーザーが制御する行き先は、SSRF、プライベートネットワーク、クラウドメタデータ、悪用、認証情報、およびログのリスクを引き起こします。プライベートに保ち、認証、許可リスト、ネットワーク層の出口制御を適用してください。
なぜOAuthとpostMessageページはNode-Unblockerを通じて失敗するのですか?
これらのシステムはオリジン、登録されたリダイレクト、クッキー、ウィンドウ間の信頼に依存しています。プロキシオリジンの下でページを提供すると、セキュリティコンテキストが変更され、フローが崩れる可能性があります。
ウェブスクレイピングに適したより良い代替は何ですか?
目的がページのコンテンツや構造化データである場合は、利用可能であれば認可されたソースAPIを使用するか、必要なレンダリングとルーティングをサポートするマネージドスクレイピングAPIを使用してください。ターゲットのポリシー、検証、ストレージ、およびコンプライアンスをクライアントアプリケーションに保持してください。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



