42 Commits
Author SHA1 Message Date
clowwindy b8f1825776 update CHANGES 2015-01-03 15:53:35 +08:00
clowwindy dde25f89e1 Update README.md 2015-01-03 14:00:33 +08:00
clowwindy 98f73e44d0 bump 2015-01-03 13:56:19 +08:00
clowwindy e0189ab1de update readme 2015-01-03 13:50:08 +08:00
clowwindy e68b3e430b add autoban 2015-01-03 13:30:16 +08:00
clowwindy bac675d7f6 2015 2015-01-03 13:24:40 +08:00
clowwindy 291adf8b85 log client address 2015-01-03 12:48:03 +08:00
clowwindy 1423fe1921 support color 2014-12-28 15:24:38 +08:00
clowwindy 5a5c8b9c7e fix coverage server 2014-12-28 15:24:38 +08:00
clowwindy 70559a1030 fix pep8 2014-12-28 15:24:38 +08:00
clowwindy 45ee594d58 coverage server now supports more projects 2014-12-28 15:24:38 +08:00
clowwindy 707b5c1def Merge pull request #237 from v3aqb/patch-1
Update ctypes_libsodium.py
2014-12-28 14:02:59 +08:00
v3aqb d91f7d85d4 Update ctypes_libsodium.py 2014-12-28 08:30:29 +08:00
clowwindy 5a5158b33f update url 2014-12-27 23:36:09 +08:00
clowwindy 7f19c31640 update project url 2014-12-27 23:29:48 +08:00
clowwindy 937693519a update url in readme 2014-12-27 23:29:07 +08:00
clowwindy 9e6e884b12 bump 2014-12-26 20:58:22 +08:00
clowwindy e8501da271 fix vim 2014-12-25 16:23:43 +08:00
clowwindy 99c8bbafe7 fix fastopen and add a new test 2014-12-25 16:20:15 +08:00
clowwindy 30f4f78557 fix travis 2014-12-24 18:23:35 +08:00
clowwindy dd140814a8 suppress some warnings 2014-12-24 18:15:52 +08:00
clowwindy d228ffbe84 add command line test 2014-12-24 18:10:12 +08:00
clowwindy ab975d1753 fix tests 2014-12-24 18:08:16 +08:00
clowwindy c6bc912c11 add command line tests 2014-12-24 18:02:14 +08:00
clowwindy b785d95f66 fix tests 2014-12-24 17:14:01 +08:00
clowwindy 1d0c8b1800 add coverage 2014-12-24 16:47:14 +08:00
clowwindy 9cfffa360e sudo tc setup 2014-12-23 15:32:29 +08:00
clowwindy cd07001471 use SIGINT instead in large file test 2014-12-23 14:05:20 +08:00
clowwindy 2cc7ee5053 alter tc rule 2014-12-23 13:57:31 +08:00
clowwindy 9b3944c954 fix large file test 2014-12-23 13:18:30 +08:00
clowwindy f1b084be06 add large file test 2014-12-23 13:09:51 +08:00
clowwindy 5ea8403e56 fix daemon and add fastopen tests 2014-12-22 22:42:39 +08:00
clowwindy 072afd68f2 use local tmp dir 2014-12-22 17:39:52 +08:00
clowwindy be1d1d5032 add SIGINT in workers 2014-12-22 17:29:58 +08:00
clowwindy 536b7d1ee6 use SIGINT instead in tests
Conflicts:
	tests/test.py
