Browse Source

log listening port, remove `auth_simple`, redirect the same port

dev
BreakWa11 8 years ago
parent
commit
0213e78847
  1. 164
      shadowsocks/obfsplugin/auth.py
  2. 37
      shadowsocks/tcprelay.py

164
shadowsocks/obfsplugin/auth.py

@ -36,9 +36,6 @@ from shadowsocks import common, lru_cache
from shadowsocks.obfsplugin import plain
from shadowsocks.common import to_bytes, to_str, ord, chr
def create_auth_simple(method):
return auth_simple(method)
def create_auth_sha1(method):
return auth_sha1(method)
@ -46,7 +43,6 @@ def create_auth_sha1_v2(method):
return auth_sha1_v2(method)
obfs_map = {
'auth_simple': (create_auth_simple,),
'auth_sha1': (create_auth_sha1,),
'auth_sha1_compatible': (create_auth_sha1,),
'auth_sha1_v2': (create_auth_sha1_v2,),
@ -137,7 +133,7 @@ class obfs_auth_data(object):
self.startup_time = int(time.time() - 30) & 0xFFFFFFFF
self.local_client_id = b''
self.connection_id = 0
self.set_max_client(16) # max active client count
self.set_max_client(64) # max active client count
def update(self, client_id, connection_id):
if client_id in self.client_id:
@ -181,162 +177,6 @@ class obfs_auth_data(object):
else:
return self.client_id[client_id].insert(connection_id)
class auth_simple(verify_base):
def __init__(self, method):
super(auth_simple, self).__init__(method)
self.recv_buf = b''
self.unit_len = 8100
self.decrypt_packet_num = 0
self.raw_trans = False
self.has_sent_header = False
self.has_recv_header = False
self.client_id = 0
self.connection_id = 0
self.max_time_dif = 60 * 5 # time dif (second) setting
def init_data(self):
return obfs_auth_data()
def set_server_info(self, server_info):
self.server_info = server_info
try:
max_client = int(server_info.protocol_param)
except:
max_client = 16
self.server_info.data.set_max_client(max_client)
def pack_data(self, buf):
rnd_data = os.urandom(common.ord(os.urandom(1)[0]) % 16)
data = common.chr(len(rnd_data) + 1) + rnd_data + buf
data = struct.pack('>H', len(data) + 6) + data
crc = (0xffffffff - binascii.crc32(data)) & 0xffffffff
data += struct.pack('<I', crc)
return data
def auth_data(self):
utc_time = int(time.time()) & 0xFFFFFFFF
if self.server_info.data.connection_id > 0xFF000000:
self.server_info.data.local_client_id = b''
if not self.server_info.data.local_client_id:
self.server_info.data.local_client_id = os.urandom(4)
logging.debug("local_client_id %s" % (binascii.hexlify(self.server_info.data.local_client_id),))
self.server_info.data.connection_id = struct.unpack('<I', os.urandom(4))[0] & 0xFFFFFF
self.server_info.data.connection_id += 1
return b''.join([struct.pack('<I', utc_time),
self.server_info.data.local_client_id,
struct.pack('<I', self.server_info.data.connection_id)])
def client_pre_encrypt(self, buf):
ret = b''
if not self.has_sent_header:
head_size = self.get_head_size(buf, 30)
datalen = min(len(buf), random.randint(0, 31) + head_size)
ret += self.pack_data(self.auth_data() + buf[:datalen])
buf = buf[datalen:]
self.has_sent_header = True
while len(buf) > self.unit_len:
ret += self.pack_data(buf[:self.unit_len])
buf = buf[self.unit_len:]
ret += self.pack_data(buf)
return ret
def client_post_decrypt(self, buf):
if self.raw_trans:
return buf
self.recv_buf += buf
out_buf = b''
while len(self.recv_buf) > 2:
length = struct.unpack('>H', self.recv_buf[:2])[0]
if length >= 8192 or length < 7:
self.raw_trans = True
self.recv_buf = b''
raise Exception('client_post_decrypt data error')
if length > len(self.recv_buf):
break
if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff:
self.raw_trans = True
self.recv_buf = b''
raise Exception('client_post_decrypt data uncorrect CRC32')
pos = common.ord(self.recv_buf[2]) + 2
out_buf += self.recv_buf[pos:length - 4]
self.recv_buf = self.recv_buf[length:]
if out_buf:
self.decrypt_packet_num += 1
return out_buf
def server_pre_encrypt(self, buf):
ret = b''
while len(buf) > self.unit_len:
ret += self.pack_data(buf[:self.unit_len])
buf = buf[self.unit_len:]
ret += self.pack_data(buf)
return ret
def server_post_decrypt(self, buf):
if self.raw_trans:
return (buf, False)
self.recv_buf += buf
out_buf = b''
while len(self.recv_buf) > 2:
length = struct.unpack('>H', self.recv_buf[:2])[0]
if length >= 8192 or length < 7:
self.raw_trans = True
self.recv_buf = b''
if self.decrypt_packet_num == 0:
logging.info('auth_simple: over size')
return (b'E', False)
else:
raise Exception('server_post_decrype data error')
if length > len(self.recv_buf):
break
if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff:
logging.info('auth_simple: crc32 error, data %s' % (binascii.hexlify(self.recv_buf[:length]),))
self.raw_trans = True
self.recv_buf = b''
if self.decrypt_packet_num == 0:
return (b'E', False)
else:
raise Exception('server_post_decrype data uncorrect CRC32')
pos = common.ord(self.recv_buf[2]) + 2
out_buf += self.recv_buf[pos:length - 4]
if not self.has_recv_header:
if len(out_buf) < 12:
self.raw_trans = True
self.recv_buf = b''
logging.info('auth_simple: too short')
return (b'E', False)
utc_time = struct.unpack('<I', out_buf[:4])[0]
client_id = struct.unpack('<I', out_buf[4:8])[0]
connection_id = struct.unpack('<I', out_buf[8:12])[0]
time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time)
if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \
or common.int32(utc_time - self.server_info.data.startup_time) < 0:
self.raw_trans = True
self.recv_buf = b''
logging.info('auth_simple: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),))
return (b'E', False)
elif self.server_info.data.insert(client_id, connection_id):
self.has_recv_header = True
out_buf = out_buf[12:]
self.client_id = client_id
self.connection_id = connection_id
else:
self.raw_trans = True
self.recv_buf = b''
logging.info('auth_simple: auth fail, data %s' % (binascii.hexlify(out_buf),))
return (b'E', False)
self.recv_buf = self.recv_buf[length:]
if out_buf:
self.server_info.data.update(self.client_id, self.connection_id)
self.decrypt_packet_num += 1
return (out_buf, False)
class auth_sha1(verify_base):
def __init__(self, method):
super(auth_sha1, self).__init__(method)
@ -476,7 +316,7 @@ class auth_sha1(verify_base):
utc_time = struct.unpack('<I', out_buf[:4])[0]
client_id = struct.unpack('<I', out_buf[4:8])[0]
connection_id = struct.unpack('<I', out_buf[8:12])[0]
time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time)
time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff))
if time_dif < -self.max_time_dif or time_dif > self.max_time_dif \
or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2:
self.raw_trans = True

