【実装】リバプロ
概要
Cloudflare Workers を使って リバースプロキシ(リバプロ) を実装する
全体像(通信フロー)
この実装では、 次の流れになります。
クライアント
→ Cloudflare(Workers)
→ オリジン(area11.org)
←
←
Workers の中で fetch() を使い、
オリジンへリクエストを転送します。
実装コード
以下が、今回のリバプロ実装です。
// Cloudflare Workers: Reverse Proxy
// - ORIGIN_HOST を変数(環境変数)として使用
// - アクセス元IPを X-Forwarded-For / X-Real-IP 等に格納
// - Host ヘッダーもオリジン向けに調整
export default {
/**
* @param {Request} request
* @param {{ ORIGIN_HOST: string }} env
* @param {ExecutionContext} ctx
*/
async fetch(request, env, ctx) {
if (!env?.ORIGIN_HOST) {
return new Response("Missing env.ORIGIN_HOST", { status: 500 })
}
const incomingUrl = new URL(request.url)
// オリジン宛URLを組み立て
const originUrl = new URL(request.url)
originUrl.hostname = env.ORIGIN_HOST
// 必要なら originUrl.protocol = "https:" の固定も可能
// クライアントIP取得(Cloudflareが付与)
// 代表例: CF-Connecting-IP
const clientIp =
request.headers.get("CF-Connecting-IP") ||
request.headers.get("True-Client-IP") ||
""
// ヘッダを複製して加工
const headers = new Headers(request.headers)
// 1) Host をオリジン用に差し替え
headers.set("Host", env.ORIGIN_HOST)
// 2) X-Forwarded-For を追記(既存があれば末尾に付与)
// 例: "既存, clientIp"
if (clientIp) {
const xff = headers.get("X-Forwarded-For")
headers.set("X-Forwarded-For", xff ? `${xff}, ${clientIp}` : clientIp)
headers.set("X-Real-IP", clientIp)
}
// 3) Forwarded / X-Forwarded-* を整備
headers.set("X-Forwarded-Host", incomingUrl.host)
headers.set("X-Forwarded-Proto", incomingUrl.protocol.replace(":", ""))
headers.set(
"X-Forwarded-Port",
incomingUrl.port || (incomingUrl.protocol === "https:" ? "443" : "80"),
)
// 任意: 由来が分かるヘッダー(運用・デバッグ用)
headers.set("X-Proxy-By", "cloudflare-worker")
// ボディありメソッドは body を渡す。
// Request.body はストリームなので、
// new Request(originUrl, request) で引き継ぐ形が簡単。
const originRequest = new Request(originUrl.toString(), {
method: request.method,
headers,
body: shouldHaveBody(request.method) ? request.body : null,
redirect: "manual",
})
// オリジンへ転送
const originResponse = await fetch(originRequest)
// レスポンスをそのまま返す(必要ならヘッダー加工も可能)
// Set-Cookie 等を触る場合は attributes や domain に注意
return originResponse
},
}
function shouldHaveBody(method) {
return !["GET", "HEAD"].includes(method.toUpperCase())
}
コードのポイント解説
ORIGIN_HOSTを環境変数にしている
コード中の env.ORIGIN_HOST が、
転送先オリジンのホスト名です。
環境ごとにオリジンを変えたい場合、 コードを書き換えずに切り替えられます。
- クライアント IP は
CF-Connecting-IPを読む
Cloudflare はエッジで、
クライアント IP を CF-Connecting-IP として付与します。
Workers 側では、
その値を X-Forwarded-For / X-Real-IP に入れてオリジンへ渡します。
X-Forwarded-Forは、 既存値がある場合に既存, clientIpとして 追記 しています。- 追記にしておくと、 多段プロキシ構成でも経路を残せます。
Hostをオリジン用に差し替える
オリジンがバーチャルホスト運用(Host でルーティング)している場合に効きます。
- 接続先(
originUrl.hostname) Hostヘッダー
を揃えると、 オリジン側は自然に処理できます。
セキュリティ上の注意点(重要)
- WAF が無い場合、
Worker は入力検証を自動ではしてくれません
- 公開 API なら WAF / Rate Limit / 認証 を併用推奨
X-Forwarded-Forを信頼しすぎない- インターネットから来る
X-Forwarded-Forは偽装可能です - Workers では
CF-Connecting-IPを元に設定し、 オリジン側は「Cloudflare 経由のリクエストだけ」このヘッダーを信頼する設計にします
- インターネットから来る
- Cookie / 認証周り
Set-CookieのDomain/SameSiteは構成によって破綻しやすいので注意
結果
workerの設定

作成したリバプロ経由で無事アクセスできている。

以上。