はじめに
本記事では、認証機能付きの Hono アプリに、IP 制限を導入する方法を紹介します。
特定の IP アドレスのみを許可する (あるいはブロックする) といった設定を行うことで、よりセキュアな環境を実現できます。
1. IP 制限の概要
IP 制限では、クライアントの IP アドレスをチェックし、あらかじめ指定したリストに含まれているかを確認します。
リスト外の場合は即座にエラーを返し、処理を続行しません。
これにより、不正な IP からのアクセスをブロックできます。
2. フロー図
以下の図では、IP フィルタを用いる基本的な流れを示しています。
3. ディレクトリ構成
以前の記事で紹介した構成に、ipFilter.ts を追加します。
my-hono-crud/
├─ .env
├─ package.json
├─ tsconfig.json
├─ src/
│ ├─ index.ts
│ ├─ routes/
│ │ └─ auth.ts
│ └─ middlewares/
│ │ ├─ auth.ts
│ │ ├─ rateLimit.ts
│ │ └─ ipFilter.ts // 今回追加
│ └─ users/
│ └─ index.ts
└─ ...
my-hono-crud/
├─ .env
├─ package.json
├─ tsconfig.json
├─ src/
│ ├─ index.ts
│ ├─ routes/
│ │ ├─ auth.ts
│ │ ├─ user.ts
│ └─ middlewares/
│ ├─ auth.ts
│ ├─ rateLimit.ts
│ ├─ csrf.ts
│ └─ ipFilter.ts
└─ ...
4. 実装例
以下では、許可する IP アドレス一覧 (allowList) をハードコードして、そこに含まれない場合は 403 を返す例を示します。
4-1. src/middlewares/ipFilter.ts
import { Context, Next } from 'hono'
// 許可したいIPアドレスを列挙 (本番環境では.envなどで管理推奨)
const allowList = [
'127.0.0.1',
'192.168.0.10'
]
export const ipFilterMiddleware = async (c: Context, next: Next) => {
// さまざまなヘッダをチェックし、最終的に取得できなければ接続元アドレスを使用
const ip =
c.req.header('x-forwarded-for') ||
c.req.header('CF-Connecting-IP') ||
c.req.header('X-Real-IP') ||
c.req.raw.connection.remoteAddress ||
'unknown'
// リストに含まれていない場合は即座に403
if (!allowList.includes(ip)) {
return c.text('Forbidden: IP not allowed', 403)
}
await next()
}
ポイント:
-
'x-forwarded-for'
のようなヘッダはリバースプロキシや CDN 経由時に使用します。環境に合わせて調整してください。 - 本番環境では、許可リストを直接ソースに書くのではなく、環境変数やデータベースなどで管理する方法がおすすめです。
4-2. src/index.ts への導入
IP 制限を適用したいルートにミドルウェアを挟みます。全体に適用する場合は app.use('*', ipFilterMiddleware)
のように記述し、一部ルートだけに適用する場合はそのルータで router.use('*', ipFilterMiddleware)
を設定します。
import { Hono } from 'hono'
import { loginHandler } from './routes/auth'
import { rateLimitMiddleware } from './middlewares/rateLimit'
import { ipFilterMiddleware } from './middlewares/ipFilter'
import userApp from './users/index'
import 'dotenv/config'
const app = new Hono()
// IP制限を全ルートに適用する例
app.use('*', ipFilterMiddleware)
// レート制限ミドルウェアを全ルートで使用
app.use('*', rateLimitMiddleware)
// ログイン用エンドポイント
app.post('/login', loginHandler)
// ユーザーCRUDなどの変更系操作には CSRF 検証を挟む
app.route('/users', userApp)
export default app
5. 動作確認
IP 制限の確認方法:
- 制限対象外のネットワークからアクセスし、正常に動作することを確認
- 許可リスト以外の IP でリクエストを投げて、403 (Forbidden) が返ることを確認
6. まとめと応用
- IP 制限は、不特定多数のアクセスを制限したい場合や管理画面などの利用が限定的な場面で有効
- 本番環境では、IP アドレスの正確な取得方法やクラウド環境特有のヘッダ (例: X-Forwarded-For) に注意が必要
- CIDR 記法 (例: 192.168.0.0/24) を使ってより幅広いネットワーク帯を制限するなど、細やかな設定も検討可能
これで、Hono アプリへの基本的な IP 制限の導入例は完了です。
他のセキュリティ対策と組み合わせ、総合的にアプリを保護していきましょう。