37
shadowsocks/tcprelay.py

@ -345,23 +345,37 @@ class TCPRelayHandler(object):
addrs = socket.getaddrinfo(client_address[0], client_address[1], 0, socket.SOCK_STREAM, socket.SOL_TCP)
af, socktype, proto, canonname, sa = addrs[0]
address_bytes = common.inet_pton(af, sa[0])
if len(address_bytes) == 16:
if af == socket.AF_INET6:
addr = struct.unpack('>Q', address_bytes[8:])[0]
if len(address_bytes) == 4:
elif af == socket.AF_INET:
addr = struct.unpack('>I', address_bytes)[0]
else:
addr = 0
host_port = []
match_port = False
if type(host_list) == list:
host_post = common.to_str(host_list[((hash_code & 0xffffffff) + addr) % len(host_list)])
else:
host_post = common.to_str(host_list)
items = host_post.rsplit(':', 1)
for host in host_list:
items = common.to_str(host).rsplit(':', 1)
if len(items) > 1:
try:
return (items[0], int(items[1]))
port = int(items[1])
if port == self._server._listen_port:
match_port = True
host_port.append((items[0], port))
except:
pass
return (host_post, 80)
else:
host_port.append((host, 80))
if match_port:
last_host_port = host_port
host_port = []
for host in last_host_port:
if host[1] == self._server._listen_port:
host_port.append(host)
return host_port[((hash_code & 0xffffffff) + addr) % len(host_port)]
def _handel_protocol_error(self, client_address, ogn_data):
logging.warn("Protocol ERROR, TCP ogn data %s from %s:%d via port %d" % (binascii.hexlify(ogn_data), client_address[0], client_address[1], self._server._listen_port))
@ -473,10 +487,9 @@ class TCPRelayHandler(object):
data = self._handel_protocol_error(self._client_address, ogn_data)
header_result = parse_header(data)
connecttype, remote_addr, remote_port, header_length = header_result
common.connect_log('%s connecting %s:%d from %s:%d' %
common.connect_log('%s connecting %s:%d via port %d' %
((connecttype == 0) and 'TCP' or 'UDP',
common.to_str(remote_addr), remote_port,
self._client_address[0], self._client_address[1]))
common.to_str(remote_addr), remote_port, self._server._listen_port))
self._remote_address = (common.to_str(remote_addr), remote_port)
self._remote_udp = (connecttype != 0)
# pause reading
@ -815,7 +828,7 @@ class TCPRelayHandler(object):
if self._remote_sock:
logging.error(eventloop.get_sock_error(self._remote_sock))
if self._remote_address:
logging.error("when connect to %s:%d from %s:%d" % (self._remote_address[0], self._remote_address[1], self._client_address[0], self._client_address[1]))
logging.error("when connect to %s:%d" % (self._remote_address[0], self._remote_address[1]))
else:
logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1]))
self.destroy()

Loading…
Cancel
Save