Merge branch 'fixbug-ci'

This commit is contained in:
mengskysama 2016-01-12 14:30:08 +08:00
commit e1e17c8e23
13 changed files with 97 additions and 23 deletions

View file

@ -1,6 +1,10 @@
shadowsocks
===========
[![PyPI version]][PyPI]
[![Build Status]][Travis CI]
[![Coverage Status]][Coverage]
A fast tunnel proxy that helps you bypass firewalls.
Features:

View file

@ -133,6 +133,42 @@ class Encryptor(object):
return self.decipher.update(buf)
def gen_key_iv(password, method):
method = method.lower()
(key_len, iv_len, m) = method_supported[method]
key = None
if key_len > 0:
key, _ = EVP_BytesToKey(password, key_len, iv_len)
else:
key = password
iv = random_string(iv_len)
return key, iv, m
def encrypt_all_m(key, iv, m, method, data):
result = []
result.append(iv)
cipher = m(method, key, iv, 1)
result.append(cipher.update(data))
return b''.join(result)
def dencrypt_all(password, method, data):
result = []
method = method.lower()
(key_len, iv_len, m) = method_supported[method]
key = None
if key_len > 0:
key, _ = EVP_BytesToKey(password, key_len, iv_len)
else:
key = password
iv = data[:iv_len]
data = data[iv_len:]
cipher = m(method, key, iv, 0)
result.append(cipher.update(data))
return b''.join(result), key, iv
def encrypt_all(password, method, op, data):
result = []
method = method.lower()
@ -185,6 +221,18 @@ def test_encrypt_all():
assert plain == plain2
def test_encrypt_all_m():
from os import urandom
plain = urandom(10240)
for method in CIPHERS_TO_TEST:
logging.warn(method)
key, iv, m = gen_key_iv(b'key', method)
cipher = encrypt_all_m(key, iv, m, method, plain)
plain2, key, iv = dencrypt_all(b'key', method, cipher)
assert plain == plain2
if __name__ == '__main__':
test_encrypt_all()
test_encryptor()
test_encrypt_all_m()

View file

@ -113,8 +113,8 @@ class TCPRelayHandler(object):
self._ota_enable = True
else:
self._ota_enable = False
self._ota_buff_head = ''
self._ota_buff_data = ''
self._ota_buff_head = b''
self._ota_buff_data = b''
self._ota_len = 0
self._ota_chunk_idx = 0
self._fastopen_connected = False
@ -242,6 +242,8 @@ class TCPRelayHandler(object):
if self._ota_enable:
self._ota_chunk_data(data,
self._data_to_write_to_remote.append)
else:
self._data_to_write_to_remote.append(data)
if self._is_local and not self._fastopen_connected and \
self._config['fast_open']:
# for sslocal and fastopen, we basically wait for data and use
@ -336,7 +338,7 @@ class TCPRelayHandler(object):
# spec https://shadowsocks.org/en/spec/one-time-auth.html
# ATYP & 0x10 == 1, then OTA is enabled.
if self._ota_enable:
data = chr(ord(data[0]) | ADDRTYPE_AUTH) + data[1:]
data = common.chr(addrtype | ADDRTYPE_AUTH) + data[1:]
key = self._encryptor.cipher_iv + self._encryptor.key
data += onetimeauth_gen(data, key)
data_to_send = self._encryptor.encrypt(data)
@ -453,8 +455,8 @@ class TCPRelayHandler(object):
else:
data_cb(self._ota_buff_data)
self._ota_chunk_idx += 1
self._ota_buff_head = ''
self._ota_buff_data = ''
self._ota_buff_head = b''
self._ota_buff_data = b''
self._ota_len = 0
return
@ -475,6 +477,8 @@ class TCPRelayHandler(object):
else:
if self._ota_enable:
self._ota_chunk_data(data, self._write_to_sock_remote)
else:
self._write_to_sock(data, self._remote_sock)
return
def _on_local_read(self):

View file

