-
Notifications
You must be signed in to change notification settings - Fork 13
/
z_client.py
155 lines (141 loc) · 5.31 KB
/
z_client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import select, socket, ssl, os
import sys, struct, random, hashlib
import json
import logging
import threading
import SocketServer
def filepath(f):
return os.path.join(os.path.split(os.path.realpath(__file__))[0], f)
def send_all(sock, data):
bytes_sent = 0
con = 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
con = con + 1
if con > 14:
raise Exception('send too many times!')
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, 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, data)
if result < len(data):
raise Exception('failed to send all data')
finally:
sock.close()
remote.close()
def send_PW(self, sock):
sock.send(PW + '\x00' * random.randint(10,80))
rePW = sock.recv(2048)
return (rePW[:len(PW)] == PW)
def handle(self):
try:
sock = self.connection
sock.recv(262)
sock.send("\x05\x00")
data = self.rfile.read(4) or '\x00' * 4
mode = ord(data[1])
if mode != 1:
logging.warn('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 = self.rfile.read(1)
addr = self.rfile.read(ord(addr_len))
addr_to_send += addr_len + addr
elif addrtype == 4:
addr_ip = self.rfile.read(16)
addr = socket.inet_ntop(socket.AF_INET6, addr_ip)
addr_to_send += addr_ip
else:
logging.warn('addr_type not support')
# not support
return
addr_port = self.rfile.read(2)
addr_to_send += addr_port
port = struct.unpack('>H', addr_port)
try:
reply = "\x05\x00\x00\x01"
reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222)
self.wfile.write(reply)
#R_P = REMOTE_PORT[random.randint(0,len(REMOTE_PORT) - 1)]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote = ssl.wrap_socket(s,
ca_certs= CA,
cert_reqs=ssl.CERT_REQUIRED)
remote.connect(self.server.seradd)
if not self.server.seradd[0] == remote.getpeercert()['subjectAltName'][0][1]:
logging.error('Server crt error !! Server Name don\'t mach !!')
logging.error(remote.getpeercert()['subjectAltName'][0][1])
return
if not self.send_PW(remote):
logging.warn('PW error !')
return
remote.send(addr_to_send)
logging.info('connecting %s:%d' % (addr, port[0]))
except socket.error, e:
logging.warn(e)
return
self.handle_tcp(sock, remote)
except socket.error, e:
logging.warn(e)
class local_server(threading.Thread):
def __init__(self, server):
threading.Thread.__init__(self)
self.server = server
def run(self):
self.server.serve_forever()
def main():
global PW, CA
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S', filemode='a+')
with open(filepath('config.json'), 'rb') as f:
config = json.load(f)
logging.info('loading config from %s' % filepath('config.json'))
SERVER = config['server']
REMOTE_PORT = config['server_port']
PORT = config['local_port']
LOCAL = config['local']
PW = hashlib.sha1(config['password'] + "3dfghuyrfplndd3e2sdrr4dddff").digest()
IPv6 = int(config['ipv6'])
CA = filepath(config['CA'])
if IPv6:
ThreadingTCPServer.address_family = socket.AF_INET6
try:
server = ThreadingTCPServer((LOCAL, PORT), Socks5Server)
server.seradd = (SERVER, REMOTE_PORT)
print "starting local at", PORT, 'to', SERVER
local_server(server).start()
except socket.error, e:
logging.error(e)
except KeyboardInterrupt:
server.shutdown()
sys.exit(0)
if __name__ == '__main__':
main()