support UDP protocol plugin
This commit is contained in:
parent
b151bf815f
commit
42a05d22d6
5 changed files with 108 additions and 7 deletions
|
@ -159,6 +159,40 @@ def encrypt_all(password, method, op, data):
|
|||
result.append(cipher.update(data))
|
||||
return b''.join(result)
|
||||
|
||||
def encrypt_key(password, method):
|
||||
method = method.lower()
|
||||
(key_len, iv_len, m) = method_supported[method]
|
||||
if key_len > 0:
|
||||
key, _ = EVP_BytesToKey(password, key_len, iv_len)
|
||||
else:
|
||||
key = password
|
||||
return key
|
||||
|
||||
def encrypt_iv_len(method):
|
||||
method = method.lower()
|
||||
(key_len, iv_len, m) = method_supported[method]
|
||||
return iv_len
|
||||
|
||||
def encrypt_new_iv(method):
|
||||
method = method.lower()
|
||||
(key_len, iv_len, m) = method_supported[method]
|
||||
return random_string(iv_len)
|
||||
|
||||
def encrypt_all_iv(key, method, op, data, ref_iv):
|
||||
result = []
|
||||
method = method.lower()
|
||||
(key_len, iv_len, m) = method_supported[method]
|
||||
if op:
|
||||
iv = ref_iv[0]
|
||||
result.append(iv)
|
||||
else:
|
||||
iv = data[:iv_len]
|
||||
data = data[iv_len:]
|
||||
ref_iv[0] = iv
|
||||
cipher = m(method, key, iv, op)
|
||||
result.append(cipher.update(data))
|
||||
return b''.join(result)
|
||||
|
||||
|
||||
CIPHERS_TO_TEST = [
|
||||
'aes-128-cfb',
|
||||
|
|
|
@ -85,6 +85,18 @@ class obfs(object):
|
|||
def server_post_decrypt(self, buf):
|
||||
return self.obfs.server_post_decrypt(buf)
|
||||
|
||||
def client_udp_pre_encrypt(self, buf):
|
||||
return self.obfs.client_udp_pre_encrypt(buf)
|
||||
|
||||
def client_udp_post_decrypt(self, buf):
|
||||
return self.obfs.client_udp_post_decrypt(buf)
|
||||
|
||||
def server_udp_pre_encrypt(self, buf):
|
||||
return self.obfs.server_udp_pre_encrypt(buf)
|
||||
|
||||
def server_udp_post_decrypt(self, buf):
|
||||
return self.obfs.server_udp_post_decrypt(buf)
|
||||
|
||||
def dispose(self):
|
||||
self.obfs.dispose()
|
||||
del self.obfs
|
||||
|
|
|
@ -69,6 +69,18 @@ class plain(object):
|
|||
def server_post_decrypt(self, buf):
|
||||
return buf
|
||||
|
||||
def client_udp_pre_encrypt(self, buf):
|
||||
return buf
|
||||
|
||||
def client_udp_post_decrypt(self, buf):
|
||||
return buf
|
||||
|
||||
def server_udp_pre_encrypt(self, buf):
|
||||
return buf
|
||||
|
||||
def server_udp_post_decrypt(self, buf):
|
||||
return buf
|
||||
|
||||
def dispose(self):
|
||||
pass
|
||||
|
||||
|
|
|
@ -342,3 +342,19 @@ class verify_sha1(verify_base):
|
|||
|
||||
return out_buf
|
||||
|
||||
def client_udp_pre_encrypt(self, buf):
|
||||
ret = self.pack_auth_data(buf)
|
||||
return chr(ord(buf[0]) | 0x10) + buf[1:]
|
||||
|
||||
def server_udp_post_decrypt(self, buf):
|
||||
if buf and ((ord(buf[0]) & 0x10) == 0x10):
|
||||
if len(buf) <= 11:
|
||||
return b'E'
|
||||
sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, buf[:-10], hashlib.sha1).digest()[:10]
|
||||
if sha1data != buf[-10:]:
|
||||
logging.error('server_udp_post_decrypt data uncorrect auth HMAC-SHA1')
|
||||
return b'E'
|
||||
return to_bytes(chr(ord(buf[0]) & 0xEF)) + buf[1:-10]
|
||||
else:
|
||||
return buf
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ import random
|
|||
import binascii
|
||||
import traceback
|
||||
|
||||
from shadowsocks import encrypt, eventloop, lru_cache, common, shell
|
||||
from shadowsocks import encrypt, obfs, eventloop, lru_cache, common, shell
|
||||
from shadowsocks.common import pre_parse_header, parse_header, pack_addr
|
||||
|
||||
# we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time
|
||||
|
@ -890,6 +890,20 @@ class UDPRelay(object):
|
|||
self.server_transfer_ul = 0
|
||||
self.server_transfer_dl = 0
|
||||
|
||||
self.protocol_data = obfs.obfs(config['protocol']).init_data()
|
||||
self._protocol = obfs.obfs(config['protocol'])
|
||||
server_info = obfs.server_info(self.protocol_data)
|
||||
server_info.host = self._listen_addr
|
||||
server_info.port = self._listen_port
|
||||
server_info.protocol_param = config['protocol_param']
|
||||
server_info.obfs_param = ''
|
||||
server_info.iv = b''
|
||||
server_info.recv_iv = b''
|
||||
server_info.key = encrypt.encrypt_key(self._password, self._method)
|
||||
server_info.head_len = 30
|
||||
server_info.tcp_mss = 1440
|
||||
self._protocol.set_server_info(server_info)
|
||||
|
||||
self._sockets = set()
|
||||
self._fd_to_handlers = {}
|
||||
self._reqid_to_hd = {}
|
||||
|
@ -991,11 +1005,14 @@ class UDPRelay(object):
|
|||
else:
|
||||
data = data[3:]
|
||||
else:
|
||||
data = encrypt.encrypt_all(self._password, self._method, 0, data)
|
||||
ref_iv = [0]
|
||||
data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0, data, ref_iv)
|
||||
# decrypt data
|
||||
if not data:
|
||||
logging.debug('UDP handle_server: data is empty after decrypt')
|
||||
return
|
||||
self._protocol.obfs.server_info.recv_iv = ref_iv[0]
|
||||
data = self._protocol.server_udp_post_decrypt(data)
|
||||
|
||||
#logging.info("UDP data %s" % (binascii.hexlify(data),))
|
||||
if not self._is_local:
|
||||
|
@ -1121,7 +1138,11 @@ class UDPRelay(object):
|
|||
r_addr[0], r_addr[1]))
|
||||
|
||||
if self._is_local:
|
||||
data = encrypt.encrypt_all(self._password, self._method, 1, data)
|
||||
ref_iv = [encrypt.encrypt_new_iv(self._method)]
|
||||
self._protocol.obfs.server_info.iv = ref_iv[0]
|
||||
data = self._protocol.client_udp_pre_encrypt(data)
|
||||
logging.info("%s" % (binascii.hexlify(data),))
|
||||
data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1, data, ref_iv)
|
||||
if not data:
|
||||
return
|
||||
else:
|
||||
|
@ -1151,15 +1172,21 @@ class UDPRelay(object):
|
|||
# drop
|
||||
return
|
||||
data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
|
||||
response = encrypt.encrypt_all(self._password, self._method, 1,
|
||||
data)
|
||||
ref_iv = [encrypt.encrypt_new_iv(self._method)]
|
||||
self._protocol.obfs.server_info.iv = ref_iv[0]
|
||||
data = self._protocol.server_udp_pre_encrypt(data)
|
||||
response = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1,
|
||||
data, ref_iv)
|
||||
if not response:
|
||||
return
|
||||
else:
|
||||
data = encrypt.encrypt_all(self._password, self._method, 0,
|
||||
data)
|
||||
ref_iv = [0]
|
||||
data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0,
|
||||
data, ref_iv)
|
||||
if not data:
|
||||
return
|
||||
self._protocol.obfs.server_info.recv_iv = ref_iv[0]
|
||||
data = self._protocol.client_udp_post_decrypt(data)
|
||||
header_result = parse_header(data)
|
||||
if header_result is None:
|
||||
return
|
||||
|
|
Loading…
Add table
Reference in a new issue