commit
7f480248f8
18 changed files with 163 additions and 149 deletions
|
@ -13,7 +13,7 @@ before_install:
|
|||
- 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 service nginx restart
|
||||
- pip install pep8 pyflakes nose coverage
|
||||
- pip install pep8 pyflakes nose coverage PySocks cymysql
|
||||
- sudo tests/socksify/install.sh
|
||||
- sudo tests/libsodium/install.sh
|
||||
- sudo tests/setup_tc.sh
|
||||
|
|
|
@ -87,7 +87,7 @@ Bugs and Issues
|
|||
|
||||
|
||||
[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
|
||||
[Coverage Status]: https://jenkins.shadowvpn.org/result/shadowsocks
|
||||
[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
|
||||
[PyPI]: https://pypi.python.org/pypi/shadowsocks
|
||||
[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
|
||||
[Wiki]: https://github.com/shadowsocks/shadowsocks/wiki
|
||||
[Windows]: https://github.com/shadowsocks/shadowsocks-csharp
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#!/usr/bin/python
|
39
setup.py
Normal file
39
setup.py
Normal file
|
@ -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,
|
||||
)
|
|
@ -28,7 +28,6 @@ if __name__ == '__main__':
|
|||
import sys
|
||||
import inspect
|
||||
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, '../'))
|
||||
|
||||
from shadowsocks import common, lru_cache, eventloop, shell
|
||||
|
|
|
@ -294,12 +294,12 @@ def test_inet_conv():
|
|||
|
||||
def test_parse_header():
|
||||
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') == \
|
||||
(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'
|
||||
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():
|
||||
|
|
|
@ -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()
|
|
@ -7,10 +7,10 @@ import os
|
|||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../'))
|
||||
|
||||
|
||||
from crypto import rc4_md5
|
||||
from crypto import openssl
|
||||
from crypto import sodium
|
||||
from crypto import table
|
||||
from shadowsocks.crypto import rc4_md5
|
||||
from shadowsocks.crypto import openssl
|
||||
from shadowsocks.crypto import sodium
|
||||
from shadowsocks.crypto import table
|
||||
|
||||
def main():
|
||||
print("\n""rc4_md5")
|
||||
|
|
|
@ -26,7 +26,6 @@ import signal
|
|||
if __name__ == '__main__':
|
||||
import inspect
|
||||
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, '../'))
|
||||
|
||||
from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, asyncdns
|
||||
|
|
|
@ -207,7 +207,9 @@ def test():
|
|||
eventloop.TIMEOUT_PRECISION = 1
|
||||
|
||||
def run_server():
|
||||
config = {
|
||||
config = shell.get_config(True)
|
||||
config = config.copy()
|
||||
a_config = {
|
||||
'server': '127.0.0.1',
|
||||
'local_port': 1081,
|
||||
'port_password': {
|
||||
|
@ -220,6 +222,7 @@ def test():
|
|||
'fast_open': False,
|
||||
'verbose': 2
|
||||
}
|
||||
config.update(a_config)
|
||||
manager = Manager(config)
|
||||
enc.append(manager)
|
||||
manager.run()
|
||||
|
|
|
@ -26,7 +26,6 @@ import signal
|
|||
if __name__ == '__main__':
|
||||
import inspect
|
||||
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, '../'))
|
||||
|
||||
from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, \
|
||||
|
|
0
tests/assert.sh
Normal file → Executable file
0
tests/assert.sh
Normal file → Executable 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', '-p']
|
||||
|
||||
client_args = python + ['shadowsocks/local.py', '-v']
|
||||
server_args = python + ['shadowsocks/server.py', '-v']
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
|
||||
. tests/assert.sh
|
||||
|
||||
PYTHON="coverage run -a -p"
|
||||
PYTHON="coverage run -p"
|
||||
LOCAL="$PYTHON shadowsocks/local.py"
|
||||
SERVER="$PYTHON shadowsocks/server.py"
|
||||
|
||||
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 "$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?"
|
||||
$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!"
|
||||
$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"
|
||||
$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop
|
||||
|
|
|
@ -18,7 +18,7 @@ function run_test {
|
|||
for module in local server
|
||||
do
|
||||
|
||||
command="coverage run -p -a shadowsocks/$module.py"
|
||||
command="coverage run -p shadowsocks/$module.py"
|
||||
|
||||
mkdir -p tmp
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
PYTHON="coverage run -p -a"
|
||||
PYTHON="coverage run -p"
|
||||
URL=http://127.0.0.1/file
|
||||
|
||||
mkdir -p tmp
|
||||
|
|
83
tests/test_udp_src.py
Normal file
83
tests/test_udp_src.py
Normal file
|
@ -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
Executable file
23
tests/test_udp_src.sh
Executable file
|
@ -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…
Add table
Add a link
Reference in a new issue