always UDP on
random length TCP/UDP packet
This commit is contained in:
parent
28318b5c1a
commit
d4ca0d281c
4 changed files with 50 additions and 36 deletions
|
@ -46,7 +46,6 @@ class ServerPool(object):
|
||||||
shell.print_shadowsocks()
|
shell.print_shadowsocks()
|
||||||
self.dns_resolver = asyncdns.DNSResolver()
|
self.dns_resolver = asyncdns.DNSResolver()
|
||||||
self.mgr = asyncmgr.ServerMgr()
|
self.mgr = asyncmgr.ServerMgr()
|
||||||
self.udp_on = True ### UDP switch =====================================
|
|
||||||
|
|
||||||
self.tcp_servers_pool = {}
|
self.tcp_servers_pool = {}
|
||||||
self.tcp_ipv6_servers_pool = {}
|
self.tcp_ipv6_servers_pool = {}
|
||||||
|
@ -110,19 +109,21 @@ class ServerPool(object):
|
||||||
a_config['password'] = password
|
a_config['password'] = password
|
||||||
try:
|
try:
|
||||||
logging.info("starting server at [%s]:%d" % (a_config['server'], port))
|
logging.info("starting server at [%s]:%d" % (a_config['server'], port))
|
||||||
|
|
||||||
tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False)
|
tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False)
|
||||||
tcp_server.add_to_loop(self.loop)
|
tcp_server.add_to_loop(self.loop)
|
||||||
self.tcp_ipv6_servers_pool.update({port: tcp_server})
|
self.tcp_ipv6_servers_pool.update({port: tcp_server})
|
||||||
if self.udp_on:
|
|
||||||
udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False)
|
udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False)
|
||||||
udp_server.add_to_loop(self.loop)
|
udp_server.add_to_loop(self.loop)
|
||||||
self.udp_ipv6_servers_pool.update({port: udp_server})
|
self.udp_ipv6_servers_pool.update({port: udp_server})
|
||||||
|
|
||||||
if a_config['server_ipv6'] == "::":
|
if a_config['server_ipv6'] == "::":
|
||||||
ipv6_ok = True
|
ipv6_ok = True
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logging.warn("IPV6 %s " % (e,))
|
logging.warn("IPV6 %s " % (e,))
|
||||||
|
|
||||||
if not ipv6_ok and 'server' in self.config:
|
if 'server' in self.config:
|
||||||
if port in self.tcp_servers_pool:
|
if port in self.tcp_servers_pool:
|
||||||
logging.info("server already at %s:%d" % (self.config['server'], port))
|
logging.info("server already at %s:%d" % (self.config['server'], port))
|
||||||
return 'this port server is already running'
|
return 'this port server is already running'
|
||||||
|
@ -132,13 +133,16 @@ class ServerPool(object):
|
||||||
a_config['password'] = password
|
a_config['password'] = password
|
||||||
try:
|
try:
|
||||||
logging.info("starting server at %s:%d" % (a_config['server'], port))
|
logging.info("starting server at %s:%d" % (a_config['server'], port))
|
||||||
tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False)
|
|
||||||
tcp_server.add_to_loop(self.loop)
|
if not ipv6_ok:
|
||||||
self.tcp_servers_pool.update({port: tcp_server})
|
tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False)
|
||||||
if self.udp_on:
|
tcp_server.add_to_loop(self.loop)
|
||||||
|
self.tcp_servers_pool.update({port: tcp_server})
|
||||||
|
|
||||||
udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False)
|
udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False)
|
||||||
udp_server.add_to_loop(self.loop)
|
udp_server.add_to_loop(self.loop)
|
||||||
self.udp_servers_pool.update({port: udp_server})
|
self.udp_servers_pool.update({port: udp_server})
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logging.warn("IPV4 %s " % (e,))
|
logging.warn("IPV4 %s " % (e,))
|
||||||
|
|
||||||
|
@ -167,12 +171,11 @@ class ServerPool(object):
|
||||||
del self.tcp_servers_pool[port]
|
del self.tcp_servers_pool[port]
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logging.warn(e)
|
logging.warn(e)
|
||||||
if self.udp_on:
|
try:
|
||||||
try:
|
self.udp_servers_pool[port].close(True)
|
||||||
self.udp_servers_pool[port].close(True)
|
del self.udp_servers_pool[port]
|
||||||
del self.udp_servers_pool[port]
|
except Exception, e:
|
||||||
except Exception, e:
|
logging.warn(e)
|
||||||
logging.warn(e)
|
|
||||||
|
|
||||||
if 'server_ipv6' in self.config:
|
if 'server_ipv6' in self.config:
|
||||||
if port not in self.tcp_ipv6_servers_pool:
|
if port not in self.tcp_ipv6_servers_pool:
|
||||||
|
@ -184,12 +187,11 @@ class ServerPool(object):
|
||||||
del self.tcp_ipv6_servers_pool[port]
|
del self.tcp_ipv6_servers_pool[port]
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logging.warn(e)
|
logging.warn(e)
|
||||||
if self.udp_on:
|
try:
|
||||||
try:
|
self.udp_ipv6_servers_pool[port].close(True)
|
||||||
self.udp_ipv6_servers_pool[port].close(True)
|
del self.udp_ipv6_servers_pool[port]
|
||||||
del self.udp_ipv6_servers_pool[port]
|
except Exception, e:
|
||||||
except Exception, e:
|
logging.warn(e)
|
||||||
logging.warn(e)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,20 @@ def pack_addr(address):
|
||||||
address = address[:255] # TODO
|
address = address[:255] # TODO
|
||||||
return b'\x03' + chr(len(address)) + address
|
return b'\x03' + chr(len(address)) + address
|
||||||
|
|
||||||
|
def pre_parse_header(data):
|
||||||
|
datatype = ord(data[0])
|
||||||
|
if datatype == 0x80 :
|
||||||
|
if len(data) <= 2:
|
||||||
|
return None
|
||||||
|
rand_data_size = ord(data[1])
|
||||||
|
if rand_data_size + 2 >= len(data):
|
||||||
|
logging.warn('header too short, maybe wrong password or '
|
||||||
|
'encryption method')
|
||||||
|
return None
|
||||||
|
data = data[rand_data_size + 2:]
|
||||||
|
elif datatype == 0x81:
|
||||||
|
data = data[1:]
|
||||||
|
return data
|
||||||
|
|
||||||
def parse_header(data):
|
def parse_header(data):
|
||||||
addrtype = ord(data[0])
|
addrtype = ord(data[0])
|
||||||
|
|
|
@ -27,7 +27,7 @@ import traceback
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from shadowsocks import encrypt, eventloop, shell, common
|
from shadowsocks import encrypt, eventloop, shell, common
|
||||||
from shadowsocks.common import parse_header
|
from shadowsocks.common import pre_parse_header, parse_header
|
||||||
|
|
||||||
# we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time
|
# we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time
|
||||||
TIMEOUTS_CLEAN_SIZE = 512
|
TIMEOUTS_CLEAN_SIZE = 512
|
||||||
|
@ -320,12 +320,15 @@ class TCPRelayHandler(object):
|
||||||
logging.error('unknown command %d', cmd)
|
logging.error('unknown command %d', cmd)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
return
|
return
|
||||||
|
data = pre_parse_header(data)
|
||||||
|
if data is None:
|
||||||
|
raise Exception('can not parse header')
|
||||||
header_result = parse_header(data)
|
header_result = parse_header(data)
|
||||||
if header_result is None:
|
if header_result is None:
|
||||||
raise Exception('can not parse header')
|
raise Exception('can not parse header')
|
||||||
connecttype, remote_addr, remote_port, header_length = header_result
|
connecttype, remote_addr, remote_port, header_length = header_result
|
||||||
logging.info('%s connecting %s:%d from %s:%d' %
|
logging.info('%s connecting %s:%d from %s:%d' %
|
||||||
((connecttype == 0) and 'tcp' or 'udp',
|
((connecttype == 0) and 'TCP' or 'UDP',
|
||||||
common.to_str(remote_addr), remote_port,
|
common.to_str(remote_addr), remote_port,
|
||||||
self._client_address[0], self._client_address[1]))
|
self._client_address[0], self._client_address[1]))
|
||||||
self._remote_address = (common.to_str(remote_addr), remote_port)
|
self._remote_address = (common.to_str(remote_addr), remote_port)
|
||||||
|
@ -356,15 +359,6 @@ class TCPRelayHandler(object):
|
||||||
# TODO use logging when debug completed
|
# TODO use logging when debug completed
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
def _has_ipv6_addr(self, addr_list):
|
|
||||||
for item in addr_list:
|
|
||||||
if type(item) is list:
|
|
||||||
if self._has_ipv6_addr(item):
|
|
||||||
return True
|
|
||||||
elif ':' in item:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _create_remote_socket(self, ip, port):
|
def _create_remote_socket(self, ip, port):
|
||||||
if self._remote_udp:
|
if self._remote_udp:
|
||||||
addrs_v6 = socket.getaddrinfo("::", 0, 0, socket.SOCK_DGRAM, socket.SOL_UDP)
|
addrs_v6 = socket.getaddrinfo("::", 0, 0, socket.SOCK_DGRAM, socket.SOL_UDP)
|
||||||
|
@ -505,7 +499,7 @@ class TCPRelayHandler(object):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
ip = socket.inet_pton(socket.AF_INET6, addr[0])
|
ip = socket.inet_pton(socket.AF_INET6, addr[0])
|
||||||
data = '\x00\x00\x00\x04' + ip + port + data
|
data = '\x00\x00\x00\x04' + ip + port + data
|
||||||
logging.info('udp recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1]))
|
logging.info('UDP recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1]))
|
||||||
else:
|
else:
|
||||||
data = self._remote_sock.recv(BUF_SIZE)
|
data = self._remote_sock.recv(BUF_SIZE)
|
||||||
except (OSError, IOError) as e:
|
except (OSError, IOError) as e:
|
||||||
|
|
|
@ -70,7 +70,7 @@ import errno
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from shadowsocks import encrypt, eventloop, lru_cache, common, shell
|
from shadowsocks import encrypt, eventloop, lru_cache, common, shell
|
||||||
from shadowsocks.common import parse_header, pack_addr
|
from shadowsocks.common import pre_parse_header, parse_header, pack_addr
|
||||||
|
|
||||||
|
|
||||||
BUF_SIZE = 65536
|
BUF_SIZE = 65536
|
||||||
|
@ -159,6 +159,10 @@ class UDPRelay(object):
|
||||||
if not data:
|
if not data:
|
||||||
logging.debug('UDP handle_server: data is empty after decrypt')
|
logging.debug('UDP handle_server: data is empty after decrypt')
|
||||||
return
|
return
|
||||||
|
data = pre_parse_header(data)
|
||||||
|
if data is None:
|
||||||
|
return
|
||||||
|
|
||||||
header_result = parse_header(data)
|
header_result = parse_header(data)
|
||||||
if header_result is None:
|
if header_result is None:
|
||||||
return
|
return
|
||||||
|
@ -173,7 +177,7 @@ class UDPRelay(object):
|
||||||
client = self._cache.get(key, None)
|
client = self._cache.get(key, None)
|
||||||
if not client:
|
if not client:
|
||||||
# TODO async getaddrinfo
|
# TODO async getaddrinfo
|
||||||
logging.info('UDP handle_server %s:%d from %s:%d' % (common.to_str(server_addr), server_port, self._listen_addr, self._listen_port))
|
#logging.info('UDP handle_server %s:%d from %s:%d' % (common.to_str(server_addr), server_port, self._listen_addr, self._listen_port))
|
||||||
addrs = socket.getaddrinfo(server_addr, server_port, 0,
|
addrs = socket.getaddrinfo(server_addr, server_port, 0,
|
||||||
socket.SOCK_DGRAM, socket.SOL_UDP)
|
socket.SOCK_DGRAM, socket.SOL_UDP)
|
||||||
if addrs:
|
if addrs:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue