diff --git a/README.md b/README.md index 02fb00e..73933d2 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Python 3.x * Define your own custom User Agent string. * Select random User-Agent strings from file. Each User Agent string in new line. * Proxy support. +* Select random proxy from file. Each proxy URL in new line. * Open IP geolocation in Google Maps using the default browser. * Export results to csv, xml and txt format. @@ -42,11 +43,11 @@ Python 3.x --- ``` $ ./ip2geolocation.py -usage: ip2geolocation.py [-h] [-m] [-t TARGET] [-T file] [-u User-Agent] [-r] +usage: ip2geolocation.py [-h] [-m] [-t TARGET] [-T file] [-u User-Agent] [-U file] [-g] [--noprint] [-v] [--nolog] [-x PROXY] - [-e file] [-ec file] [-ex file] + [-X file] [-e file] [-ec file] [-ex file] -IPGeoLocation 1.8 +IPGeoLocation 1.9 Retrieve IP Geolocation information from http://ip-api.com http://ip-api.com service will automatically ban any IP addresses doing over 150 requests per minute. @@ -59,16 +60,17 @@ optional arguments: -T file, --tlist file A list of IPs/Domains targets, each target in new line. -u User-Agent, --user-agent User-Agent - Set the User-Agent request header (default: IP2GeoLocation 1.8). - -r Pick User-Agent strings randomly from a file. + Set the User-Agent request header (default: IP2GeoLocation 1.9). -U file, --ulist file A list of User-Agent strings, each string in new line. -g Open IP location in Google maps with default browser. - --noprint Run without printing results to terminal. + --noprint IPGeolocation will print IP Geolocation info to terminal. It is possible to tell IPGeolocation not to print results to terminal with this option. -v, --verbose Enable verbose output. - --nolog Run without logging. + --nolog IPGeolocation will save a .log file. It is possible to tell IPGeolocation not to save those log files with this option. -x PROXY, --proxy PROXY Setup proxy server (example: http://127.0.0.1:8080) + -X file, --xlist file + A list of proxies, each proxy url in new line. -e file, --txt file Export results. -ec file, --csv file Export results in CSV format. -ex file, --xml file Export results in XML format. @@ -95,8 +97,11 @@ optional arguments: **Using Proxy** * ./ip2geolocation.py -t x.x.x.x -x http://127.0.0.1:8080 -**Pick User Agent string randomly** -* ./ip2geolocation.py -t x.x.x.x -U /path/to/user/agent/strings/filename.txt -r +**Using random Proxy** +* ./ip2geolocation.py -t x.x.x.x -X /path/to/proxies/filename.txt + +**Pick User-Agent string randomly** +* ./ip2geolocation.py -t x.x.x.x -U /path/to/user/agent/strings/filename.txt **Retrieve IP geolocation and open location in Google maps with default browser** * ./ip2geolocation.py -t x.x.x.x -g diff --git a/geolocation/IpGeoLocationLib.py b/geolocation/IpGeoLocationLib.py index 960800b..2e9044e 100644 --- a/geolocation/IpGeoLocationLib.py +++ b/geolocation/IpGeoLocationLib.py @@ -32,7 +32,7 @@ from utilities.FileExporter import FileExporter from subprocess import call from sys import platform as _platform - +from urllib.parse import urlparse class IpGeoLocationLib: """Retrieve IP Geolocation information from http://ip-api.com""" @@ -42,11 +42,12 @@ def __init__(self): self.URL = 'http://ip-api.com' self.RequestURL = self.URL + '/json/{}' self.BOLD = '\033[1m' - self.Proxy = request.ProxyHandler({}) - self.RandomUA = False + self.Proxy = None self.UserAgentFile = None self.UserAgents = None + self.Proxies = None self.TargetsFile = None + self.ProxiesFile = None self.Targets = None self.Verbose = False self.NoPrint = False @@ -54,21 +55,25 @@ def __init__(self): def GetInfo(self, target, userAgent, targetsFile=None, - rUserAgent=False, userAgentFile=None, - proxy=False, noprint=False, verbose=False, - nolog=False, exportToCSVFile=None, + userAgentFile=None, proxy=False, proxiesFile=None, + noprint=False, verbose=False, nolog=False, exportToCSVFile=None, exportToXMLFile=None, exportToTXTFile=None, googleMaps=False): """Retrieve information""" self.UserAgent = userAgent - self.RandomUA = rUserAgent self.Verbose = verbose self.NoPrint = noprint self.NoLog = nolog try: + #check proxies file and load it + if proxiesFile and os.path.isfile(proxiesFile) and os.access(proxiesFile, os.R_OK): + self.ProxiesFile = proxiesFile + self.__print('Loading Proxies from file {}..'.format(self.ProxiesFile)) + self.__loadProxies() + #check user-agent strings file and load it if userAgentFile and os.path.isfile(userAgentFile) and os.access(userAgentFile, os.R_OK): self.UserAgentFile = userAgentFile @@ -81,13 +86,10 @@ def GetInfo(self, target, userAgent, targetsFile=None, self.__print('Loading targets from file {}..'.format(self.TargetsFile)) self.__loadTargets() - #read proxy settings, check if valid and configure connection + #check if proxy valid and configure connection if proxy: - self.__checkProxy(proxy.netloc) - self.Proxy = request.ProxyHandler({'http':proxy.scheme + '://' + proxy.netloc}) - opener = request.build_opener(self.Proxy) - request.install_opener(opener) - self.__print('Proxy ({}) has been configured.'.format(proxy.scheme + '://' + proxy.netloc)) + self.__configureProxy(proxy) + #retrieve information results = None @@ -107,7 +109,7 @@ def GetInfo(self, target, userAgent, targetsFile=None, if exportToTXTFile and not os.path.exists(exportToTXTFile) and os.access(os.path.dirname(exportToTXTFile), os.W_OK): self.__exportResultsToTXT(results, exportToTXTFile) - + #open location in Google Maps with default browser if googleMaps and type(results) is IpGeoLocation: self.__openLocationInGoogleMaps(results) @@ -116,21 +118,45 @@ def GetInfo(self, target, userAgent, targetsFile=None, except MyExceptions.UserAgentFileEmptyError: self.__printError("User-Agent strings file is empty!") except MyExceptions.InvalidTargetError: - self.__printError('Please provide a valid Domain or IP address.') + self.__printError('Please provide a valid Domain or IP address!') except MyExceptions.TargetsFileEmptyError: - self.__printError('Targets file is empty!.') + self.__printError('Targets file is empty!') except MyExceptions.UserAgentFileNotSpecifiedError: - self.__printError('User-Agent strings file has not been provided!.') + self.__printError('User-Agent strings file has not been provided!') except MyExceptions.TargetsFileNotSpecifiedError: - self.__printError('Targets file has not been provided!.') + self.__printError('Targets file has not been provided!') except MyExceptions.ProxyServerNotReachableError: - self.__printError('Proxy server not reachable') - except: - self.__printError("An unexpected error occurred") + self.__printError('Proxy server not reachable!') + except MyExceptions.ProxiesFileNotSpecifiedError: + self.__printError('Proxies file has not been provided!') + except MyExceptions.ProxiesFileEmptyError: + self.__printError('Proxies file is empty!') + except MyExceptions.InvalidProxyUrlError: + self.__printError('Proxy URL is not valid!') + except Exception as error: + self.__printError('An unexpected error occurred {}!'.format(error)) return False + def __checkProxyUrl(self, url): + """Check if proxy url is valid""" + url_checked = urlparse(url) + if ((url_checked.scheme != 'http') & (url_checked.scheme != 'https')) | (url_checked.netloc == ''): + raise MyExceptions.InvalidProxyUrlError() + return url_checked + + + def __configureProxy(self, proxy): + proxy = self.__checkProxyUrl(proxy) + self.__checkProxyConn(proxy.netloc) + self.Proxy = proxy + proxyHandler = request.ProxyHandler({'http':proxy.scheme + '://' + proxy.netloc}) + opener = request.build_opener(proxyHandler) + request.install_opener(opener) + self.__print('Proxy ({}) has been configured.'.format(proxy.scheme + '://' + proxy.netloc)) + + def __openLocationInGoogleMaps(self, ipGeolObj): """Open IP Geolocation in Google Maps with default browser""" if type(ipGeolObj.Longtitude) == float and type(ipGeolObj.Latitude) == float: @@ -145,6 +171,7 @@ def __openLocationInGoogleMaps(self, ipGeolObj): else: self.__printError('-g option is not available on your platform.') + def __exportResultsToCSV(self, objToExport, csvFile): """Export results to csv file""" fileExporter = FileExporter() @@ -221,9 +248,15 @@ def __retrieveGeolocation(self, target): target = ip - if self.RandomUA and self.UserAgentFile: + #pick random user-agent string + if self.UserAgentFile: self.__pickRandomUserAgent() - + + + #pick random proxy connection + if self.ProxiesFile: + self.__pickRandomProxy() + self.__print('Retrieving {} Geolocation..'.format(query)) @@ -234,7 +267,10 @@ def __retrieveGeolocation(self, target): response = request.urlopen(req) if response.code == 200: + self.__print('User-Agent used: {}'.format(self.UserAgent)) + #self.__print('Proxy server used: {}'.format('{}://{}'.format(self.Proxy.scheme, self.Proxy.netloc))) + encoding = response.headers.get_content_charset() ipGeoLocObj = IpGeoLocation(query, json.loads(response.read().decode(encoding))) @@ -248,14 +284,26 @@ def __retrieveGeolocation(self, target): return False + def __loadProxies(self): + """Load proxies from file""" + if not self.ProxiesFile: + raise MyExceptions.ProxiesFileNotSpecifiedError() + + self.Proxies = [line.strip() for line in open(self.ProxiesFile, 'r') if line.strip()] + self.__print('{} Proxies loaded.'.format(len(self.Proxies))) + + if len(self.Proxies) == 0: + raise MyExceptions.ProxiesFileEmptyError() + + def __loadUserAgents(self): """Load user-agent strings from file""" if not self.UserAgentFile: raise MyExceptions.UserAgentFileNotSpecifiedError() self.UserAgents = [line.strip() for line in open(self.UserAgentFile, 'r') if line.strip()] - self.__print('User-Agent strings loaded.') - + self.__print('{} User-Agent strings loaded.'.format(len(self.UserAgents))) + if len(self.UserAgents) == 0: raise MyExceptions.UserAgentFileEmptyError() @@ -266,14 +314,22 @@ def __loadTargets(self): raise MyExceptions.TargetsFileNotSpecifiedError() self.Targets = [line.strip() for line in open(self.TargetsFile, 'r') if line.strip()] - self.__print('Targets loaded.') + self.__print('{} Targets loaded.'.format(len(self.Targets))) if len(self.Targets) == 0: raise MyExceptions.TargetsFileEmptyError() + + def __pickRandomProxy(self): + """Pick randomly a proxy from the list""" + if not self.Proxies or len(self.Proxies) == 0: + raise MyExceptions.ProxiesFileEmptyError() + + self.__configureProxy(random.choice(self.Proxies)) + def __pickRandomUserAgent(self): - """Pick randomly a user-agent string from list""" + """Pick randomly a user-agent string from the list""" if not self.UserAgents or len(self.UserAgents) == 0: raise MyExceptions.UserAgentFileEmptyError() @@ -347,7 +403,7 @@ def __printIPGeoLocation(self, ipGeoLocation): #.encode('cp737', errors='replace').decode('cp737') - def __checkProxy(self, proxy): + def __checkProxyConn(self, proxy): """check proxy connectivity""" check = True self.__print('Testing proxy {} connectivity..'.format(proxy)) diff --git a/ip2geolocation.py b/ip2geolocation.py index 4a30d9c..dc2a876 100644 --- a/ip2geolocation.py +++ b/ip2geolocation.py @@ -102,10 +102,6 @@ def printError(message): default='IP2GeoLocation {}'.format(__version__), help='Set the User-Agent request header (default: IP2GeoLocation {}).'.format(__version__)) - parser.add_argument('-r', - action='store_true', - help='Pick User-Agent strings randomly from a file.') - parser.add_argument('-U', '--ulist', metavar='file', type=checkFileRead, @@ -135,6 +131,11 @@ def printError(message): type=checkProxyUrl, help='Setup proxy server (example: http://127.0.0.1:8080)') + parser.add_argument('-X', '--xlist', + metavar='file', + type=checkFileRead, + help='A list of proxies, each proxy url in new line.') + #export options parser.add_argument('-e', '--txt', @@ -175,22 +176,28 @@ def printError(message): printError("You can request Geolocation information either for a list of targets(-T) or your own IP address. Not both!") sys.exit(4) - #single target and google maps + #single target and google maps only allowed if(args.tlist and args.g): printError("Google maps location is working only with single targets.") sys.exit(5) - - #pick random user-agent string without user-agent strings list - if(args.r and not args.ulist): - printError("You haven't provided a User-Agent strings file, each string in a new line.") - sys.exit(6) + #specify user-agent or random + if(args.uagent and args.ulist): + printError("You can either specify a user-agent string or let IPGeolocation pick random user-agent strings for you from a file.") + sys.exit(6) + + #specify proxy or random + if(args.proxy and args.xlist): + printError("You can either specify a proxy or let IPGeolocation pick random proxy connections for you from a file.") + sys.exit(7) + + #init lib ipGeoLocRequest = IpGeoLocationLib() #retrieve information if not ipGeoLocRequest.GetInfo(args.target, args.uagent, args.tlist, - args.r, args.ulist, args.proxy, + args.ulist, args.proxy, args.xlist, args.noprint, args.verbose, args.nolog, args.csv, args.xml, args.txt, args.g): printError("Retrieving IP Geolocation information failed.") diff --git a/utilities/MyExceptions.py b/utilities/MyExceptions.py index b51eae7..20628a6 100644 --- a/utilities/MyExceptions.py +++ b/utilities/MyExceptions.py @@ -39,4 +39,13 @@ class UserAgentFileNotSpecifiedError(Exception): pass class ProxyServerNotReachableError(Exception): + pass + +class ProxiesFileNotSpecifiedError(Exception): + pass + +class ProxiesFileEmptyError(Exception): + pass + +class InvalidProxyUrlError(Exception): pass \ No newline at end of file