2014-12-22 17:25:39 +08:00
clowwindy c7b5a5a011 fix ci 2014-12-22 16:45:46 +08:00
clowwindy be2ab378ff add jenkins 2014-12-22 16:33:23 +08:00
clowwindy 2b4c3619d6 reorder setsid and kill 2014-12-21 14:52:00 +08:00
clowwindy dae2624b30 add setsid 2014-12-21 14:49:51 +08:00
clowwindy fb789d8e9f update readme 2014-12-21 14:09:07 +08:00
clowwindy 2733e6a4ba update readme 2014-12-21 14:08:11 +08:00
clowwindy 35c3b0b41c refine documentation 2014-12-21 14:06:28 +08:00
23 changed files with 552 additions and 165 deletions
+1
View File
@@ -17,6 +17,7 @@ develop-eggs
pip-log.txt pip-log.txt
# Unit test / coverage reports # Unit test / coverage reports
htmlcov
.coverage .coverage
.tox .tox
Executable
+71
View File
@@ -0,0 +1,71 @@
#!/bin/bash
result=0
function run_test {
printf '\e[0;36m'
echo "running test: $command $@"
printf '\e[0m'
$command "$@"
status=$?
if [ $status -ne 0 ]; then
printf '\e[0;31m'
echo "test failed: $command $@"
printf '\e[0m'
echo
result=1
else
printf '\e[0;32m'
echo OK
printf '\e[0m'
echo
fi
return 0
}
coverage erase
mkdir tmp
run_test pep8 .
run_test pyflakes .
run_test coverage run tests/nose_plugin.py -v
run_test python setup.py sdist
run_test tests/test_daemon.sh
run_test python tests/test.py --with-coverage -c tests/aes.json
run_test python tests/test.py --with-coverage -c tests/aes-ctr.json
run_test python tests/test.py --with-coverage -c tests/aes-cfb1.json
run_test python tests/test.py --with-coverage -c tests/aes-cfb8.json
run_test python tests/test.py --with-coverage -c tests/rc4-md5.json
run_test python tests/test.py --with-coverage -c tests/salsa20.json
run_test python tests/test.py --with-coverage -c tests/chacha20.json
run_test python tests/test.py --with-coverage -c tests/salsa20-ctr.json
run_test python tests/test.py --with-coverage -c tests/table.json
run_test python tests/test.py --with-coverage -c tests/server-multi-ports.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 -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"
if [ -f /proc/sys/net/ipv4/tcp_fastopen ] ; then
if [ 3 -eq `cat /proc/sys/net/ipv4/tcp_fastopen` ] ; then
# we have to run it twice:
# the first time there's no syn cookie
# the second time there is syn cookie
run_test python tests/test.py --with-coverage -c tests/fastopen.json
run_test python tests/test.py --with-coverage -c tests/fastopen.json
fi
fi
run_test tests/test_large_file.sh
run_test tests/test_command.sh
coverage combine && coverage report --include=shadowsocks/*
rm -rf htmlcov
rm -rf tmp
coverage html --include=shadowsocks/*
coverage report --include=shadowsocks/* | tail -n1 | rev | cut -d' ' -f 1 | rev > /tmp/shadowsocks-coverage
exit $result
+5 -22
View File
@@ -9,29 +9,12 @@ cache:
- dante-1.4.0 - dante-1.4.0
before_install: before_install:
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq build-essential libssl-dev swig python-m2crypto python-numpy dnsutils - sudo apt-get install -qq build-essential libssl-dev swig python-m2crypto python-numpy dnsutils iproute nginx bc
- sudo dd if=/dev/urandom of=/usr/share/nginx/www/file bs=1M count=10
- sudo service nginx restart
- pip install m2crypto salsa20 pep8 pyflakes nose coverage - pip install m2crypto salsa20 pep8 pyflakes nose coverage
- 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
script: script:
- pep8 . - ./.jenkins.sh
- pyflakes .
- coverage run tests/nose_plugin.py -v
- python setup.py sdist
- tests/test_daemon.sh
- python tests/test.py --with-coverage -c tests/aes.json
- python tests/test.py --with-coverage -c tests/aes-ctr.json
- python tests/test.py --with-coverage -c tests/aes-cfb1.json
- python tests/test.py --with-coverage -c tests/aes-cfb8.json
- python tests/test.py --with-coverage -c tests/rc4-md5.json
- python tests/test.py --with-coverage -c tests/salsa20.json
- python tests/test.py --with-coverage -c tests/chacha20.json
- python tests/test.py --with-coverage -c tests/salsa20-ctr.json
- python tests/test.py --with-coverage -c tests/table.json
- python tests/test.py --with-coverage -c tests/server-multi-ports.json
- python tests/test.py --with-coverage -s tests/server-multi-passwd.json -c tests/server-multi-passwd-client-side.json
- python tests/test.py --with-coverage -c tests/workers.json
- python tests/test.py --with-coverage -s tests/ipv6.json -c tests/ipv6-client-side.json
- python tests/test.py --with-coverage -b "-m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388" -a "-m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -l 1081"
- python tests/test.py --with-coverage -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081"
- coverage combine && coverage report --include=shadowsocks/*
+7
View File
@@ -1,3 +1,10 @@
2.6.2 2015-01-03
- Log client IP
2.6.1 2014-12-26
- Fix a problem with TCP Fast Open on local side
- Fix sometimes daemon_start returns wrong exit status
2.6 2014-12-21 2.6 2014-12-21
- Add daemon support - Add daemon support
+1 -1
View File
@@ -1,6 +1,6 @@
Shadowsocks Shadowsocks
Copyright (c) 2014 clowwindy Copyright (c) 2012-2015 clowwindy
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+33 -40
View File
@@ -1,7 +1,9 @@
shadowsocks shadowsocks
=========== ===========
[![PyPI version]][PyPI] [![Build Status]][Travis CI] [![PyPI version]][PyPI]
[![Build Status]][Travis CI]
[![Coverage Status]][Coverage]
A fast tunnel proxy that helps you bypass firewalls. A fast tunnel proxy that helps you bypass firewalls.
@@ -56,8 +58,7 @@ Example:
"password":"mypassword", "password":"mypassword",
"timeout":300, "timeout":300,
"method":"aes-256-cfb", "method":"aes-256-cfb",
"fast_open": false, "fast_open": false
"workers": 1
} }
Explanation of the fields: Explanation of the fields:
@@ -74,43 +75,36 @@ Explanation of the fields:
| fast_open | use [TCP_FASTOPEN], true / false | | fast_open | use [TCP_FASTOPEN], true / false |
| workers | number of workers, available on Unix/Linux | | workers | number of workers, available on Unix/Linux |
Run `ssserver -c /etc/shadowsocks.json` on your server. To run it in the On your server:
background, use [Supervisor].
On your client machine, use the same configuration as your server, and To run in the foreground:
start your client.
If you use Chrome, it's recommended to use [SwitchySharp]. Change the proxy ssserver -c /etc/shadowsocks.json
settings to
protocol: socks5 To run in the background:
hostname: 127.0.0.1
port: your local_port
If you can't install [SwitchySharp], you can launch Chrome with the following ssserver -c /etc/shadowsocks.json -d start
arguments to force Chrome to use the proxy: ssserver -c /etc/shadowsocks.json -d stop
Chrome.exe --proxy-server="socks5://127.0.0.1:1080" --host-resolver-rules="MAP * 0.0.0.0 , EXCLUDE localhost" On your client machine, use the same configuration as your server. Check the
README of your client for more information.
If you can't even download Chrome, find a friend to download a Command Line Options
[Chrome Standalone] installer for you. --------------------
Command line args Check the options via `-h`.You can use args to override settings from
------------------ `config.json`.
You can use args to override settings from `config.json`.
sslocal -s server_name -p server_port -l local_port -k password -m bf-cfb sslocal -s server_name -p server_port -l local_port -k password -m bf-cfb
ssserver -p server_port -k password -m bf-cfb --workers 2 ssserver -p server_port -k password -m bf-cfb --workers 2
ssserver -c /etc/shadowsocks/config.json ssserver -c /etc/shadowsocks/config.json -d start --pid-file=/tmp/shadowsocks.pid
ssserver -c /etc/shadowsocks/config.json -d stop --pid-file=/tmp/shadowsocks.pid
List all available args with `-h`. Documentation
-------------
Wiki
----
You can find all the documentation in the wiki: You can find all the documentation in the wiki:
https://github.com/clowwindy/shadowsocks/wiki https://github.com/shadowsocks/shadowsocks/wiki
License License
------- -------
@@ -124,24 +118,23 @@ Bugs and Issues
* [Mailing list] * [Mailing list]
[Android]: https://github.com/clowwindy/shadowsocks/wiki/Ports-and-Clients#android [Android]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#android
[Build Status]: https://img.shields.io/travis/clowwindy/shadowsocks/master.svg?style=flat [Build Status]: https://img.shields.io/travis/shadowsocks/shadowsocks/master.svg?style=flat
[Chinese Readme]: https://github.com/clowwindy/shadowsocks/wiki/Shadowsocks-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E [Chinese Readme]: https://github.com/shadowsocks/shadowsocks/wiki/Shadowsocks-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
[Chrome Standalone]: https://support.google.com/installer/answer/126299 [Coverage Status]: http://192.81.132.184/result/shadowsocks
[Coverage]: http://192.81.132.184/job/Shadowsocks/ws/htmlcov/index.html
[Debian sid]: https://packages.debian.org/unstable/python/shadowsocks [Debian sid]: https://packages.debian.org/unstable/python/shadowsocks
[the package]: https://pypi.python.org/pypi/shadowsocks [the package]: https://pypi.python.org/pypi/shadowsocks
[Encryption]: https://github.com/clowwindy/shadowsocks/wiki/Encryption [Encryption]: https://github.com/shadowsocks/shadowsocks/wiki/Encryption
[iOS]: https://github.com/shadowsocks/shadowsocks-iOS/wiki/Help [iOS]: https://github.com/shadowsocks/shadowsocks-iOS/wiki/Help
[Issue Tracker]: https://github.com/clowwindy/shadowsocks/issues?state=open [Issue Tracker]: https://github.com/shadowsocks/shadowsocks/issues?state=open
[Mailing list]: http://groups.google.com/group/shadowsocks [Mailing list]: http://groups.google.com/group/shadowsocks
[OpenSSL for Windows]: http://slproweb.com/products/Win32OpenSSL.html [OpenSSL for Windows]: http://slproweb.com/products/Win32OpenSSL.html
[OpenWRT]: https://github.com/clowwindy/shadowsocks/wiki/Ports-and-Clients#openwrt [OpenWRT]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#openwrt
[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
[Supervisor]: https://github.com/clowwindy/shadowsocks/wiki/Configure-Shadowsocks-with-Supervisor [TCP_FASTOPEN]: https://github.com/shadowsocks/shadowsocks/wiki/TCP-Fast-Open
[TCP_FASTOPEN]: https://github.com/clowwindy/shadowsocks/wiki/TCP-Fast-Open [Travis CI]: https://travis-ci.org/shadowsocks/shadowsocks
[Travis CI]: https://travis-ci.org/clowwindy/shadowsocks [Troubleshooting]: https://github.com/shadowsocks/shadowsocks/wiki/Troubleshooting
[Troubleshooting]: https://github.com/clowwindy/shadowsocks/wiki/Troubleshooting [Windows]: https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#windows
[SwitchySharp]: https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm
[Windows]: https://github.com/clowwindy/shadowsocks/wiki/Ports-and-Clients#windows
+54 -64
View File
@@ -1,11 +1,11 @@
shadowsocks shadowsocks
=========== ===========
|PyPI version| |Build Status| |PyPI version| |Build Status| |Coverage Status|
A fast tunnel proxy that helps you bypass firewalls. A fast tunnel proxy that helps you bypass firewalls.
`中文说明 <https://github.com/clowwindy/shadowsocks/wiki/Shadowsocks-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E>`__ `中文说明 <https://github.com/shadowsocks/shadowsocks/wiki/Shadowsocks-%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E>`__
Install Install
------- -------
@@ -16,12 +16,12 @@ server.
Client Client
~~~~~~ ~~~~~~
- `Windows <https://github.com/clowwindy/shadowsocks/wiki/Ports-and-Clients#windows>`__ - `Windows <https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#windows>`__
/ `OS / `OS
X <https://github.com/shadowsocks/shadowsocks-iOS/wiki/Shadowsocks-for-OSX-Help>`__ X <https://github.com/shadowsocks/shadowsocks-iOS/wiki/Shadowsocks-for-OSX-Help>`__
- `Android <https://github.com/clowwindy/shadowsocks/wiki/Ports-and-Clients#android>`__ - `Android <https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#android>`__
/ `iOS <https://github.com/shadowsocks/shadowsocks-iOS/wiki/Help>`__ / `iOS <https://github.com/shadowsocks/shadowsocks-iOS/wiki/Help>`__
- `OpenWRT <https://github.com/clowwindy/shadowsocks/wiki/Ports-and-Clients#openwrt>`__ - `OpenWRT <https://github.com/shadowsocks/shadowsocks/wiki/Ports-and-Clients#openwrt>`__
Server Server
~~~~~~ ~~~~~~
@@ -50,9 +50,10 @@ CentOS:
Windows: Windows:
^^^^^^^^ ^^^^^^^^
Download OpenSSL for Windows and install. Then install shadowsocks via Download `OpenSSL for
easy\_install and pip as Linux. If you don't know how to use them, you Windows <http://slproweb.com/products/Win32OpenSSL.html>`__ and install.
can directly download `the Then install shadowsocks via easy\_install and pip as Linux. If you
don't know how to use them, you can directly download `the
package <https://pypi.python.org/pypi/shadowsocks>`__, and use package <https://pypi.python.org/pypi/shadowsocks>`__, and use
``python shadowsocks/server.py`` instead of ``ssserver`` command below. ``python shadowsocks/server.py`` instead of ``ssserver`` command below.
@@ -71,82 +72,69 @@ On your server create a config file ``/etc/shadowsocks.json``. Example:
"password":"mypassword", "password":"mypassword",
"timeout":300, "timeout":300,
"method":"aes-256-cfb", "method":"aes-256-cfb",
"fast_open": false, "fast_open": false
"workers": 1
} }
Explanation of the fields: Explanation of the fields:
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| Name | Explanation | | Name | Explanation |
+==================+=========================================================================================================+ +==================+===========================================================================================================+
| server | the address your server listens | | server | the address your server listens |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| server\_port | server port | | server\_port | server port |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| local\_address | the address your local listens | | local\_address | the address your local listens |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| local\_port | local port | | local\_port | local port |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| password | password used for encryption | | password | password used for encryption |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| timeout | in seconds | | timeout | in seconds |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| method | default: "aes-256-cfb", see `Encryption <https://github.com/clowwindy/shadowsocks/wiki/Encryption>`__ | | method | default: "aes-256-cfb", see `Encryption <https://github.com/shadowsocks/shadowsocks/wiki/Encryption>`__ |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| fast\_open | use `TCP\_FASTOPEN <https://github.com/clowwindy/shadowsocks/wiki/TCP-Fast-Open>`__, true / false | | fast\_open | use `TCP\_FASTOPEN <https://github.com/shadowsocks/shadowsocks/wiki/TCP-Fast-Open>`__, true / false |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
| workers | number of workers, available on Unix/Linux | | workers | number of workers, available on Unix/Linux |
+------------------+---------------------------------------------------------------------------------------------------------+ +------------------+-----------------------------------------------------------------------------------------------------------+
Run ``ssserver -c /etc/shadowsocks.json`` on your server. To run it in On your server:
the background, use
`Supervisor <https://github.com/clowwindy/shadowsocks/wiki/Configure-Shadowsocks-with-Supervisor>`__.
On your client machine, use the same configuration as your server, and To run in the foreground:
start your client.
If you use Chrome, it's recommended to use
`SwitchySharp <https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm>`__.
Change the proxy settings to
:: ::
protocol: socks5 ssserver -c /etc/shadowsocks.json
hostname: 127.0.0.1
port: your local_port
If you can't install To run in the background:
`SwitchySharp <https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm>`__,
you can launch Chrome with the following arguments to force Chrome to
use the proxy:
:: ::
Chrome.exe --proxy-server="socks5://127.0.0.1:1080" --host-resolver-rules="MAP * 0.0.0.0 , EXCLUDE localhost" ssserver -c /etc/shadowsocks.json -d start
ssserver -c /etc/shadowsocks.json -d stop
If you can't even download Chrome, find a friend to download a `Chrome On your client machine, use the same configuration as your server. Check
Standalone <https://support.google.com/installer/answer/126299>`__ the README of your client for more information.
installer for you.
Command line args Command Line Options
----------------- --------------------
You can use args to override settings from ``config.json``. Check the options via ``-h``.You can use args to override settings from
``config.json``.
:: ::
sslocal -s server_name -p server_port -l local_port -k password -m bf-cfb sslocal -s server_name -p server_port -l local_port -k password -m bf-cfb
ssserver -p server_port -k password -m bf-cfb --workers 2 ssserver -p server_port -k password -m bf-cfb --workers 2
ssserver -c /etc/shadowsocks/config.json ssserver -c /etc/shadowsocks/config.json -d start --pid-file=/tmp/shadowsocks.pid
ssserver -c /etc/shadowsocks/config.json -d stop --pid-file=/tmp/shadowsocks.pid
List all available args with ``-h``. Documentation
-------------
Wiki
----
You can find all the documentation in the wiki: You can find all the documentation in the wiki:
https://github.com/clowwindy/shadowsocks/wiki https://github.com/shadowsocks/shadowsocks/wiki
License License
------- -------
@@ -156,12 +144,14 @@ MIT
Bugs and Issues Bugs and Issues
--------------- ---------------
- `Troubleshooting <https://github.com/clowwindy/shadowsocks/wiki/Troubleshooting>`__ - `Troubleshooting <https://github.com/shadowsocks/shadowsocks/wiki/Troubleshooting>`__
- `Issue - `Issue
Tracker <https://github.com/clowwindy/shadowsocks/issues?state=open>`__ Tracker <https://github.com/shadowsocks/shadowsocks/issues?state=open>`__
- `Mailing list <http://groups.google.com/group/shadowsocks>`__ - `Mailing list <http://groups.google.com/group/shadowsocks>`__
.. |PyPI version| image:: https://img.shields.io/pypi/v/shadowsocks.svg?style=flat .. |PyPI version| image:: https://img.shields.io/pypi/v/shadowsocks.svg?style=flat
:target: https://pypi.python.org/pypi/shadowsocks :target: https://pypi.python.org/pypi/shadowsocks
.. |Build Status| image:: https://img.shields.io/travis/clowwindy/shadowsocks/master.svg?style=flat .. |Build Status| image:: https://img.shields.io/travis/shadowsocks/shadowsocks/master.svg?style=flat
:target: https://travis-ci.org/clowwindy/shadowsocks :target: https://travis-ci.org/shadowsocks/shadowsocks
.. |Coverage Status| image:: http://192.81.132.184/result/shadowsocks
:target: http://192.81.132.184/job/Shadowsocks/ws/htmlcov/index.html
+2 -2
View File
@@ -7,12 +7,12 @@ with codecs.open('README.rst', encoding='utf-8') as f:
setup( setup(
name="shadowsocks", name="shadowsocks",
version="2.6", version="2.6.2",
license='MIT', license='MIT',
description="A fast tunnel proxy that help you get through firewalls", description="A fast tunnel proxy that help you get through firewalls",
author='clowwindy', author='clowwindy',
author_email='clowwindy42@gmail.com', author_email='clowwindy42@gmail.com',
url='https://github.com/clowwindy/shadowsocks', url='https://github.com/shadowsocks/shadowsocks',
packages=['shadowsocks', 'shadowsocks.crypto'], packages=['shadowsocks', 'shadowsocks.crypto'],
package_data={ package_data={
'shadowsocks': ['README.rst', 'LICENSE'] 'shadowsocks': ['README.rst', 'LICENSE']
+1 -1
View File
@@ -42,7 +42,7 @@ def load_libsodium():
global loaded, libsodium, buf global loaded, libsodium, buf
from ctypes.util import find_library from ctypes.util import find_library
for p in ('sodium',): for p in ('sodium', 'libsodium'):
libsodium_path = find_library(p) libsodium_path = find_library(p)
if libsodium_path: if libsodium_path:
break break
+11 -7
View File
@@ -37,7 +37,7 @@ from shadowsocks import common
def daemon_exec(config): def daemon_exec(config):
if 'daemon' in config: if 'daemon' in config:
if os.name != 'posix': if os.name != 'posix':
raise Exception('daemon mode is only supported in unix') raise Exception('daemon mode is only supported on Unix')
command = config['daemon'] command = config['daemon']
if not command: if not command:
command = 'start' command = 'start'
@@ -100,19 +100,21 @@ def freopen(f, mode, stream):
def daemon_start(pid_file, log_file): def daemon_start(pid_file, log_file):
# fork only once because we are sure parent will exit
pid = os.fork()
assert pid != -1
def handle_exit(signum, _): def handle_exit(signum, _):
if signum == signal.SIGTERM: if signum == signal.SIGTERM:
sys.exit(0) sys.exit(0)
sys.exit(1) sys.exit(1)
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
# fork only once because we are sure parent will exit
pid = os.fork()
assert pid != -1
if pid > 0: if pid > 0:
# parent waits for its child # parent waits for its child
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
time.sleep(5) time.sleep(5)
sys.exit(0) sys.exit(0)
@@ -123,6 +125,9 @@ def daemon_start(pid_file, log_file):
os.kill(ppid, signal.SIGINT) os.kill(ppid, signal.SIGINT)
sys.exit(1) sys.exit(1)
os.setsid()
signal.signal(signal.SIG_IGN, signal.SIGHUP)
print('started') print('started')
os.kill(ppid, signal.SIGTERM) os.kill(ppid, signal.SIGTERM)
@@ -132,7 +137,6 @@ def daemon_start(pid_file, log_file):
freopen(log_file, 'a', sys.stderr) freopen(log_file, 'a', sys.stderr)
except IOError as e: except IOError as e:
logging.error(e) logging.error(e)
os.kill(ppid, signal.SIGINT)
sys.exit(1) sys.exit(1)
+5
View File
@@ -68,6 +68,11 @@ def main():
tcp_server.close(next_tick=True) tcp_server.close(next_tick=True)
udp_server.close(next_tick=True) udp_server.close(next_tick=True)
signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler)
def int_handler(signum, _):
sys.exit(1)
signal.signal(signal.SIGINT, int_handler)
loop.run() loop.run()
except (KeyboardInterrupt, IOError, OSError) as e: except (KeyboardInterrupt, IOError, OSError) as e:
logging.error(e) logging.error(e)
+6
View File
@@ -77,6 +77,11 @@ def main():
tcp_servers + udp_servers)) tcp_servers + udp_servers))
signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM),
child_handler) child_handler)
def int_handler(signum, _):
sys.exit(1)
signal.signal(signal.SIGINT, int_handler)
try: try:
loop = eventloop.EventLoop() loop = eventloop.EventLoop()
dns_resolver.add_to_loop(loop) dns_resolver.add_to_loop(loop)
@@ -113,6 +118,7 @@ def main():
sys.exit() sys.exit()
signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGQUIT, handler)
signal.signal(signal.SIGINT, handler)
# master # master
for a_tcp_server in tcp_servers: for a_tcp_server in tcp_servers:
+16 -11
View File
@@ -1,7 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2014 clowwindy # Copyright (c) 2015 clowwindy
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
@@ -121,6 +121,7 @@ class TCPRelayHandler(object):
self._data_to_write_to_remote = [] self._data_to_write_to_remote = []
self._upstream_status = WAIT_STATUS_READING self._upstream_status = WAIT_STATUS_READING
self._downstream_status = WAIT_STATUS_INIT self._downstream_status = WAIT_STATUS_INIT
self._client_address = local_sock.getpeername()[:2]
self._remote_address = None self._remote_address = None
if is_local: if is_local:
self._chosen_server = self._get_a_server() self._chosen_server = self._get_a_server()
@@ -241,19 +242,18 @@ class TCPRelayHandler(object):
self._create_remote_socket(self._chosen_server[0], self._create_remote_socket(self._chosen_server[0],
self._chosen_server[1]) self._chosen_server[1])
self._loop.add(remote_sock, eventloop.POLL_ERR) self._loop.add(remote_sock, eventloop.POLL_ERR)
data = b''.join(self._data_to_write_to_local) data = b''.join(self._data_to_write_to_remote)
l = len(data) l = len(data)
s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server)
if s < l: if s < l:
data = data[s:] data = data[s:]
self._data_to_write_to_local = [data] self._data_to_write_to_remote = [data]
self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
else: else:
self._data_to_write_to_local = [] self._data_to_write_to_remote = []
self._update_stream(STREAM_UP, WAIT_STATUS_READING) self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
self._stage = STAGE_STREAM
except (OSError, IOError) as e: except (OSError, IOError) as e:
if eventloop.errno_from_exception(e) == errno.EINPROGRESS: if eventloop.errno_from_exception(e) == errno.EINPROGRESS:
# in this case data is not sent at all
self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING)
elif eventloop.errno_from_exception(e) == errno.ENOTCONN: elif eventloop.errno_from_exception(e) == errno.ENOTCONN:
logging.error('fast open not supported on this OS') logging.error('fast open not supported on this OS')
@@ -295,8 +295,9 @@ class TCPRelayHandler(object):
if header_result is None: if header_result is None:
raise Exception('can not parse header') raise Exception('can not parse header')
addrtype, remote_addr, remote_port, header_length = header_result addrtype, remote_addr, remote_port, header_length = header_result
logging.info('connecting %s:%d' % (common.to_str(remote_addr), logging.info('connecting %s:%d from %s:%d' %
remote_port)) (common.to_str(remote_addr), remote_port,
self._client_address[0], self._client_address[1]))
self._remote_address = (remote_addr, remote_port) self._remote_address = (remote_addr, remote_port)
# pause reading # pause reading
self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
@@ -318,7 +319,7 @@ class TCPRelayHandler(object):
self._dns_resolver.resolve(remote_addr, self._dns_resolver.resolve(remote_addr,
self._handle_dns_resolved) self._handle_dns_resolved)
except Exception as e: except Exception as e:
logging.error(e) self._log_error(e)
if self._config['verbose']: if self._config['verbose']:
traceback.print_exc() traceback.print_exc()
# TODO use logging when debug completed # TODO use logging when debug completed
@@ -339,7 +340,7 @@ class TCPRelayHandler(object):
def _handle_dns_resolved(self, result, error): def _handle_dns_resolved(self, result, error):
if error: if error:
logging.error(error) self._log_error(error)
self.destroy() self.destroy()
return return
if result: if result:
@@ -508,6 +509,10 @@ class TCPRelayHandler(object):
else: else:
logging.warn('unknown socket') logging.warn('unknown socket')
def _log_error(self, e):
logging.error('%s when handling connection from %s:%d' %
(e, self._client_address[0], self._client_address[1]))
def destroy(self): def destroy(self):
# destroy the handler and release any resources # destroy the handler and release any resources
# promises: # promises:
+2 -2
View File
@@ -29,7 +29,7 @@ import json
import sys import sys
import getopt import getopt
import logging import logging
from shadowsocks.common import to_bytes from shadowsocks.common import to_bytes, to_str
VERBOSE_LEVEL = 5 VERBOSE_LEVEL = 5
@@ -73,7 +73,7 @@ def check_config(config):
logging.warn('warning: local set to listen on 0.0.0.0, it\'s not safe') logging.warn('warning: local set to listen on 0.0.0.0, it\'s not safe')
if config.get('server', '') in [b'127.0.0.1', b'localhost']: if config.get('server', '') in [b'127.0.0.1', b'localhost']:
logging.warn('warning: server set to listen on %s:%s, are you sure?' % logging.warn('warning: server set to listen on %s:%s, are you sure?' %
(config['server'], config['server_port'])) (to_str(config['server']), config['server_port']))
if (config.get('method', '') or '').lower() == b'table': if (config.get('method', '') or '').lower() == b'table':
logging.warn('warning: table is not safe; please use a safer cipher, ' logging.warn('warning: table is not safe; please use a safer cipher, '
'like AES-256-CFB') 'like AES-256-CFB')
+148
View File
@@ -0,0 +1,148 @@
#!/bin/bash
# assert.sh 1.0 - bash unit testing framework
# Copyright (C) 2009, 2010, 2011, 2012 Robert Lehmann
#
# http://github.com/lehmannro/assert.sh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
export DISCOVERONLY=${DISCOVERONLY:-}
export DEBUG=${DEBUG:-}
export STOP=${STOP:-}
export INVARIANT=${INVARIANT:-}
export CONTINUE=${CONTINUE:-}
args="$(getopt -n "$0" -l \
verbose,help,stop,discover,invariant,continue vhxdic $*)" \
|| exit -1
for arg in $args; do
case "$arg" in
-h)
echo "$0 [-vxidc]" \
"[--verbose] [--stop] [--invariant] [--discover] [--continue]"
echo "`sed 's/./ /g' <<< "$0"` [-h] [--help]"
exit 0;;
--help)
cat <<EOF
Usage: $0 [options]
Language-agnostic unit tests for subprocesses.
Options:
-v, --verbose generate output for every individual test case
-x, --stop stop running tests after the first failure
-i, --invariant do not measure timings to remain invariant between runs
-d, --discover collect test suites only, do not run any tests
-c, --continue do not modify exit code to test suite status
-h show brief usage information and exit
--help show this help message and exit
EOF
exit 0;;
-v|--verbose)
DEBUG=1;;
-x|--stop)
STOP=1;;
-i|--invariant)
INVARIANT=1;;
-d|--discover)
DISCOVERONLY=1;;
-c|--continue)
CONTINUE=1;;
esac
done
printf -v _indent "\n\t" # local format helper
_assert_reset() {
tests_ran=0
tests_failed=0
tests_errors=()
tests_starttime="$(date +%s.%N)" # seconds_since_epoch.nanoseconds
}
assert_end() {
# assert_end [suite ..]
tests_endtime="$(date +%s.%N)"
tests="$tests_ran ${*:+$* }tests"
[[ -n "$DISCOVERONLY" ]] && echo "collected $tests." && _assert_reset && return
[[ -n "$DEBUG" ]] && echo
[[ -z "$INVARIANT" ]] && report_time=" in $(bc \
<<< "${tests_endtime%.N} - ${tests_starttime%.N}" \
| sed -e 's/\.\([0-9]\{0,3\}\)[0-9]*/.\1/' -e 's/^\./0./')s" \
|| report_time=
if [[ "$tests_failed" -eq 0 ]]; then
echo "all $tests passed$report_time."
else
for error in "${tests_errors[@]}"; do echo "$error"; done
echo "$tests_failed of $tests failed$report_time."
fi
tests_failed_previous=$tests_failed
[[ $tests_failed -gt 0 ]] && tests_suite_status=1
_assert_reset
return $tests_failed_previous
}
assert() {
# assert <command> <expected stdout> [stdin]
(( tests_ran++ )) || :
[[ -n "$DISCOVERONLY" ]] && return || true
# printf required for formatting
printf -v expected "x${2:-}" # x required to overwrite older results
result="$(eval 2>/dev/null $1 <<< ${3:-})" || true
# Note: $expected is already decorated
if [[ "x$result" == "$expected" ]]; then
[[ -n "$DEBUG" ]] && echo -n . || true
return
fi
result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")"
[[ -z "$result" ]] && result="nothing" || result="\"$result\""
[[ -z "$2" ]] && expected="nothing" || expected="\"$2\""
_assert_fail "expected $expected${_indent}got $result" "$1" "$3"
}
assert_raises() {
# assert_raises <command> <expected code> [stdin]
(( tests_ran++ )) || :
[[ -n "$DISCOVERONLY" ]] && return || true
status=0
(eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$?
expected=${2:-0}
if [[ "$status" -eq "$expected" ]]; then
[[ -n "$DEBUG" ]] && echo -n . || true
return
fi
_assert_fail "program terminated with code $status instead of $expected" "$1" "$3"
}
_assert_fail() {
# _assert_fail <failure> <command> <stdin>
[[ -n "$DEBUG" ]] && echo -n X
report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1"
if [[ -n "$STOP" ]]; then
[[ -n "$DEBUG" ]] && echo
echo "$report"
exit 1
fi
tests_errors[$tests_failed]="$report"
(( tests_failed++ )) || :
}
_assert_reset
: ${tests_suite_status:=0} # remember if any of the tests failed so far
_assert_cleanup() {
local status=$?
# modify exit code if it's not already non-zero
[[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status
}
trap _assert_cleanup EXIT
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env python
if __name__ == '__main__':
import tornado.ioloop
import tornado.web
import urllib
class MainHandler(tornado.web.RequestHandler):
def get(self, project):
try:
with open('/tmp/%s-coverage' % project, 'rb') as f:
coverage = f.read().strip()
n = int(coverage.strip('%'))
if n > 80:
color = 'brightgreen'
else:
color = 'yellow'
self.redirect(('https://img.shields.io/badge/'
'coverage-%s-%s.svg'
'?style=flat') %
(urllib.quote(coverage), color))
except IOError:
raise tornado.web.HTTPError(404)
application = tornado.web.Application([
(r"/([a-zA-Z0-9\-_]+)", MainHandler),
])
if __name__ == "__main__":
application.listen(8888, address='127.0.0.1')
tornado.ioloop.IOLoop.instance().start()
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
DEV=lo
PORT=8388
DELAY=100ms
type tc 2> /dev/null && (
tc qdisc add dev $DEV root handle 1: htb
tc class add dev $DEV parent 1: classid 1:1 htb rate 2mbps
tc class add dev $DEV parent 1:1 classid 1:6 htb rate 2mbps ceil 1mbps prio 0
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 6 fw flowid 1:6
tc filter add dev $DEV parent 1:0 protocol ip u32 match ip dport $PORT 0xffff flowid 1:6
tc filter add dev $DEV parent 1:0 protocol ip u32 match ip sport $PORT 0xffff flowid 1:6
tc qdisc show dev lo
)
+1 -1
View File
@@ -138,7 +138,7 @@ try:
finally: finally:
for p in [p1, p2]: for p in [p1, p2]:
try: try:
os.kill(p.pid, signal.SIGQUIT) os.kill(p.pid, signal.SIGINT)
os.waitpid(p.pid, 0) os.waitpid(p.pid, 0)
except OSError: except OSError:
pass pass
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
. tests/assert.sh
PYTHON="coverage run -a -p"
LOCAL="$PYTHON shadowsocks/local.py"
SERVER="$PYTHON shadowsocks/server.py"
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
assert "$LOCAL 2>&1 -m rc4-md5 -k testrc4 -s 0.0.0.0 -p 8388 -t10 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: your timeout 10 seems too short"
$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 -k testrc4 -s 0.0.0.0 -p 8388 -t1000 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: your timeout 1000 seems too long"
$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 -k testrc4 -s 0.0.0.0 -p 8388 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: RC4 is not safe; please use a safer cipher, like AES-256-CFB"
$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 -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_end command
+15 -14
View File
@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
function test { function run_test {
expected=$1 expected=$1
shift shift
echo "running test: $command $@" echo "running test: $command $@"
@@ -20,23 +20,24 @@ do
command="coverage run -p -a shadowsocks/$module.py" command="coverage run -p -a shadowsocks/$module.py"
test 0 -c tests/aes.json -d stop --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log mkdir -p tmp
test 0 -c tests/aes.json -d start --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 0 -c tests/aes.json -d stop --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log
test 0 -c tests/aes.json -d start --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 1 -c tests/aes.json -d start --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 0 -c tests/aes.json -d stop --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log
test 0 -c tests/aes.json -d start --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 0 -c tests/aes.json -d restart --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 1 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 0 -c tests/aes.json -d stop --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 0 -c tests/aes.json -d restart --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 0 -c tests/aes.json -d stop --pid-file /tmp/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d restart --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 1 -c tests/aes.json -d start --pid-file /tmp/not_exist/shadowsocks.pid --log-file /tmp/shadowsocks.log run_test 0 -c tests/aes.json -d restart --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
test 1 -c tests/aes.json -d start --pid-file /tmp/shadowsocks.pid --log-file /tmp/not_exist/shadowsocks.log run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log
run_test 1 -c tests/aes.json -d start --pid-file tmp/not_exist/shadowsocks.pid --log-file tmp/shadowsocks.log
done done
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
PYTHON="coverage run -p -a"
URL=http://127.0.0.1/file
mkdir -p tmp
$PYTHON shadowsocks/local.py -c tests/aes.json &
LOCAL=$!
$PYTHON shadowsocks/server.py -c tests/aes.json &
SERVER=$!
sleep 3
time curl -o tmp/expected $URL
time curl -o tmp/result --socks5-hostname 127.0.0.1:1081 $URL
kill -s SIGINT $LOCAL
kill -s SIGINT $SERVER
sleep 2
diff tmp/expected tmp/result || exit 1
+9
View File
@@ -0,0 +1,9 @@
Useful Tools
===========
autoban.py
----------
Automatically ban IPs that try to brute force crack the server.
See https://github.com/shadowsocks/shadowsocks/wiki/Ban-Brute-Force-Crackers
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2015 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 os
import sys
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='See README')
parser.add_argument('-c', '--count', default=3, type=int,
help='with how many failure times it should be '
'considered as an attack')
config = parser.parse_args()
ips = {}
banned = set()
for line in sys.stdin:
if 'can not parse header when' in line:
ip = line.split()[-1].split(':')[0]
if ip not in ips:
ips[ip] = 1
print(ip)
else:
ips[ip] += 1
if ip not in banned and ips[ip] >= config.count:
banned.add(ip)
cmd = 'iptables -A INPUT -s %s -j DROP' % ip
print(cmd, file=sys.stderr)
os.system(cmd)