言語を切り替える
テーマを切り替える

APIキー流出で請求額がヤバいことに?Workersプロキシで5分で作る鉄壁のセキュリティ

はじめに

先月、ChatGPT APIを使ったちょっとしたツールを作りました。面倒だったので、APIキーをフロントエンドのコードに直接書いてデプロイしました。翌朝、目が覚めるとアカウントから300ドル(約4.5万円)が消えていました。

管理画面を見ると、一晩で数千回ものAPI呼び出しがありました。慌ててキーを再生成しましたが、根本的な問題は解決していません。フロントエンドにキーがある限り、いつでも盗まれるリスクがあります。

.envファイルを使えば安全でしょ?」と思うかもしれませんが、ViteやWebpackでビルドすると、環境変数はJSファイルの中に文字列として埋め込まれます。ブラウザのF12キーを押してNetworkタブを見れば、誰でもあなたのAPIキーを取得できてしまうのです。

解決策は「バックエンドサーバーを立ててキーを隠す」ことですが、個人開発でわざわざサーバーを借りて(月額コストがかかる)、Node.jsやSSL証明書の設定をするのは重すぎます。

そこで出会ったのが Cloudflare Workers です。5分でAPIプロキシを構築でき、APIキーはサーバー側の環境変数として安全に保存されます。しかも完全無料で、毎日10万回のリクエストまでOK。CORS(クロスドメイン)問題もついでに解決できます。

この記事では、この「無料かつ最強のAPIキー保護策」の構築手順を、コピー&ペーストで動くコードと共に紹介します。

なぜフロントエンドにキーを置いてはいけないのか

コードは全て筒抜け

フロントエンドのコードは、ユーザーのブラウザ上で実行されます。つまり、ユーザーはあなたが書いた全てのコードを見ることができます。難読化や圧縮をしても、APIリクエストを送信する瞬間には生のAPIキーが必要になるため、Networkタブを見れば一発でバレます。

盗難の被害は甚大

GitHubには、公開コードからAPIキーを自動で収集するボットが巡回しています。見つかったキーは、攻撃者に売られるか、高価なAIモデルの利用(タダ乗り)に使われます。OpenAIやGoogle Mapsのような従量課金制のAPIの場合、被害額は青天井になる可能性があります。

従来のサーバー構築は面倒すぎる

「バックエンドを立てる」のが正攻法ですが、デメリットが多すぎます:

  • コスト: 安いVPSでも月額500〜1000円。
  • 手間: OSセットアップ、Nginx設定、SSL証明書更新、セキュリティパッチ…。
  • 保守: サーバーが落ちたら再起動が必要です。

Cloudflare Workersが最適な理由

無料で高性能

Cloudflare Workersの無料プランは1日10万リクエストまで使えます。個人開発や小規模なサービスなら、まず使い切ることはありません。

10万回/日
無料枠
個人開発には十分すぎる容量
5分
デプロイ
環境構築不要、コマンド一発
¥0
コスト
サーバー代もSSL代も不要

さらに、世界200箇所以上のデータセンターで実行されるため、ユーザーの近くのサーバーが自動的に応答し、遅延(レイテンシ)も極小です。コールドスタート(サーバーの起動待ち時間)もほぼありません。

デプロイが爆速

サーバー設定は一切不要。

  1. コードを書く(JSファイル1つ)
  2. wrangler deploy コマンドを叩く
    これだけで、HTTPS対応のAPIサーバーが世界中に公開されます。

CORS問題も解決

フロントエンドから外部APIを叩くとよく出る「CORSエラー」。これもWorkersを経由させることで、自分のサーバーとして振る舞えるため、簡単に回避できます。

実践:5分で作るAPIプロキシ

OpenAI APIを例に、安全なプロキシを作ってみましょう。

Step 1: 準備

1. Cloudflareアカウント作成
cloudflare.com で無料アカウントを作ります。

2. Wrangler CLIインストール

npm install -g wrangler

3. ログイン

wrangler login

ブラウザが開くので「Allow」をクリック。

Step 2: プロジェクト作成

wrangler init openai-proxy

質問には以下のように回答:

  • TypeScript? → No(慣れていればYesでもOK)
  • Create Worker? → Yes
  • Install dependencies? → Yes

Step 3: コード作成

src/index.js を以下のコードに書き換えます。

