增加ip 的白名單

總共7個IP地址,分佈在4個地點:
岡山:1個IP
汐止:2個IP
新竹:2個IP
璟茂:2個IP
This commit is contained in:
2025-08-01 12:59:44 +08:00
parent b261cc277a
commit 2282eed9a1
9 changed files with 8617 additions and 16 deletions

123
middleware.ts Normal file
View File

@@ -0,0 +1,123 @@
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { isIpAllowed, getClientIp } from '@/lib/ip-utils'
export function middleware(request: NextRequest) {
// 檢查是否啟用IP白名單
const enableIpWhitelist = process.env.ENABLE_IP_WHITELIST === 'true'
if (!enableIpWhitelist) {
return NextResponse.next()
}
// 獲取客戶端IP
const clientIp = getClientIp(request)
// 獲取允許的IP列表
const allowedIps = process.env.ALLOWED_IPS || ''
// 檢查IP是否被允許
if (!isIpAllowed(clientIp, allowedIps)) {
// 記錄被拒絕的訪問
console.warn(`Access denied for IP: ${clientIp} - Path: ${request.nextUrl.pathname}`)
// 返回403禁止訪問頁面
return new NextResponse(
`
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>訪問被拒絕</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
color: white;
}
.container {
text-align: center;
background: rgba(255, 255, 255, 0.1);
padding: 3rem;
border-radius: 1rem;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
max-width: 500px;
margin: 1rem;
}
h1 {
font-size: 2rem;
margin-bottom: 1rem;
color: #ff6b6b;
}
p {
font-size: 1.1rem;
line-height: 1.6;
margin-bottom: 1rem;
opacity: 0.9;
}
.ip-info {
background: rgba(255, 255, 255, 0.1);
padding: 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
font-family: 'Courier New', monospace;
}
.contact {
font-size: 0.9rem;
opacity: 0.7;
margin-top: 2rem;
}
</style>
</head>
<body>
<div class="container">
<h1>🚫 訪問被拒絕</h1>
<p>很抱歉您的IP地址不在允許的訪問列表中。</p>
<div class="ip-info">
<strong>您的IP地址</strong><br>
${clientIp}
</div>
<p>如果您認為這是一個錯誤,請聯繫系統管理員。</p>
<div class="contact">
錯誤代碼403 Forbidden<br>
時間:${new Date().toLocaleString('zh-TW')}
</div>
</div>
</body>
</html>
`,
{
status: 403,
headers: {
'Content-Type': 'text/html; charset=utf-8',
},
}
)
}
// IP檢查通過繼續處理請求
return NextResponse.next()
}
// 配置中間件適用的路徑
export const config = {
matcher: [
/*
* 匹配所有路徑,除了:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - icon.png (icon file)
*/
'/((?!api|_next/static|_next/image|favicon.ico|icon.png).*)',
],
}