@ -150,6 +150,8 @@ class UDPRelay(object):
def _handle_server(self):
server = self._server_socket
data, r_addr = server.recvfrom(BUF_SIZE)
key = None
iv = None
if not data:
logging.debug('UDP handle_server: data is empty')
if self._stat_callback:
@ -162,7 +164,9 @@ class UDPRelay(object):
else:
data = data[3:]
else:
data = encrypt.encrypt_all(self._password, self._method, 0, data)
data, key, iv = encrypt.dencrypt_all(self._password,
self._method,
data)
# decrypt data
if not data:
logging.debug(
@ -184,13 +188,11 @@ class UDPRelay(object):
logging.warn('UDP one time auth header is too short')
return
_hash = data[-ONETIMEAUTH_BYTES:]
_data = data[header_length: -ONETIMEAUTH_BYTES]
_key = self._encryptor.decipher_iv + self._encryptor.key
if onetimeauth_verify(_hash, _data, _key) is False:
data = data[: -ONETIMEAUTH_BYTES]
_key = iv + key
if onetimeauth_verify(_hash, data, _key) is False:
logging.warn('UDP one time auth fail')
return
self._one_time_authed = True
header_length += ONETIMEAUTH_BYTES
addrs = self._dns_cache.get(server_addr, None)
if addrs is None:
addrs = socket.getaddrinfo(server_addr, server_port, 0,
@ -221,10 +223,11 @@ class UDPRelay(object):
self._eventloop.add(client, eventloop.POLL_IN, self)
if self._is_local:
key, iv, m = encrypt.gen_key_iv(self._password, self._method)
# spec https://shadowsocks.org/en/spec/one-time-auth.html
if self._one_time_auth_enable:
data = self._one_time_auth_chunk_data_gen(data)
data = encrypt.encrypt_all(self._password, self._method, 1, data)
data = self._ota_chunk_data_gen(key, iv, data)
data = encrypt.encrypt_all_m(key, iv, m, self._method, data)
if not data:
return
else:
@ -275,9 +278,9 @@ class UDPRelay(object):
# simply drop that packet
pass
def _one_time_auth_chunk_data_gen(self, data):
data = chr(ord(data[0]) | ADDRTYPE_AUTH) + data[1:]
key = self._encryptor.cipher_iv + self._encryptor.key
def _ota_chunk_data_gen(self, key, iv, data):
data = common.chr(common.ord(data[0]) | ADDRTYPE_AUTH) + data[1:]
key = iv + key
return data + onetimeauth_gen(data, key)
def add_to_loop(self, loop):

View file

@ -45,7 +45,9 @@ run_test python tests/test.py --with-coverage -s tests/aes.json -c tests/client-
run_test python tests/test.py --with-coverage -s tests/server-dnsserver.json -c tests/client-multi-server-ip.json
run_test python tests/test.py --with-coverage -s tests/server-multi-passwd.json -c tests/server-multi-passwd-client-side.json
run_test python tests/test.py --with-coverage -c tests/workers.json
run_test python tests/test.py --with-coverage -s tests/ipv6.json -c tests/ipv6-client-side.json
run_test python tests/test.py --with-coverage -c tests/rc4-md5-ota.json
# travis-ci not support IPv6
# run_test python tests/test.py --with-coverage -s tests/ipv6.json -c tests/ipv6-client-side.json
run_test python tests/test.py --with-coverage -b "-m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -q" -a "-m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -vv"
run_test python tests/test.py --with-coverage -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 --workers 1" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -t 30 -qq -b 127.0.0.1"
run_test python tests/test.py --with-coverage --should-fail --url="http://127.0.0.1/" -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 --forbidden-ip=127.0.0.1,::1,8.8.8.8" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -t 30 -b 127.0.0.1"

11
tests/rc4-md5-ota.json Normal file
View file

@ -0,0 +1,11 @@
{
"server":"127.0.0.1",
"server_port":8388,
"local_port":1081,
"password":"aes_password",
"timeout":60,
"method":"rc4-md5",
"local_address":"127.0.0.1",
"fast_open":false,
"one_time_auth":true
}

View file

@ -44,7 +44,7 @@ parser.add_argument('--dns', type=str, default='8.8.8.8')
config = parser.parse_args()
if config.with_coverage:
python = ['coverage', 'run', '-p', '-a']
python = ['coverage', 'run', '-a']
client_args = python + ['shadowsocks/local.py', '-v']
server_args = python + ['shadowsocks/server.py', '-v']

View file

@ -2,7 +2,7 @@
. tests/assert.sh
PYTHON="coverage run -a -p"
PYTHON="coverage run -a"
LOCAL="$PYTHON shadowsocks/local.py"
SERVER="$PYTHON shadowsocks/server.py"

View file

@ -18,7 +18,7 @@ function run_test {
for module in local server
do
command="coverage run -p -a shadowsocks/$module.py"
command="coverage run -a shadowsocks/$module.py"
mkdir -p tmp

View file

@ -1,6 +1,6 @@
#!/bin/bash
PYTHON="coverage run -p -a"
PYTHON="coverage run -a"
URL=http://127.0.0.1/file

View file

@ -1,6 +1,6 @@
#!/bin/bash
PYTHON="coverage run -p -a"
PYTHON="coverage run -a"
URL=http://127.0.0.1/file
mkdir -p tmp

View file

@ -36,6 +36,7 @@ if __name__ == '__main__':
# make sure they're from the same source port
assert result1 == result2
"""
# Test 2: same source port IPv6
# try again from the same port but IPv6
sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM,
@ -81,3 +82,4 @@ if __name__ == '__main__':
sock_out.close()
sock_in1.close()
"""

View file

@ -1,6 +1,6 @@
#!/bin/bash
PYTHON="coverage run -p -a"
PYTHON="coverage run -a"
mkdir -p tmp