forked from realgam3/pymultitor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 113ce8c
Showing
8 changed files
with
1,019 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#OS junk Files | ||
[Tt]humbs.db | ||
*.DS_Store | ||
desktop.ini | ||
|
||
# Python Files | ||
*.py[cod] | ||
torData | ||
TorCtl | ||
|
||
# C Extensions | ||
*.so | ||
|
||
# Packages | ||
*.egg | ||
*.egg-info | ||
dist | ||
build | ||
eggs | ||
parts | ||
bin | ||
var | ||
sdist | ||
develop-eggs | ||
.installed.cfg | ||
lib | ||
lib64 | ||
__pycache__ | ||
|
||
# Installer Logs | ||
pip-log.txt | ||
|
||
# Translations | ||
*.mo | ||
|
||
# Developer | ||
.project | ||
.pydevproject | ||
.idea |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
#!/usr/bin/env python | ||
######################################################## | ||
# Python MultiTor | ||
# Author: RealGame (Tomer Zait) | ||
# Site: http://RealGame.co.il | ||
######################################################## | ||
|
||
#Monkey Patch All - Change Everything To Gevent | ||
from gevent.monkey import patch_all | ||
patch_all() | ||
|
||
from TorConfig import * | ||
from gevent import Timeout | ||
from re import findall | ||
from os import makedirs | ||
from time import time as now | ||
from requesocks import request | ||
from stem.process import launch_tor_with_config | ||
from stem.control import Controller | ||
from stem import Signal | ||
from zipfile import ZipFile | ||
from psutil import process_iter | ||
from subprocess import check_output | ||
|
||
|
||
#TorConnection - Contains Controller And Subprocess | ||
class TorConnection(object): | ||
def __init__(self, socksPort, ctrlPort): | ||
#Variables | ||
self.__isFree = False | ||
self.__socksPort = socksPort | ||
self.__ctrlPort = ctrlPort | ||
self.__torConfig = None | ||
self.__torProcess = None | ||
self.__torCtrl = None | ||
self.__proxies = None | ||
self.__lastTimeIpChanged = 0 | ||
#Call Creator | ||
self.__start() | ||
|
||
def __torPrint(self, line): | ||
if "Bootstrapped" in line: | ||
print "%s\t->\t%s" % (self.getId(), line) | ||
|
||
def __open(self): | ||
#Open Tor Process | ||
opened = False | ||
while not opened: | ||
with Timeout(PROCESS_TIMEOUT, False): | ||
self.__torProcess = launch_tor_with_config(config=self.__torConfig, | ||
tor_cmd=TOR_CMD, | ||
init_msg_handler=self.__torPrint) | ||
self.__torProcess.stdout.close() | ||
opened = True | ||
if not opened: | ||
self.__torProcess.terminate() | ||
|
||
#Open Tor Control | ||
self.__torCtrl = Controller.from_port(address=HOST, port=self.__ctrlPort) | ||
self.__torCtrl.authenticate(PASS_PHRASE) | ||
|
||
def __start(self): | ||
#Data Paths | ||
dataPath = path.join(TOR_ROOT_DATA_PATH, "data_%d" % self.__socksPort) | ||
if not path.exists(dataPath): | ||
makedirs(dataPath) | ||
|
||
#Create Configuration Dictionary | ||
self.__torConfig = {"ControlPort": str(self.__ctrlPort), | ||
"HashedControlPassword": passPhraseHash, | ||
"ExcludeNodes": "{CN},{HK},{MO}", | ||
"SOCKSPort": str(self.__socksPort), | ||
"DataDirectory": dataPath} | ||
|
||
#Open Tor Process | ||
self.__open() | ||
|
||
#Create Proxy String | ||
self.__proxies = {"http": "socks5://%s:%d" % (HOST, self.__socksPort), | ||
"https": "socks5://%s:%d" % (HOST, self.__socksPort)} | ||
|
||
#The Tor Connection Is Now Ready To Use | ||
self.__isFree = True | ||
|
||
#Up And Running Message | ||
print "%s\t->\tUp & Running!" % self.getId() | ||
|
||
def changeState(self): | ||
self.__isFree = not self.__isFree | ||
|
||
def isFree(self): | ||
return self.__isFree | ||
|
||
def kill(self): | ||
with Timeout(TOR_TIMEOUT, False): | ||
self.__torCtrl.close() | ||
self.__torProcess.terminate() | ||
|
||
def reset(self): | ||
#Kill All | ||
self.kill() | ||
#Start All | ||
self.__open() | ||
|
||
#Inform | ||
print "%s\t->\tUp & Running After Reset!" % self.getId() | ||
|
||
def changeIp(self, i, msg): | ||
#Tor Need 10 Seconds(TOR_TIMEOUT) Difference Between Id Changes | ||
if (now() - self.__lastTimeIpChanged) >= TOR_TIMEOUT: | ||
print "%s\t->\t%d) ChangeIP (%s)" % (self.getId(), i, msg) | ||
#Check If TimedOut | ||
timedOut = True | ||
with Timeout(TOR_TIMEOUT, False): | ||
self.__torCtrl.signal(Signal.NEWNYM) | ||
timedOut = False | ||
if timedOut: | ||
self.reset() | ||
self.__lastTimeIpChanged = now() | ||
return True | ||
return False | ||
|
||
def getId(self): | ||
return "Tor_%d" % self.__socksPort | ||
|
||
def getProxies(self): | ||
return self.__proxies | ||
|
||
|
||
#TorConnectionCollector - Sends Free TorConnection To The Thread Function | ||
class TorConnectionCollector(object): | ||
def __init__(self): | ||
self.__torCons = [] | ||
for i in xrange(MAX_NUM_OF_THREADS): | ||
self.__torCons.append(TorConnection(SOCKS_START_PORT + i, CONTROL_START_PORT + i)) | ||
|
||
def getFreeConnection(self): | ||
while True: | ||
for conn in self.__torCons: | ||
if conn.isFree(): | ||
conn.changeState() | ||
return conn | ||
|
||
def killConnections(self): | ||
for conn in self.__torCons: | ||
conn.kill() | ||
|
||
|
||
def pool_function(torRange): | ||
#Important Variables | ||
torConn = torConnColl.getFreeConnection() | ||
proxies = torConn.getProxies() | ||
torId = torConn.getId() | ||
size = len(torRange) | ||
|
||
print "%s\t->\tStart (%d - %d)" % (torId, torRange[0], torRange[-1]) | ||
i = 0 | ||
#I Use While Because For Cant Move Backwards | ||
while i < size: | ||
try: | ||
#Send Request | ||
req = request(method="GET", | ||
url="http://checkip.dyndns.org/", | ||
timeout=REQUEST_TIMEOUT, | ||
headers=HEADERS, | ||
proxies=proxies) | ||
res = req.text | ||
if res == "": | ||
continue | ||
except Exception as ex: | ||
#Change IP | ||
ipChanged = False | ||
while not ipChanged: | ||
ipChanged = torConn.changeIp(torRange[i], ex) | ||
continue | ||
#Print Result | ||
print "%s\t->\t%d) %s" % (torId, torRange[i], "".join(findall(r"[0-9]+(?:\.[0-9]+){3}", res))) | ||
i += 1 | ||
|
||
#Change IP | ||
ipChanged = False | ||
while not ipChanged: | ||
ipChanged = torConn.changeIp(i, "Finished.") | ||
|
||
#Free The TorConnection | ||
torConn.changeState() | ||
|
||
|
||
def main(): | ||
#Kill All Tor Processes | ||
for process in process_iter(): | ||
if path.basename(TOR_CMD) == process.name: | ||
process.terminate() | ||
#Extract Tor Windows Files If Needed | ||
if isWindows() and not path.exists(TOR_ROOT_DATA_PATH): | ||
makedirs(TOR_ROOT_DATA_PATH) | ||
ZipFile(path.join(getcwd(), "torWin.data")).extractall(TOR_ROOT_DATA_PATH) | ||
#Create TorConnectionCollector And Tor PassPhrase Hash | ||
global torConnColl, passPhraseHash | ||
passPhraseHash = check_output([TOR_CMD, "--hash-password", PASS_PHRASE]).strip().split("\n")[-1] | ||
torConnColl = TorConnectionCollector() | ||
#Create The Threads Pool | ||
for i in xrange(START, END, INC): | ||
POOL.spawn(pool_function, range(i, i + INC)) | ||
#Block Until Pool Done | ||
POOL.join() | ||
#Kill All TorConnections | ||
print "Kill Tor Connections" | ||
torConnColl.killConnections() | ||
#Finish | ||
print "Finished Scanning" | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
Requirements: | ||
Linux Installation: | ||
1) sudo apt-get install python-dev python-pip libevent-dev openssl tor | ||
2) sudo pip install -r requirements.txt | ||
3) sudo update-rc.d -f tor disable | ||
|
||
MacOSx Installation: | ||
1) Install Xcode Command Line Tools (AppStore) | ||
2) ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)" | ||
3) brew install openssl tor | ||
4) sudo easy_install pip | ||
5) sudo pip install -r requirements.txt | ||
|
||
Windows 32bit Installation: | ||
1) Install setuptools (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/setuptools-1.1.5.win32-py2.7.exe) - No Need In ActivePython | ||
2) Install greenlet (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/greenlet-0.4.1.win32-py2.7.exe) | ||
3) Install gevent (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/gevent-0.13.8.win32-py2.7.exe) | ||
4) Install psutil (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/psutil-1.0.1.win32-py2.7.exe) | ||
5) Open Command Prompt(cmd) as Administrator -> Goto python folder -> Scripts (cd c:\Python27\Scripts) | ||
6) pip install -r (Full Path To requirements.txt), OR pip install requesocks && pip install stem | ||
|
||
Windows 64bit Installation: | ||
1) Install setuptools (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/setuptools-1.1.5.win-amd64-py2.7.exe) - No Need In ActivePython | ||
2) Install greenlet (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/greenlet-0.4.1.win-amd64-py2.7.exe) | ||
3) Install gevent (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/gevent-0.13.8.win-amd64-py2.7.exe) | ||
4) Install psutil (http://www.lfd.uci.edu/~gohlke/pythonlibs/3n2nz84p/psutil-1.0.1.win-amd64-py2.7.exe) | ||
5) Open Command Prompt(cmd) as Administrator -> Goto python folder -> Scripts (cd c:\Python27\Scripts) | ||
6) pip install -r (Full Path To requirements.txt), OR pip install requesocks && pip install stem | ||
|
||
Thanks: | ||
* Omri Bahumi | ||
* Shimon Tolts | ||
* Roman Labunsky |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
TODO: | ||
1) TorConnections as Threads - For Faster Initialize. | ||
2) Create Semaphores / Locks - For TorConnections Threads. | ||
3) Make MAX_REQUEST_THREADS - For Faster Fequests. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
######################################################## | ||
__author__ = 'RealGame (Tomer Zait)' | ||
__license__ = 'GPL v3' | ||
__version__ = '1.0.0' | ||
__email__ = '[email protected]' | ||
######################################################## | ||
|
||
from gevent.pool import Pool | ||
from os import getcwd, path | ||
from sys import platform | ||
from requesocks.defaults import defaults | ||
|
||
|
||
def isWindows(): | ||
return platform == 'win32' | ||
|
||
|
||
def isMacosx(): | ||
return platform == 'darwin' | ||
|
||
|
||
#Define Configuration Variables: | ||
TOR_ROOT_DATA_PATH = path.join(getcwd(), 'torData') | ||
|
||
# Create Tor Command For Linux / Windows / MacOSX | ||
TOR_CMD = 'tor' | ||
if isWindows(): | ||
TOR_CMD = path.join(TOR_ROOT_DATA_PATH, TOR_CMD + '.exe') | ||
elif isMacosx(): | ||
TOR_CMD = path.join('/usr/local/bin', TOR_CMD) | ||
|
||
MAX_NUM_OF_THREADS = 4 | ||
TOR_TIMEOUT = 10 | ||
PROCESS_TIMEOUT = 120 | ||
REQUEST_TIMEOUT = 15 | ||
MAX_RETRIES = 2 | ||
CONTROL_START_PORT = 9050 | ||
SOCKS_START_PORT = 5050 | ||
PASS_PHRASE = 'lol' | ||
HOST = '127.0.0.1' | ||
POOL = Pool(size=MAX_NUM_OF_THREADS) | ||
HEADERS = {'User-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0'} | ||
START = 1 | ||
END = 400 | ||
INC = 50 | ||
# Change Requesocks Default Configurations | ||
defaults['pool_connections'] = MAX_NUM_OF_THREADS | ||
defaults['pool_maxsize'] = MAX_NUM_OF_THREADS | ||
defaults['max_retries'] = MAX_RETRIES | ||
defaults['max_redirects'] = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
gevent >= 0.13.8 | ||
greenlet >= 0.4.1 | ||
requesocks >= 0.10.8 | ||
stem >= 1.0.1 | ||
psutil >= 1.0.1 |
Binary file not shown.