增加ip 的白名單
總共7個IP地址,分佈在4個地點: 岡山:1個IP 汐止:2個IP 新竹:2個IP 璟茂:2個IP
This commit is contained in:
93
lib/ip-utils.ts
Normal file
93
lib/ip-utils.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* IP 白名單檢查工具
|
||||
*/
|
||||
|
||||
// 檢查IP是否在指定範圍內
|
||||
function isIpInRange(ip: string, range: string): boolean {
|
||||
// 處理單一IP
|
||||
if (!range.includes('/')) {
|
||||
return ip === range;
|
||||
}
|
||||
|
||||
// 處理CIDR範圍 (例如: 192.168.1.0/24)
|
||||
const [rangeIp, prefixLength] = range.split('/');
|
||||
const mask = parseInt(prefixLength);
|
||||
|
||||
if (isNaN(mask) || mask < 0 || mask > 32) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ipNum = ipToNumber(ip);
|
||||
const rangeNum = ipToNumber(rangeIp);
|
||||
const maskNum = (0xFFFFFFFF << (32 - mask)) >>> 0;
|
||||
|
||||
return (ipNum & maskNum) === (rangeNum & maskNum);
|
||||
}
|
||||
|
||||
// 將IP地址轉換為數字
|
||||
function ipToNumber(ip: string): number {
|
||||
const parts = ip.split('.').map(part => parseInt(part));
|
||||
if (parts.length !== 4 || parts.some(part => isNaN(part) || part < 0 || part > 255)) {
|
||||
throw new Error(`Invalid IP address: ${ip}`);
|
||||
}
|
||||
return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3];
|
||||
}
|
||||
|
||||
// 檢查IP是否在白名單內
|
||||
export function isIpAllowed(clientIp: string, allowedIps: string): boolean {
|
||||
if (!allowedIps || allowedIps.trim() === '') {
|
||||
return true; // 如果沒有設置白名單,允許所有IP
|
||||
}
|
||||
|
||||
const allowedIpList = allowedIps.split(',').map(ip => ip.trim()).filter(ip => ip);
|
||||
|
||||
for (const allowedIp of allowedIpList) {
|
||||
try {
|
||||
if (isIpInRange(clientIp, allowedIp)) {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Invalid IP range: ${allowedIp}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 獲取客戶端真實IP
|
||||
export function getClientIp(req: any): string {
|
||||
// 檢查各種可能的IP來源
|
||||
const ipSources = [
|
||||
req.headers['x-forwarded-for'],
|
||||
req.headers['x-real-ip'],
|
||||
req.headers['x-client-ip'],
|
||||
req.headers['cf-connecting-ip'], // Cloudflare
|
||||
req.connection?.remoteAddress,
|
||||
req.socket?.remoteAddress,
|
||||
req.ip
|
||||
];
|
||||
|
||||
for (const ipSource of ipSources) {
|
||||
if (ipSource) {
|
||||
// 處理多個IP的情況 (例如: "192.168.1.1, 10.0.0.1")
|
||||
const firstIp = ipSource.toString().split(',')[0].trim();
|
||||
if (firstIp && firstIp !== '::1' && firstIp !== '127.0.0.1') {
|
||||
return firstIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '127.0.0.1'; // 默認本地IP
|
||||
}
|
||||
|
||||
// 驗證IP地址格式
|
||||
export function isValidIp(ip: string): boolean {
|
||||
const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
return ipRegex.test(ip);
|
||||
}
|
||||
|
||||
// 驗證CIDR格式
|
||||
export function isValidCidr(cidr: string): boolean {
|
||||
const cidrRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
||||
return cidrRegex.test(cidr);
|
||||
}
|
Reference in New Issue
Block a user