LoginSignup
14
9

More than 3 years have passed since last update.

Firebase Hosting の一部だけ IP でアクセス制限する

Last updated at Posted at 2019-09-30

内容としてはこれの発展形です。特定のフォルダ内に別なNuxt.jsプロジェクトが入っており、そこをIP制限します。

/index.html   // baseurl のリクエストをさばくファイル
/_nuxt        // baseurl にリクエストされた時に読み込まれるスクリプト
/restrict     // baseurl/restrict にきたアクセスを IP 制限したい
  /index.html // baseurl/restrict のリクエストをさばくファイル
  /_nuxt      // baseurl/restrict にリクエストされた時に読み込まれるスクリプト

TL;DR

認証の窓口となる express サーバーを Cloud Functions で動かして、静的ファイル(今回はビルドされたNuxt.js)をホスティングする。

前提条件

/restrict 配下にアクセスが有った場合のみ IP 制限を実施し、それ以外については制限をかけない。

詳細

IP 制限する Cloud Functions を用意

Firebase は express のインスタンスを onRequest で渡せばよしなに動いてくれるので、IP 制限する express サーバーを用意します。こちらを参考にしました。
https://qiita.com/otakky/items/1363e7b4c706dc9cd096

ipAuth.ts
import * as functions from 'firebase-functions';
import * as requestIp from 'request-ip';
import * as express from 'express';

// ここにアクセスを許可したいIPを記載
const allowedIps = ['192.168.1.1', ...];

const app = express();
app.all('/*', (req, res, next) => {
  const clientIp = requestIp.getClientIp(req);
  const isAllowed = allowedIps.indexOf(clientIp) !== -1;

  if (!isAllowed) {
    res.status(statusCode).send(`You cannot access here. Please check your IP. `);
  } else {
    next();
  }
});
// ホスティングしたい静的ファイルが格納されたフォルダを指定
app.use('/restrict', express.static(`${__dirname}/../restrict/`));

export const ipAuth = functions.https.onRequest(app);

Firebase Hosting の設定を変更

rewrite ルールを使って、経由させたい関数を指定する。

firebase.json
"hosting": {
  /* 中略 */
  "rewrites": [
    {
      "source": "/restrict{,/**}",
      "function": "ipAuth"
    },
    {
      "source": "**",
      "destination": "/index.html"
    }
  ]
  /* 中略 */
}

全体を IP 制限したいのであれば、 2つ目のルールの "destination""function": "ipAuth" にしてあげればよいです。

Nuxt.js の設定

Nuxt.js のビルド結果は絶対パスで生成されるため、ローカルで直接開けば正常に動きますが、ホスティングすると https://BASEURL/_nuxt を参照してしまい、 /restrict 向けのビルド結果を参照できません。それを是正するため、 baseルートを指定します。

nuxt.config.js
export default {
  // 略
  router: {
    base: '/restrict/'
  },
  // 略
}

これで、dist にビルドされる index.html の script タグの参照先は /restrict/_nuxt/hogehoge...js になり、ホスティングされても正しく解釈されるようになります。

デプロイ前調整

/restrict でアクセスされる Nuxt.js のビルド結果を IP 制限用 Cloud Functions の静的ファイルが指し示す場所 ${__dirname}/../restrict/ にコピーしてください。

デプロイ

通常通り firebase deploy で大丈夫です。

ハマりどころ

express-ipfilter を使ってはいけない

何故か Firebase の内部 IP を拾ってしまうようで、どこからアクセスしても 自分のグローバル IP ではないもいの(しかも IPv6 ) を拾ってしまいフィルター出来ませんでした。

express サーバーのパスの指定漏れ

ipAuth.ts
app.use('/restrict', express.static(`${__dirname}/../public/restrict/`));
//       ~~~~~~~~~ これ

全体をIP制限したい場合は未指定 app.use(express.static(...)) でいいのですが、今回は /restrict にアクセスした場合のみ制限するため、これがないとエラーになります。

Hosting の設定

rewrites ルールで "source": "/restrict" と書いてしまうと、/restrict/_nuxt/hogehoge...js すら /restrict にリダイレクトされてしまい、内容が index.html になっている JS が配信されてしまいます。

その他

同じ感じで BASIC 認証も出来ます。express で BASIC 認証する方法を調べれば良いと思います。

デメリット

アクセスする度に Function execution startedFunction execution took xx ms, finished with status code: 200 のログが出力されるので Stackdriverが 汚されます。別にログ取らなくていいんだけどなぁ。。。

それでは!

2020/10/1追記: 他のやり方

身もふたもないですが、プロキシサーバーを用意して、IP制限したいコンテンツだけ別サーバーでホスティングするというのが多分最適解です。
この記事を書くに至ったプロジェクトはプロキシサーバー方式に変更する予定です。

14
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9