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))
|
result.append(cipher.update(data))
|
||||||
return b''.join(result)
|
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 = [
|
CIPHERS_TO_TEST = [
|
||||||
'aes-128-cfb',
|
'aes-128-cfb',
|
||||||
|
|
|
@ -85,6 +85,18 @@ class obfs(object):
|
||||||
def server_post_decrypt(self, buf):
|
def server_post_decrypt(self, buf):
|
||||||
return self.obfs.server_post_decrypt(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):
|
def dispose(self):
|
||||||
self.obfs.dispose()
|
self.obfs.dispose()
|
||||||
del self.obfs
|
del self.obfs
|
||||||
|
|
|
@ -69,6 +69,18 @@ class plain(object):
|
||||||
def server_post_decrypt(self, buf):
|
def server_post_decrypt(self, buf):
|
||||||
return 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):
|
def dispose(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -342,3 +342,19 @@ class verify_sha1(verify_base):
|
||||||
|
|
||||||
return out_buf
|
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 binascii
|
||||||
import traceback
|
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
|
from shadowsocks.common import pre_parse_header, parse_header, pack_addr
|
||||||
|
|
||||||
# we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time
|
# 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_ul = 0
|
||||||
self.server_transfer_dl = 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._sockets = set()
|
||||||
self._fd_to_handlers = {}
|
self._fd_to_handlers = {}
|
||||||
self._reqid_to_hd = {}
|
self._reqid_to_hd = {}
|
||||||
|
@ -991,11 +1005,14 @@ class UDPRelay(object):
|
||||||
else:
|
else:
|
||||||
data = data[3:]
|
data = data[3:]
|
||||||
else:
|
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
|
# decrypt data
|
||||||
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
|
||||||
|
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),))
|
#logging.info("UDP data %s" % (binascii.hexlify(data),))
|
||||||
if not self._is_local:
|
if not self._is_local:
|
||||||
|
@ -1121,7 +1138,11 @@ class UDPRelay(object):
|
||||||
r_addr[0], r_addr[1]))
|
r_addr[0], r_addr[1]))
|
||||||
|
|
||||||
if self._is_local:
|
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:
|
if not data:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -1151,15 +1172,21 @@ class UDPRelay(object):
|
||||||
# drop
|
# drop
|
||||||
return
|
return
|
||||||
data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
|
data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
|
||||||
response = encrypt.encrypt_all(self._password, self._method, 1,
|
ref_iv = [encrypt.encrypt_new_iv(self._method)]
|
||||||
data)
|
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:
|
if not response:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
data = encrypt.encrypt_all(self._password, self._method, 0,
|
ref_iv = [0]
|
||||||
data)
|
data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0,
|
||||||
|
data, ref_iv)
|
||||||
if not data:
|
if not data:
|
||||||
return
|
return
|
||||||
|
self._protocol.obfs.server_info.recv_iv = ref_iv[0]
|
||||||
|
data = self._protocol.client_udp_post_decrypt(data)
|
||||||
header_result = parse_header(data)
|
header_result = parse_header(data)
|
||||||
if header_result is None:
|
if header_result is None:
|
||||||
return
|
return
|
||||||
|
|
Loading…
Add table
Reference in a new issue