move to pypi
This commit is contained in:
parent
da3981ac23
commit
794ff240a6
10 changed files with 169 additions and 62 deletions
10
.travis.yml
10
.travis.yml
|
@ -1,15 +1,11 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- 2.6
|
||||
- 2.7
|
||||
- pypy
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libevent-dev python-gevent
|
||||
- pip install gevent
|
||||
- pip install simplejson
|
||||
script:
|
||||
- python test.py
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
|
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
Shadowsocks
|
||||
|
||||
Copyright (c) 2013 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.
|
45
README.md
45
README.md
|
@ -2,7 +2,7 @@ shadowsocks
|
|||
===========
|
||||
|
||||
[![Build Status](https://travis-ci.org/clowwindy/shadowsocks.png)](https://travis-ci.org/clowwindy/shadowsocks)
|
||||
Current version: 1.2.3
|
||||
Current version: 1.3.0
|
||||
|
||||
shadowsocks is a lightweight tunnel proxy which can help you get through firewalls
|
||||
|
||||
|
@ -15,20 +15,35 @@ First, make sure you have Python 2.6 or 2.7.
|
|||
|
||||
$ python --version
|
||||
Python 2.6.8
|
||||
|
||||
Install Shadowsocks.
|
||||
|
||||
pip install shadowsocks
|
||||
|
||||
Create a file named `config.json`, with the following content.
|
||||
|
||||
Then edit `config.json`, change the following values:
|
||||
{
|
||||
"server":"my_server_ip",
|
||||
"server_port":8388,
|
||||
"local_port":1080,
|
||||
"password":"barfoo!",
|
||||
"timeout":600,
|
||||
"method":null
|
||||
}
|
||||
|
||||
server your server ip or hostname
|
||||
Explaination of the fields:
|
||||
|
||||
server your server IP (IPv4/IPv6), notice that your server will listen to this IP
|
||||
server_port server port
|
||||
local_port local port
|
||||
password a password used to encrypt transfer
|
||||
timeout in seconds
|
||||
method encryption method, "bf-cfb", "aes-256-cfb", "des-cfb", "rc4", etc. Default is table
|
||||
|
||||
`cd` into the directory of `config.json`. Run `ssserver` on your server. To run it in the background, run
|
||||
`nohup ssserver > log &`.
|
||||
|
||||
Put all the files on your server. Run `python server.py` on your server. To run it in the background, run `nohup python server.py > log &`.
|
||||
|
||||
Put all the files on your client machine. Run `python local.py` on your client machine.
|
||||
On your client machine, run `sslocal`.
|
||||
|
||||
Change the proxy setting in your browser into
|
||||
|
||||
|
@ -36,6 +51,15 @@ Change the proxy setting in your browser into
|
|||
hostname: 127.0.0.1
|
||||
port: your local_port
|
||||
|
||||
Command line args
|
||||
------------------
|
||||
|
||||
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
|
||||
ssserver -p server_port -k password -m bf-cfb
|
||||
ssserver -c /etc/shadowsocks/config.json
|
||||
|
||||
Encryption
|
||||
------------
|
||||
|
||||
|
@ -49,15 +73,6 @@ Others:
|
|||
|
||||
pip install M2Crypto
|
||||
|
||||
|
||||
Command line args
|
||||
-----------------
|
||||
|
||||
You can use args to override settings from `config.json`.
|
||||
|
||||
python local.py -s server_name -p server_port -l local_port -k password -m bf-cfb -b bind_address -6
|
||||
python server.py -p server_port -k password -m bf-cfb -6
|
||||
|
||||
Performance
|
||||
------------
|
||||
|
||||
|
|
21
setup.py
Normal file
21
setup.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name = "shadowsocks",
|
||||
version = "1.3.0",
|
||||
license = 'MIT',
|
||||
description = "a lightweight tunnel proxy",
|
||||
author = 'clowwindy42@gmail.com',
|
||||
url = 'https://github.com/clowwindy/shadowsocks',
|
||||
packages = ['shadowsocks'],
|
||||
package_data={
|
||||
'shadowsocks': ['README.md', 'LICENSE', 'config.json']
|
||||
},
|
||||
install_requires = ['setuptools',
|
||||
],
|
||||
entry_points="""
|
||||
[console_scripts]
|
||||
sslocal = shadowsocks.local:main
|
||||
ssserver = shadowsocks.server:main
|
||||
""",
|
||||
)
|
1
shadowsocks/__init__.py
Normal file
1
shadowsocks/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
#!/usr/bin/python
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2012 clowwindy
|
||||
# Copyright (c) 2013 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
|
||||
|
@ -43,6 +43,7 @@ import os
|
|||
import logging
|
||||
import getopt
|
||||
import encrypt
|
||||
import utils
|
||||
|
||||
|
||||
def send_all(sock, data):
|
||||
|
@ -142,28 +143,48 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
|||
logging.warn(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
def main():
|
||||
global SERVER, REMOTE_PORT, PORT, KEY, METHOD, LOCAL, IPv6
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s %(levelname)-8s %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S', filemode='a+')
|
||||
|
||||
# fix py2exe
|
||||
if hasattr(sys, "frozen") and sys.frozen in \
|
||||
("windows_exe", "console_exe"):
|
||||
p = os.path.dirname(os.path.abspath(sys.executable))
|
||||
os.chdir(p)
|
||||
version = ''
|
||||
try:
|
||||
os.chdir(os.path.dirname(__file__) or '.')
|
||||
except NameError:
|
||||
# fix py2exe
|
||||
if hasattr(sys, "frozen") and sys.frozen in \
|
||||
("windows_exe", "console_exe"):
|
||||
p = os.path.dirname(os.path.abspath(sys.executable))
|
||||
os.chdir(p)
|
||||
print 'shadowsocks v1.2.3'
|
||||
import pkg_resources
|
||||
version = pkg_resources.get_distribution('shadowsocks').version
|
||||
except ImportError:
|
||||
pass
|
||||
print 'shadowsocks %s' % version
|
||||
|
||||
with open('config.json', 'rb') as f:
|
||||
config = json.load(f)
|
||||
SERVER = config['server']
|
||||
REMOTE_PORT = config['server_port']
|
||||
PORT = config['local_port']
|
||||
KEY = config['password']
|
||||
METHOD = config.get('method', None)
|
||||
LOCAL = config.get('local', '')
|
||||
METHOD = None
|
||||
LOCAL = ''
|
||||
IPv6 = False
|
||||
|
||||
config_path = utils.find_config()
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6')
|
||||
for key, value in optlist:
|
||||
if key == '-c':
|
||||
config_path = value
|
||||
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:6')
|
||||
if config_path:
|
||||
logging.info('loading config from %s' % config_path)
|
||||
with open(config_path, 'rb') as f:
|
||||
config = json.load(f)
|
||||
SERVER = config['server']
|
||||
REMOTE_PORT = config['server_port']
|
||||
PORT = config['local_port']
|
||||
KEY = config['password']
|
||||
METHOD = config.get('method', None)
|
||||
LOCAL = config.get('local', '')
|
||||
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 's:b:p:k:l:m:c:6')
|
||||
for key, value in optlist:
|
||||
if key == '-p':
|
||||
REMOTE_PORT = int(value)
|
||||
|
@ -180,10 +201,6 @@ if __name__ == '__main__':
|
|||
elif key == '-6':
|
||||
IPv6 = True
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s %(levelname)-8s %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S', filemode='a+')
|
||||
|
||||
encrypt.init_table(KEY, METHOD)
|
||||
|
||||
try:
|
||||
|
@ -197,3 +214,6 @@ if __name__ == '__main__':
|
|||
except KeyboardInterrupt:
|
||||
server.shutdown()
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2012 clowwindy
|
||||
# Copyright (c) 2013 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
|
||||
|
@ -43,6 +43,7 @@ import os
|
|||
import logging
|
||||
import getopt
|
||||
import encrypt
|
||||
import utils
|
||||
|
||||
|
||||
def send_all(sock, data):
|
||||
|
@ -123,21 +124,40 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
|||
except socket.error, e:
|
||||
logging.warn(e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.chdir(os.path.dirname(__file__) or '.')
|
||||
|
||||
print 'shadowsocks v1.2.3'
|
||||
def main():
|
||||
global SERVER, PORT, KEY, METHOD, IPv6
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s %(levelname)-8s %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S', filemode='a+')
|
||||
|
||||
version = ''
|
||||
try:
|
||||
import pkg_resources
|
||||
version = pkg_resources.get_distribution('shadowsocks').version
|
||||
except ImportError:
|
||||
pass
|
||||
print 'shadowsocks %s' % version
|
||||
|
||||
METHOD = None
|
||||
IPv6 = False
|
||||
|
||||
config_path = utils.find_config()
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 'p:k:m:c:6')
|
||||
for key, value in optlist:
|
||||
if key == '-c':
|
||||
config_path = value
|
||||
with open('config.json', 'rb') as f:
|
||||
config = json.load(f)
|
||||
|
||||
SERVER = config['server']
|
||||
PORT = config['server_port']
|
||||
KEY = config['password']
|
||||
METHOD = config.get('method', None)
|
||||
IPv6 = False
|
||||
if config_path:
|
||||
logging.info('loading config from %s' % config_path)
|
||||
SERVER = config['server']
|
||||
PORT = config['server_port']
|
||||
KEY = config['password']
|
||||
METHOD = config.get('method', None)
|
||||
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 'p:k:m:6')
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 'p:k:m:c:6')
|
||||
for key, value in optlist:
|
||||
if key == '-p':
|
||||
PORT = int(value)
|
||||
|
@ -148,10 +168,6 @@ if __name__ == '__main__':
|
|||
elif key == '-6':
|
||||
IPv6 = True
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG,
|
||||
format='%(asctime)s %(levelname)-8s %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S', filemode='a+')
|
||||
|
||||
encrypt.init_table(KEY, METHOD)
|
||||
if IPv6:
|
||||
ThreadingTCPServer.address_family = socket.AF_INET6
|
||||
|
@ -161,3 +177,6 @@ if __name__ == '__main__':
|
|||
server.serve_forever()
|
||||
except socket.error, e:
|
||||
logging.error(e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
14
shadowsocks/utils.py
Normal file
14
shadowsocks/utils.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def find_config():
|
||||
config_path = 'config.json'
|
||||
if os.path.exists(config_path):
|
||||
return config_path
|
||||
config_path = os.path.join(os.path.dirname(__file__), '../', 'config.json')
|
||||
if os.path.exists(config_path):
|
||||
return config_path
|
||||
return None
|
4
test.py
4
test.py
|
@ -82,9 +82,9 @@ decrypt_table = string.maketrans(encrypt_table, string.maketrans('', ''))
|
|||
for i in range(0, 256):
|
||||
assert(target2[0][i] == ord(encrypt_table[i]))
|
||||
assert(target2[1][i] == ord(decrypt_table[i]))
|
||||
p1 = Popen(['python', 'server.py'], shell=False, bufsize=0, stdin=PIPE,
|
||||
p1 = Popen(['python', 'shadowsocks/server.py'], shell=False, bufsize=0, stdin=PIPE,
|
||||
stdout=PIPE, stderr=PIPE, close_fds=True)
|
||||
p2 = Popen(['python', 'local.py'], shell=False, bufsize=0, stdin=PIPE,
|
||||
p2 = Popen(['python', 'shadowsocks/local.py'], shell=False, bufsize=0, stdin=PIPE,
|
||||
stdout=PIPE, stderr=PIPE, close_fds=True)
|
||||
p3 = None
|
||||
|
||||
|
|
Loading…
Reference in a new issue