@@ -3,6 +3,7 @@ import rateLimit from 'express-rate-limit';
33import argon2 from 'argon2' ;
44import jwt from 'jsonwebtoken' ;
55import { createHash , randomBytes } from 'crypto' ;
6+ import { isIP } from 'net' ;
67
78import { query } from '../config/db.js' ;
89import { generateToken , authenticateToken } from '../middleware/auth.js' ;
@@ -99,16 +100,28 @@ function isPrivateIp(ip) {
99100 return false ;
100101}
101102
102- async function isVpnOrProxy ( ip ) {
103- if ( isPrivateIp ( ip ) ) {
104- console . log ( '[VPN] Skipping private IP:' , ip ) ;
103+ function normalizeClientIp ( ip ) {
104+ if ( typeof ip !== 'string' ) return null ;
105+ const trimmed = ip . trim ( ) ;
106+ if ( ! trimmed ) return null ;
107+ const withoutV4Mapped = trimmed . replace ( / ^ : : f f f f : / , '' ) ;
108+ return isIP ( withoutV4Mapped ) ? withoutV4Mapped : null ;
109+ }
110+
111+ export async function isVpnOrProxy ( ip ) {
112+ const cleanIp = normalizeClientIp ( ip ) ;
113+ if ( ! cleanIp ) {
114+ console . log ( '[VPN] Skipping invalid IP:' , ip ) ;
105115 return false ;
106116 }
107117
108- const cleanIp = ip . replace ( / ^ : : f f f f : / , '' ) ;
118+ if ( isPrivateIp ( cleanIp ) ) {
119+ console . log ( '[VPN] Skipping private IP:' , cleanIp ) ;
120+ return false ;
121+ }
109122
110123 try {
111- const res = await fetchWithTimeout ( `http://ip-api.com/json/${ cleanIp } ?fields=proxy,hosting,isp,org,query` ) ;
124+ const res = await fetchWithTimeout ( `http://ip-api.com/json/${ encodeURIComponent ( cleanIp ) } ?fields=proxy,hosting,isp,org,query` ) ;
112125 const data = await res . json ( ) ;
113126 console . log ( '[VPN] ip-api response for' , cleanIp , ':' , JSON . stringify ( data ) ) ;
114127 return data . proxy === true || data . hosting === true ;
@@ -117,7 +130,7 @@ async function isVpnOrProxy(ip) {
117130 }
118131
119132 try {
120- const res = await fetchWithTimeout ( `https://ipinfo.io/${ cleanIp } /json` ) ;
133+ const res = await fetchWithTimeout ( `https://ipinfo.io/${ encodeURIComponent ( cleanIp ) } /json` ) ;
121134 const data = await res . json ( ) ;
122135 console . log ( '[VPN] ipinfo response for' , cleanIp , ':' , JSON . stringify ( { org : data . org } ) ) ;
123136 const orgLower = ( data . org || '' ) . toLowerCase ( ) ;
0 commit comments