Created
February 26, 2013 14:07
-
-
Save saharabear/5038637 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| import sys | |
| try: | |
| import gevent, gevent.monkey | |
| gevent.monkey.patch_all(dns=gevent.version_info[0]>=1) | |
| except ImportError: | |
| gevent = None | |
| print >>sys.stderr, 'warning: gevent not found, using threading instead' | |
| import socket | |
| import select | |
| import SocketServer | |
| import struct | |
| import string | |
| import hashlib | |
| import os | |
| import json | |
| import logging | |
| import getopt | |
| def get_table(key): | |
| m = hashlib.md5() | |
| m.update(key) | |
| s = m.digest() | |
| (a, b) = struct.unpack('<QQ', s) | |
| table = [c for c in string.maketrans('', '')] | |
| for i in xrange(1, 1024): | |
| table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i))) | |
| return table | |
| def send_all(sock, data): | |
| bytes_sent = 0 | |
| while True: | |
| r = sock.send(data[bytes_sent:]) | |
| if r < 0: | |
| return r | |
| bytes_sent += r | |
| if bytes_sent == len(data): | |
| return bytes_sent | |
| class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): | |
| allow_reuse_address = True | |
| class Socks5Server(SocketServer.StreamRequestHandler): | |
| def handle_tcp(self, sock, remote): | |
| try: | |
| fdset = [sock, remote] | |
| while True: | |
| r, w, e = select.select(fdset, [], []) | |
| if sock in r: | |
| data = sock.recv(4096) | |
| if len(data) <= 0: | |
| break | |
| result = send_all(remote, self.decrypt(data)) | |
| if result < len(data): | |
| raise Exception('failed to send all data') | |
| if remote in r: | |
| data = remote.recv(4096) | |
| if len(data) <= 0: | |
| break | |
| result = send_all(sock, self.encrypt(data)) | |
| if result < len(data): | |
| raise Exception('failed to send all data') | |
| finally: | |
| sock.close() | |
| remote.close() | |
| def encrypt(self, data): | |
| return data.translate(encrypt_table) | |
| def decrypt(self, data): | |
| return data.translate(decrypt_table) | |
| def handle(self): | |
| try: | |
| sock = self.connection | |
| addrtype = ord(self.decrypt(sock.recv(1))) | |
| if addrtype == 1: | |
| addr = socket.inet_ntoa(self.decrypt(self.rfile.read(4))) | |
| elif addrtype == 3: | |
| addr = self.decrypt( | |
| self.rfile.read(ord(self.decrypt(sock.recv(1))))) | |
| else: | |
| # not support | |
| logging.warn('addr_type not support') | |
| return | |
| port = struct.unpack('>H', self.decrypt(self.rfile.read(2))) | |
| try: | |
| logging.info('connecting %s:%d' % (addr, port[0])) | |
| remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
| remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) | |
| remote.connect((addr, port[0])) | |
| except socket.error, e: | |
| # Connection refused | |
| logging.warn(e) | |
| return | |
| self.handle_tcp(sock, remote) | |
| except socket.error, e: | |
| logging.warn(e) | |
| if __name__ == '__main__': | |
| os.chdir(os.path.dirname(__file__) or '.') | |
| print 'MIT Shadows v0.9.3' | |
| with open('config.json', 'rb') as f: | |
| config = json.load(f) | |
| SERVER = config['server'] | |
| PORT = config['server_port'] | |
| KEY = config['password'] | |
| optlist, args = getopt.getopt(sys.argv[1:], 'p:k:') | |
| for key, value in optlist: | |
| if key == '-p': | |
| PORT = int(value) | |
| elif key == '-k': | |
| KEY = value | |
| logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s', | |
| datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') | |
| encrypt_table = ''.join(get_table(KEY)) | |
| decrypt_table = string.maketrans(encrypt_table, string.maketrans('', '')) | |
| if '-6' in sys.argv[1:]: | |
| ThreadingTCPServer.address_family = socket.AF_INET6 | |
| try: | |
| server = ThreadingTCPServer(('', PORT), Socks5Server) | |
| logging.info("starting server at port %d ..." % PORT) | |
| server.serve_forever() | |
| except socket.error, e: | |
| logging.error(e) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment