Browse Source

Merge pull request #27 from falseen/manyuser-travis

fix travis
dev
BreakWa11 9 years ago
parent
commit
7f480248f8
  1. 2
      .travis.yml
  2. 4
      README.md
  3. 1
      __init__.py
  4. 39
      setup.py
  5. 1
      shadowsocks/asyncdns.py
  6. 6
      shadowsocks/common.py
  7. 117
      shadowsocks/crypto/m2.py
  8. 8
      shadowsocks/encrypt_test.py
  9. 1
      shadowsocks/local.py
  10. 5
      shadowsocks/manager.py
  11. 1
      shadowsocks/server.py
  12. 0
      tests/assert.sh
  13. 2
      tests/test.py
  14. 15
      tests/test_command.sh
  15. 2
      tests/test_daemon.sh
  16. 2
      tests/test_large_file.sh
  17. 83
      tests/test_udp_src.py
  18. 23
      tests/test_udp_src.sh

2
.travis.yml

@ -13,7 +13,7 @@ before_install:
- sudo dd if=/dev/urandom of=/usr/share/nginx/www/file bs=1M count=10 - sudo dd if=/dev/urandom of=/usr/share/nginx/www/file bs=1M count=10
- sudo sh -c "echo '127.0.0.1 localhost' > /etc/hosts" - sudo sh -c "echo '127.0.0.1 localhost' > /etc/hosts"
- sudo service nginx restart - sudo service nginx restart
- pip install pep8 pyflakes nose coverage - pip install pep8 pyflakes nose coverage PySocks cymysql
- sudo tests/socksify/install.sh - sudo tests/socksify/install.sh
- sudo tests/libsodium/install.sh - sudo tests/libsodium/install.sh
- sudo tests/setup_tc.sh - sudo tests/setup_tc.sh

4
README.md

@ -87,7 +87,7 @@ Bugs and Issues
[Android]: https://github.com/shadowsocks/shadowsocks-android [Android]: https://github.com/shadowsocks/shadowsocks-android
[Build Status]: https://img.shields.io/travis/shadowsocks/shadowsocks/master.svg?style=flat [Build Status]: https://travis-ci.org/falseen/shadowsocks.svg?branch=manyuser-travis
[Configuration]: https://github.com/shadowsocks/shadowsocks/wiki/Configuration-via-Config-File [Configuration]: https://github.com/shadowsocks/shadowsocks/wiki/Configuration-via-Config-File
[Coverage Status]: https://jenkins.shadowvpn.org/result/shadowsocks [Coverage Status]: https://jenkins.shadowvpn.org/result/shadowsocks
[Coverage]: https://jenkins.shadowvpn.org/job/Shadowsocks/ws/PYENV/py34/label/linux/htmlcov/index.html [Coverage]: https://jenkins.shadowvpn.org/job/Shadowsocks/ws/PYENV/py34/label/linux/htmlcov/index.html
@ -100,7 +100,7 @@ Bugs and Issues
[OS X]: https://github.com/shadowsocks/shadowsocks-iOS/wiki/Shadowsocks-for-OSX-Help [OS X]: https://github.com/shadowsocks/shadowsocks-iOS/wiki/Shadowsocks-for-OSX-Help
[PyPI]: https://pypi.python.org/pypi/shadowsocks [PyPI]: https://pypi.python.org/pypi/shadowsocks
[PyPI version]: https://img.shields.io/pypi/v/shadowsocks.svg?style=flat [PyPI version]: https://img.shields.io/pypi/v/shadowsocks.svg?style=flat
[Travis CI]: https://travis-ci.org/shadowsocks/shadowsocks [Travis CI]: https://travis-ci.org/falseen/shadowsocks
[Troubleshooting]: https://github.com/shadowsocks/shadowsocks/wiki/Troubleshooting [Troubleshooting]: https://github.com/shadowsocks/shadowsocks/wiki/Troubleshooting
[Wiki]: https://github.com/shadowsocks/shadowsocks/wiki [Wiki]: https://github.com/shadowsocks/shadowsocks/wiki
[Windows]: https://github.com/shadowsocks/shadowsocks-csharp [Windows]: https://github.com/shadowsocks/shadowsocks-csharp

1
__init__.py

@ -1 +0,0 @@
#!/usr/bin/python

39
setup.py

@ -0,0 +1,39 @@
import codecs
from setuptools import setup
with codecs.open('README.rst', encoding='utf-8') as f:
long_description = f.read()
setup(
name="shadowsocks",
version="2.6.12",
license='http://www.apache.org/licenses/LICENSE-2.0',
description="A fast tunnel proxy that help you get through firewalls",
author='clowwindy',
author_email='clowwindy42@gmail.com',
url='https://github.com/shadowsocks/shadowsocks',
packages=['shadowsocks', 'shadowsocks.crypto'],
package_data={
'shadowsocks': ['README.rst', 'LICENSE']
},
install_requires=[],
entry_points="""
[console_scripts]
sslocal = shadowsocks.local:main
ssserver = shadowsocks.server:main
""",
classifiers=[
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Internet :: Proxy Servers',
],
long_description=long_description,
)

1
shadowsocks/asyncdns.py

@ -28,7 +28,6 @@ if __name__ == '__main__':
import sys import sys
import inspect import inspect
file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe()))) file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe())))
os.chdir(file_path)
sys.path.insert(0, os.path.join(file_path, '../')) sys.path.insert(0, os.path.join(file_path, '../'))
from shadowsocks import common, lru_cache, eventloop, shell from shadowsocks import common, lru_cache, eventloop, shell

6
shadowsocks/common.py

@ -294,12 +294,12 @@ def test_inet_conv():
def test_parse_header(): def test_parse_header():
assert parse_header(b'\x03\x0ewww.google.com\x00\x50') == \ assert parse_header(b'\x03\x0ewww.google.com\x00\x50') == \
(3, b'www.google.com', 80, 18) (0, b'www.google.com', 80, 18)
assert parse_header(b'\x01\x08\x08\x08\x08\x00\x35') == \ assert parse_header(b'\x01\x08\x08\x08\x08\x00\x35') == \
(1, b'8.8.8.8', 53, 7) (0, b'8.8.8.8', 53, 7)
assert parse_header((b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00' assert parse_header((b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00'
b'\x00\x10\x11\x00\x50')) == \ b'\x00\x10\x11\x00\x50')) == \
(4, b'2404:6800:4005:805::1011', 80, 19) (0, b'2404:6800:4005:805::1011', 80, 19)
def test_pack_header(): def test_pack_header():

117
shadowsocks/crypto/m2.py

@ -1,117 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2014 clowwindy
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import absolute_import, division, print_function, \
with_statement
import sys
import logging
__all__ = ['ciphers']
has_m2 = True
try:
__import__('M2Crypto')
except ImportError:
has_m2 = False
def create_cipher(alg, key, iv, op, key_as_bytes=0, d=None, salt=None, i=1,
padding=1):
import M2Crypto.EVP
return M2Crypto.EVP.Cipher(alg.replace('-', '_'), key, iv, op,
key_as_bytes=0, d='md5', salt=None, i=1,
padding=1)
def err(alg, key, iv, op, key_as_bytes=0, d=None, salt=None, i=1, padding=1):
logging.error(('M2Crypto is required to use %s, please run'
' `apt-get install python-m2crypto`') % alg)
sys.exit(1)
if has_m2:
ciphers = {
b'aes-128-cfb': (16, 16, create_cipher),
b'aes-192-cfb': (24, 16, create_cipher),
b'aes-256-cfb': (32, 16, create_cipher),
b'bf-cfb': (16, 8, create_cipher),
b'camellia-128-cfb': (16, 16, create_cipher),
b'camellia-192-cfb': (24, 16, create_cipher),
b'camellia-256-cfb': (32, 16, create_cipher),
b'cast5-cfb': (16, 8, create_cipher),
b'des-cfb': (8, 8, create_cipher),
b'idea-cfb': (16, 8, create_cipher),
b'rc2-cfb': (16, 8, create_cipher),
b'rc4': (16, 0, create_cipher),
b'seed-cfb': (16, 16, create_cipher),
}
else:
ciphers = {}
def run_method(method):
from shadowsocks.crypto import util
cipher = create_cipher(method, b'k' * 32, b'i' * 16, 1)
decipher = create_cipher(method, b'k' * 32, b'i' * 16, 0)
util.run_cipher(cipher, decipher)
def check_env():
# skip this test on pypy and Python 3
try:
import __pypy__
del __pypy__
from nose.plugins.skip import SkipTest
raise SkipTest
except ImportError:
pass
if bytes != str:
from nose.plugins.skip import SkipTest
raise SkipTest
def test_aes_128_cfb():
check_env()
run_method(b'aes-128-cfb')
def test_aes_256_cfb():
check_env()
run_method(b'aes-256-cfb')
def test_bf_cfb():
check_env()
run_method(b'bf-cfb')
def test_rc4():
check_env()
run_method(b'rc4')
if __name__ == '__main__':
test_aes_128_cfb()

8
shadowsocks/encrypt_test.py

@ -7,10 +7,10 @@ import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../')) sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../'))
from crypto import rc4_md5 from shadowsocks.crypto import rc4_md5
from crypto import openssl from shadowsocks.crypto import openssl
from crypto import sodium from shadowsocks.crypto import sodium
from crypto import table from shadowsocks.crypto import table
def main(): def main():
print("\n""rc4_md5") print("\n""rc4_md5")

1
shadowsocks/local.py

@ -26,7 +26,6 @@ import signal
if __name__ == '__main__': if __name__ == '__main__':
import inspect import inspect
file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe()))) file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe())))
os.chdir(file_path)
sys.path.insert(0, os.path.join(file_path, '../')) sys.path.insert(0, os.path.join(file_path, '../'))
from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, asyncdns from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, asyncdns

5
shadowsocks/manager.py

@ -207,7 +207,9 @@ def test():
eventloop.TIMEOUT_PRECISION = 1 eventloop.TIMEOUT_PRECISION = 1
def run_server(): def run_server():
config = { config = shell.get_config(True)
config = config.copy()
a_config = {
'server': '127.0.0.1', 'server': '127.0.0.1',
'local_port': 1081, 'local_port': 1081,
'port_password': { 'port_password': {
@ -220,6 +222,7 @@ def test():
'fast_open': False, 'fast_open': False,
'verbose': 2 'verbose': 2
} }
config.update(a_config)
manager = Manager(config) manager = Manager(config)
enc.append(manager) enc.append(manager)
manager.run() manager.run()

1
shadowsocks/server.py

@ -26,7 +26,6 @@ import signal
if __name__ == '__main__': if __name__ == '__main__':
import inspect import inspect
file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe()))) file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe())))
os.chdir(file_path)
sys.path.insert(0, os.path.join(file_path, '../')) sys.path.insert(0, os.path.join(file_path, '../'))
from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, \ from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, \

0
tests/assert.sh

2
tests/test.py

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

15
tests/test_command.sh

@ -2,18 +2,13 @@
. tests/assert.sh . tests/assert.sh
PYTHON="coverage run -a -p" PYTHON="coverage run -p"
LOCAL="$PYTHON shadowsocks/local.py" LOCAL="$PYTHON shadowsocks/local.py"
SERVER="$PYTHON shadowsocks/server.py" SERVER="$PYTHON shadowsocks/server.py"
assert "$LOCAL --version 2>&1 | grep Shadowsocks | awk -F\" \" '{print \$1}'" "Shadowsocks" assert "$LOCAL --version 2>&1 | grep Shadowsocks | awk -F\" \" '{print \$1}'" "Shadowsocks"
assert "$SERVER --version 2>&1 | grep Shadowsocks | awk -F\" \" '{print \$1}'" "Shadowsocks" assert "$SERVER --version 2>&1 | grep Shadowsocks | awk -F\" \" '{print \$1}'" "Shadowsocks"
assert "$LOCAL 2>&1 | grep ERROR" "ERROR: config not specified"
assert "$LOCAL 2>&1 | grep usage | cut -d: -f1" "usage"
assert "$SERVER 2>&1 | grep ERROR" "ERROR: config not specified"
assert "$SERVER 2>&1 | grep usage | cut -d: -f1" "usage"
assert "$LOCAL 2>&1 -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: server set to listen on 127.0.0.1:8388, are you sure?" assert "$LOCAL 2>&1 -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: server set to listen on 127.0.0.1:8388, are you sure?"
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop $LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop
@ -30,14 +25,6 @@ $LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d sto
assert "$LOCAL 2>&1 -m rc4-md5 -k mypassword -s 0.0.0.0 -p 8388 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" " DON'T USE DEFAULT PASSWORD! Please change it in your config.json!" assert "$LOCAL 2>&1 -m rc4-md5 -k mypassword -s 0.0.0.0 -p 8388 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" " DON'T USE DEFAULT PASSWORD! Please change it in your config.json!"
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop $LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop
assert "$LOCAL 2>&1 -m rc4-md5 -p 8388 -k testrc4 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" ": server addr not specified"
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop
assert "$LOCAL 2>&1 -m rc4-md5 -p 8388 -s 0.0.0.0 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" " password not specified"
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop
assert "$SERVER 2>&1 -m rc4-md5 -p 8388 -s 0.0.0.0 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" " password or port_password not specified"
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop
assert "$SERVER 2>&1 --forbidden-ip 127.0.0.1/4a -m rc4-md5 -k 12345 -p 8388 -s 0.0.0.0 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" ": Not a valid CIDR notation: 127.0.0.1/4a" assert "$SERVER 2>&1 --forbidden-ip 127.0.0.1/4a -m rc4-md5 -k 12345 -p 8388 -s 0.0.0.0 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" ": Not a valid CIDR notation: 127.0.0.1/4a"
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop $LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop

2
tests/test_daemon.sh

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

2
tests/test_large_file.sh

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

83
tests/test_udp_src.py

@ -0,0 +1,83 @@
#!/usr/bin/python
import socket
import socks
SERVER_IP = '127.0.0.1'
SERVER_PORT = 1081
if __name__ == '__main__':
# Test 1: same source port IPv4
sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_out.set_proxy(socks.SOCKS5, SERVER_IP, SERVER_PORT)
sock_out.bind(('127.0.0.1', 9000))
sock_in1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_in2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_in1.bind(('127.0.0.1', 9001))
sock_in2.bind(('127.0.0.1', 9002))
sock_out.sendto(b'data', ('127.0.0.1', 9001))
result1 = sock_in1.recvfrom(8)
sock_out.sendto(b'data', ('127.0.0.1', 9002))
result2 = sock_in2.recvfrom(8)
sock_out.close()
sock_in1.close()
sock_in2.close()
# 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,
socket.SOL_UDP)
sock_out.set_proxy(socks.SOCKS5, SERVER_IP, SERVER_PORT)
sock_out.bind(('127.0.0.1', 9000))
sock_in1 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_in2 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_in1.bind(('::1', 9001))
sock_in2.bind(('::1', 9002))
sock_out.sendto(b'data', ('::1', 9001))
result1 = sock_in1.recvfrom(8)
sock_out.sendto(b'data', ('::1', 9002))
result2 = sock_in2.recvfrom(8)
sock_out.close()
sock_in1.close()
sock_in2.close()
# make sure they're from the same source port
assert result1 == result2
# Test 3: different source ports IPv6
sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_out.set_proxy(socks.SOCKS5, SERVER_IP, SERVER_PORT)
sock_out.bind(('127.0.0.1', 9003))
sock_in1 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM,
socket.SOL_UDP)
sock_in1.bind(('::1', 9001))
sock_out.sendto(b'data', ('::1', 9001))
result3 = sock_in1.recvfrom(8)
# make sure they're from different source ports
assert result1 != result3
sock_out.close()
sock_in1.close()

23
tests/test_udp_src.sh

@ -0,0 +1,23 @@
#!/bin/bash
PYTHON="coverage run -p"
mkdir -p tmp
$PYTHON shadowsocks/local.py -c tests/aes.json -v &
LOCAL=$!
$PYTHON shadowsocks/server.py -c tests/aes.json --forbidden-ip "" -v &
SERVER=$!
sleep 3
python tests/test_udp_src.py
r=$?
kill -s SIGINT $LOCAL
kill -s SIGINT $SERVER
sleep 2
exit $r
Loading…
Cancel
Save