updated code
This commit is contained in:
parent
4ae7a41554
commit
d4b9b2eb50
1 changed files with 78 additions and 9 deletions
85
src/index.ts
85
src/index.ts
|
|
@ -21,16 +21,64 @@ const NODE_ENV = process.env.NODE_ENV || 'production';
|
||||||
|
|
||||||
const objs: ApiResponse[] = []
|
const objs: ApiResponse[] = []
|
||||||
|
|
||||||
// Create Fastify instance with trust proxy enabled
|
// Create Fastify instance with comprehensive trust proxy
|
||||||
const fastify = Fastify({
|
const fastify = Fastify({
|
||||||
logger: NODE_ENV === 'development',
|
logger: NODE_ENV === 'development',
|
||||||
trustProxy: process.env.TRUST_PROXY === 'true' || true
|
trustProxy: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.1', '::1'] // Trust k8s networks
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Enhanced IP detection function
|
||||||
|
function getClientIP(request: FastifyRequest): string {
|
||||||
|
const headers = request.headers;
|
||||||
|
|
||||||
|
// Try multiple headers in order of preference
|
||||||
|
const ipSources = [
|
||||||
|
headers['cf-connecting-ip']?.toString(), // Cloudflare
|
||||||
|
headers['true-client-ip']?.toString(), // Akamai/other CDNs
|
||||||
|
headers['x-forwarded-for']?.toString().split(',')[0]?.trim(), // Most common
|
||||||
|
headers['x-client-ip']?.toString(), // Apache
|
||||||
|
headers['x-cluster-client-ip']?.toString(), // Cluster
|
||||||
|
headers['forwarded']?.toString().match(/for=([^;,\s]+)/)?.[1], // RFC 7239
|
||||||
|
request.ip, // Fastify default
|
||||||
|
request.socket.remoteAddress // Socket
|
||||||
|
];
|
||||||
|
|
||||||
|
// Filter out internal/private IPs and return first public IP
|
||||||
|
for (const ip of ipSources) {
|
||||||
|
if (ip && ip !== 'unknown' && !isPrivateIP(ip)) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no public IP found, return the first non-unknown IP
|
||||||
|
return ipSources.find(ip => ip && ip !== 'unknown') || 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if IP is private/internal
|
||||||
|
function isPrivateIP(ip: string): boolean {
|
||||||
|
if (!ip || ip === 'unknown') return true;
|
||||||
|
|
||||||
|
// Remove any port number
|
||||||
|
const cleanIP = ip.split(':')[0];
|
||||||
|
|
||||||
|
// Private IP ranges
|
||||||
|
const privateRanges = [
|
||||||
|
/^10\./, // 10.0.0.0/8
|
||||||
|
/^172\.(1[6-9]|2[0-9]|3[0-1])\./, // 172.16.0.0/12
|
||||||
|
/^192\.168\./, // 192.168.0.0/16
|
||||||
|
/^127\./, // 127.0.0.0/8 (localhost)
|
||||||
|
/^169\.254\./, // 169.254.0.0/16 (link-local)
|
||||||
|
/^::1$/, // IPv6 localhost
|
||||||
|
/^fe80:/ // IPv6 link-local
|
||||||
|
];
|
||||||
|
|
||||||
|
return privateRanges.some(range => range.test(cleanIP));
|
||||||
|
}
|
||||||
|
|
||||||
// API Key authentication middleware
|
// API Key authentication middleware
|
||||||
fastify.addHook('preHandler', async (request: FastifyRequest, reply: FastifyReply) => {
|
fastify.addHook('preHandler', async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
// Skip auth for health check endpoint
|
// Skip auth for health check and debug endpoints
|
||||||
if (request.url === '/health') {
|
if (request.url === '/health' || request.url === '/ip-debug') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,9 +103,8 @@ fastify.addHook('preHandler', async (request: FastifyRequest, reply: FastifyRepl
|
||||||
|
|
||||||
// Helper function to get full IP chain
|
// Helper function to get full IP chain
|
||||||
function getFullIPChain(request: FastifyRequest): { clientIP: string, ipChain: string[] } {
|
function getFullIPChain(request: FastifyRequest): { clientIP: string, ipChain: string[] } {
|
||||||
// Fastify automatically parses X-Forwarded-For when trustProxy is enabled
|
const clientIP = getClientIP(request);
|
||||||
const clientIP = request.ip || 'unknown';
|
const ipChain = request.ips || [];
|
||||||
const ipChain = request.ips || []; // Full chain of IPs
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
clientIP,
|
clientIP,
|
||||||
|
|
@ -84,6 +131,27 @@ const start = async () => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// IP Debug endpoint (bypasses authentication) - for troubleshooting
|
||||||
|
fastify.get('/ip-debug', async (request) => {
|
||||||
|
return {
|
||||||
|
detectedClientIP: getClientIP(request),
|
||||||
|
fastifyIP: request.ip,
|
||||||
|
fastifyIPs: request.ips,
|
||||||
|
socketIP: request.socket.remoteAddress,
|
||||||
|
allIPHeaders: {
|
||||||
|
'x-forwarded-for': request.headers['x-forwarded-for'],
|
||||||
|
'x-real-ip': request.headers['x-real-ip'],
|
||||||
|
'cf-connecting-ip': request.headers['cf-connecting-ip'],
|
||||||
|
'true-client-ip': request.headers['true-client-ip'],
|
||||||
|
'x-client-ip': request.headers['x-client-ip'],
|
||||||
|
'x-cluster-client-ip': request.headers['x-cluster-client-ip'],
|
||||||
|
'forwarded': request.headers['forwarded']
|
||||||
|
},
|
||||||
|
isPrivateIP: isPrivateIP(request.headers['x-real-ip']?.toString() || ''),
|
||||||
|
timestamp: Date.now()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Random endpoint for testing
|
// Random endpoint for testing
|
||||||
fastify.get('/random', async () => {
|
fastify.get('/random', async () => {
|
||||||
return objs[Math.round(objs.length * Math.random())] || { message: 'No data yet' };
|
return objs[Math.round(objs.length * Math.random())] || { message: 'No data yet' };
|
||||||
|
|
@ -103,7 +171,7 @@ const start = async () => {
|
||||||
const ipInfo = getFullIPChain(request);
|
const ipInfo = getFullIPChain(request);
|
||||||
const obj = {
|
const obj = {
|
||||||
success: true,
|
success: true,
|
||||||
clientIP: ipInfo.clientIP, // Fastify's auto-detected client IP
|
clientIP: ipInfo.clientIP, // Enhanced client IP detection
|
||||||
ipChain: ipInfo.ipChain, // Full proxy chain
|
ipChain: ipInfo.ipChain, // Full proxy chain
|
||||||
foundIPs: result.ips, // IPs found by our custom parser
|
foundIPs: result.ips, // IPs found by our custom parser
|
||||||
totalFound: result.ips.length,
|
totalFound: result.ips.length,
|
||||||
|
|
@ -122,6 +190,7 @@ const start = async () => {
|
||||||
console.log(`🚀 Proxy Detection API running on http://localhost:${PORT}`);
|
console.log(`🚀 Proxy Detection API running on http://localhost:${PORT}`);
|
||||||
console.log(`📍 Available endpoints:`);
|
console.log(`📍 Available endpoints:`);
|
||||||
console.log(` GET /health - Health check (no auth required)`);
|
console.log(` GET /health - Health check (no auth required)`);
|
||||||
|
console.log(` GET /ip-debug - IP debugging info (no auth required)`);
|
||||||
console.log(` GET / - Extract all IP addresses from request headers`);
|
console.log(` GET / - Extract all IP addresses from request headers`);
|
||||||
console.log(` GET /random - Get random cached result`);
|
console.log(` GET /random - Get random cached result`);
|
||||||
console.log(`🔑 API Key required for protected endpoints`);
|
console.log(`🔑 API Key required for protected endpoints`);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue