Merge pull request #10 from clowwindy/local-socks5

Local socks5
This commit is contained in:
clowwindy 2012-06-20 23:30:01 -07:00
commit a79b90d2a5
2 changed files with 77 additions and 64 deletions

106
local.py
View file

@ -20,19 +20,18 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
SERVER = 'my server ip' SERVER = '127.0.0.1'
REMOTE_PORT = 8499 REMOTE_PORT = 8388
PORT = 1080 PORT = 1080
KEY = "foobar!" KEY = "barfoo!"
import socket import socket
import select import select
import string
import struct
import hashlib
import threading
import time
import SocketServer import SocketServer
import struct
import string
import hashlib
import sys
def get_table(key): def get_table(key):
m = hashlib.md5() m = hashlib.md5()
@ -44,47 +43,19 @@ def get_table(key):
table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i))) table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i)))
return table return table
encrypt_table = ''.join(get_table(KEY))
decrypt_table = string.maketrans(encrypt_table, string.maketrans('', ''))
my_lock = threading.Lock()
def lock_print(msg):
my_lock.acquire()
try:
print "[%s] %s" % (time.ctime(), msg)
finally:
my_lock.release()
class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
pass pass
class Socks5Server(SocketServer.StreamRequestHandler): class Socks5Server(SocketServer.StreamRequestHandler):
def encrypt(self, data):
return data.translate(encrypt_table)
def decrypt(self, data):
return data.translate(decrypt_table)
def handle_tcp(self, sock, remote): def handle_tcp(self, sock, remote):
try: try:
fdset = [sock, remote] fdset = [sock, remote]
counter = 0
while True: while True:
r, w, e = select.select(fdset, [], []) r, w, e = select.select(fdset, [], [])
if sock in r: if sock in r:
r_data = sock.recv(4096) if remote.send(self.encrypt(sock.recv(4096))) <= 0:
if counter == 1:
try:
lock_print(
"Connecting " + r_data[5:5 + ord(r_data[4])])
except Exception:
pass
if counter < 2:
counter += 1
if remote.send(self.encrypt(r_data)) <= 0:
break break
if remote in r: if remote in r:
if sock.send(self.decrypt(remote.recv(4096))) <= 0: if sock.send(self.decrypt(remote.recv(4096))) <= 0:
@ -92,20 +63,73 @@ class Socks5Server(SocketServer.StreamRequestHandler):
finally: finally:
remote.close() remote.close()
def encrypt(self, data):
return data.translate(encrypt_table)
def decrypt(self, data):
return data.translate(decrypt_table)
def send_encrpyt(self, sock, data):
sock.send(self.encrypt(data))
def handle(self): def handle(self):
try: try:
print 'socks connection from ', self.client_address
sock = self.connection sock = self.connection
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.recv(262)
remote.connect((SERVER, REMOTE_PORT)) sock.send("\x05\x00")
data = self.rfile.read(4)
mode = ord(data[1])
if mode != 1:
print 'mode != 1'
return
addrtype = ord(data[3])
addr_to_send = data[3]
if addrtype == 1:
addr_ip = self.rfile.read(4)
addr = socket.inet_ntoa(addr_ip)
addr_to_send += addr_ip
elif addrtype == 3:
addr_len = sock.recv(1)
addr = self.rfile.read(ord(addr_len))
addr_to_send += addr_len + addr
else:
print 'not support'
# not support
return
addr_port = self.rfile.read(2)
addr_to_send += addr_port
port = struct.unpack('>H', addr_port)
try:
if mode == 1:
reply = "\x05\x00\x00\x01"
reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222)
sock.send(reply)
# reply immediately
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote.connect((SERVER, REMOTE_PORT))
self.send_encrpyt(remote, addr_to_send)
print 'Tcp connect to', addr, port[0]
else:
print 'command not supported'
return
except socket.error as e:
print 'socket error ' + str(e)
return
self.handle_tcp(sock, remote) self.handle_tcp(sock, remote)
except socket.error as e: except socket.error as e:
lock_print('socket error: %s' % str(e)) print 'socket error ' + str(e)
def main(): def main():
print 'Starting proxy at port %d' % PORT if '-6' in sys.argv[1:]:
ThreadingTCPServer.address_family = socket.AF_INET6
server = ThreadingTCPServer(('', PORT), Socks5Server) server = ThreadingTCPServer(('', PORT), Socks5Server)
server.allow_reuse_address = True
print "starting server at port %d ..." % PORT
server.serve_forever() server.serve_forever()
if __name__ == '__main__': if __name__ == '__main__':
encrypt_table = ''.join(get_table(KEY))
decrypt_table = string.maketrans(encrypt_table, string.maketrans('', ''))
main() main()

View file

@ -20,8 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
PORT = 8499 PORT = 8388
KEY = "foobar!" KEY = "barfoo!"
import socket import socket
import select import select
@ -74,11 +74,7 @@ class Socks5Server(SocketServer.StreamRequestHandler):
try: try:
print 'socks connection from ', self.client_address print 'socks connection from ', self.client_address
sock = self.connection sock = self.connection
sock.recv(262) addrtype = ord(self.decrypt(sock.recv(1)))
self.send_encrpyt(sock, "\x05\x00")
data = self.decrypt(self.rfile.read(4))
mode = ord(data[1])
addrtype = ord(data[3])
if addrtype == 1: if addrtype == 1:
addr = socket.inet_ntoa(self.decrypt(self.rfile.read(4))) addr = socket.inet_ntoa(self.decrypt(self.rfile.read(4)))
elif addrtype == 3: elif addrtype == 3:
@ -86,32 +82,25 @@ class Socks5Server(SocketServer.StreamRequestHandler):
self.rfile.read(ord(self.decrypt(sock.recv(1))))) self.rfile.read(ord(self.decrypt(sock.recv(1)))))
else: else:
# not support # not support
print 'server: not support'
return return
port = struct.unpack('>H', self.decrypt(self.rfile.read(2))) port = struct.unpack('>H', self.decrypt(self.rfile.read(2)))
reply = "\x05\x00\x00\x01"
try: try:
if mode == 1: print 'Tcp connecting to', addr, port[0]
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote.connect((addr, port[0])) remote.connect((addr, port[0]))
local = remote.getsockname() local = remote.getsockname()
reply += socket.inet_aton(local[0]) + struct.pack(">H",
local[1])
print 'Tcp connect to', addr, port[0]
else:
reply = "\x05\x07\x00\x01" # Command not supported
print 'command not supported'
except socket.error: except socket.error:
# Connection refused # Connection refused
reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' return
self.send_encrpyt(sock, reply) self.handle_tcp(sock, remote)
if reply[1] == '\x00':
if mode == 1:
self.handle_tcp(sock, remote)
except socket.error as e: except socket.error as e:
print 'socket error' print 'socket error'
def main(): def main():
if '-6' in sys.argv[1:]:
ThreadingTCPServer.address_family = socket.AF_INET6
server = ThreadingTCPServer(('', PORT), Socks5Server) server = ThreadingTCPServer(('', PORT), Socks5Server)
server.allow_reuse_address = True server.allow_reuse_address = True
print "starting server at port %d ..." % PORT print "starting server at port %d ..." % PORT