export default {
  async fetch(request, env) {
    // POSTリクエストのみ許可
    if (request.method !== 'POST') {
      return new Response('Method not allowed', { status: 405 });
    }

    // 環境変数からAPIキーを取得
    const apiKey = env.OPENAI_API_KEY;
    if (!apiKey) {
      return new Response('API Key not configured', { status: 500 });
    }

    try {
      // フロントエンドからのデータを受け取る
      const body = await request.json();

      // 本物のOpenAI APIを呼び出す
      const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${apiKey}`,  // ここでサーバー側キーを使用
        },
        body: JSON.stringify(body),
      });

      // レスポンスを取得
      const data = await response.json();

      // フロントエンドに返す(CORSヘッダー付き)
      return new Response(JSON.stringify(data), {
        status: response.status,
        headers: {
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': '*',  // 全ドメイン許可(必要に応じて制限)
          'Access-Control-Allow-Methods': 'POST',
          'Access-Control-Allow-Headers': 'Content-Type',
        },
      });

    } catch (error) {
      return new Response(JSON.stringify({ error: error.message }), {
        status: 500,
        headers: { 'Content-Type': 'application/json' },
      });
    }
  },
};

Step 4: APIキーを安全に保存

ここが最重要です。コードにはキーを書かず、CloudflareのSecrets(暗号化ストレージ)に保存します。

wrangler secret put OPENAI_API_KEY

コマンド実行後、あなたのOpenAI APIキー(sk-...)を入力します。これでキーは暗号化され、安全に保管されます。

Step 5: デプロイ

wrangler deploy

完了すると、https://openai-proxy.あなたのサブドメイン.workers.dev というURLが発行されます。

あとはフロントエンドのコードで、APIの宛先をこのURLに変更するだけです。キーを渡す必要はありません。

さらなるセキュリティ対策

上記のままだと、エンドポイントを知っている人は誰でもあなたのAPIキーを使って勝手にリクエストを送れてしまいます。以下の対策を追加しましょう。

1. 独自のトークン認証

フロントエンドとWorkersだけで共有する「合言葉」を設定します。

// Workers側
if (request.headers.get('X-My-Token') !== env.MY_SECRET_TOKEN) {
  return new Response('Unauthorized', { status: 401 });
}

wrangler secret put MY_SECRET_TOKEN で合言葉を設定し、フロントエンドのリクエストヘッダーに含めます。

2. リファラー/オリジン制限

自分のサイトから来たリクエストだけを許可します。

const allowedOrigin = 'https://mysite.com';
if (request.headers.get('Origin') !== allowedOrigin) {
  return new Response('Forbidden', { status: 403 });
}

よくある質問

Q: 無料枠を超えたらどうなりますか?
A: リクエストが拒否されます。勝手に課金されることはありません。必要であれば月額5ドルの有料プランにすれば、リクエスト数は1000万回/月に増えます。

Q: 自分のドメインは使えますか?
A: はい、Cloudflareダッシュボードからカスタムドメインをバインドできます。設定は数分で反映され、自動的にSSL化されます。

Q: 速度は遅くなりませんか?
A: Cloudflareのエッジネットワークは非常に高速なので、ボトルネックになることは稀です。多くの場合、海外にあるAPIサーバーに直接アクセスするより、Cloudflareの最適化されたルートを経由するほうが安定します。

まとめ

APIキーの流出は、開発者が最も恐れる「クラウド破産」の入り口です。
「面倒だから」と後回しにせず、Cloudflare Workersを使って今すぐ安全な環境を作りましょう。5分もあれば、夜も安心して眠れるようになります。

Cloudflare Workers APIプロキシ構築手順

APIキーを隠蔽するための安全なプロキシサーバーを構築するフロー

⏱️ Estimated time: 5 min

  1. 1

    Step1: Wranglerのインストールとログイン

    npm install -g wrangler でツールをインストールし、wrangler login でCloudflareアカウントにログインします。
  2. 2

    Step2: プロジェクト作成

    wrangler init コマンドで新しいWorkersプロジェクトを作成します。
  3. 3

    Step3: コードの実装

    src/index.js にプロキシロジックを記述します。リクエストを受け取り、環境変数のAPIキーを使って外部APIを叩き、結果を返す処理です。
  4. 4

    Step4: APIキーの保存

    wrangler secret put <KEY_NAME> コマンドを使って、APIキーを暗号化してCloudflare上に保存します。コード内には書きません。
  5. 5

    Step5: デプロイ

    wrangler deploy コマンドを実行して、世界中のエッジサーバーにコードを配信します。

FAQ

なぜフロントエンドにAPIキーを置いてはいけないのですか?
フロントエンドのコードはユーザーのブラウザにダウンロードされて実行されるため、誰でも中身を見ることができます。難読化しても通信内容は隠せないため、APIキーは簡単に盗まれてしまいます。
プロキシサーバーを立てるコストはかかりますか?
Cloudflare Workersを使えば、1日10万リクエストまで無料で利用できます。仮想サーバー(VPS)を借りる必要がないため、維持費は0円です。
CORSエラーの解決にもなりますか?
はい、Workers側で適切な `Access-Control-Allow-Origin` ヘッダーを付与してレスポンスを返すことで、フロントエンドでのCORSエラーを完全に回避できます。

3 min read · 公開日: 2025年12月1日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事