├── .gitignore ├── README.md ├── local.py └── server.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | 3 | list.txt 4 | 5 | # Packages 6 | *.egg 7 | *.egg-info 8 | dist 9 | build 10 | eggs 11 | parts 12 | bin 13 | var 14 | sdist 15 | develop-eggs 16 | .installed.cfg 17 | 18 | # Installer logs 19 | pip-log.txt 20 | 21 | # Unit test / coverage reports 22 | .coverage 23 | .tox 24 | 25 | #Translations 26 | *.mo 27 | 28 | #Mr Developer 29 | .mr.developer.cfg 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 增加自定义服务器列表支持,请将服务器地址列表放在同文件夹下,文件名: list.txt 2 | 格式: 3 | 4 | 8.8.8.8:8499 5 | 4.4.4.4:8499 6 | #1.1.1.1:8849 7 | 8 | 暂时不使用的服务器地址可使用#注释 9 | ----------- 10 | 本程序fork自shadowsocks。增加对多个服务端的支持,如果在限制带宽的内网使用,可达到多倍带宽的效果。在下载http资源,及播放在线视频时有显著加速功能。 11 | 12 | I forked this project, and try to update it so it can connect to multi-servers, so I can use more bandwidth, 13 | I hope it can take effects, ^_~ 14 | 2012.4.21 00:00 15 | ----------- 16 | shadowsocks 17 | =========== 18 | 19 | shadowsocks is a lightweight tunnel proxy which can help you get through firewalls 20 | 21 | usage 22 | ----------- 23 | 24 | Put `server.py` on your server. Edit `server.py`, change the following values: 25 | 26 | PORT server port 27 | KEY a password to identify clients 28 | 29 | Run `python server.py` on your server. To run it in the background, run `setsid python server.py`. 30 | 31 | Put `local.py` on your client machine. Edit `local.py`, change these values: 32 | 33 | SERVER your your server ip or hostname 34 | REMOTE_PORT server port 35 | PORT local port 36 | KEY a password, it must be the same as the password of your server 37 | 38 | Run `python local.py` on your client machine. 39 | 40 | Change proxy settings of your browser into 41 | 42 | SOCKS5 127.0.0.1:PORT 43 | 44 | -------------------------------------------------------------------------------- /local.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2012 clowwindy 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | import os 23 | SERVERS = [ 24 | ('xxx.xxx.xx.11', 8499), 25 | ] 26 | 27 | if os.path.exists('list.txt'): 28 | data = open('list.txt').readlines() 29 | SERVERS = [] 30 | item = (i.split(':') for i in data if ':' '#' not in i) 31 | while 1: 32 | try: 33 | i = item.next() 34 | except: 35 | break 36 | SERVERS.append((i[0], int(i[1]))) 37 | 38 | PORT = 1080 39 | KEY = "foobar!" 40 | 41 | import sys 42 | import socket 43 | import select 44 | import string 45 | import struct 46 | import hashlib 47 | import threading 48 | import time 49 | import SocketServer 50 | 51 | 52 | def get_server(): 53 | servers = SERVERS 54 | while 1: 55 | for i in servers: 56 | yield i 57 | 58 | server = get_server() 59 | 60 | def get_table(key): 61 | m = hashlib.md5() 62 | m.update(key) 63 | s = m.digest() 64 | (a, b) = struct.unpack('H', self.decrypt(self.rfile.read(2))) 91 | reply = "\x05\x00\x00\x01" 92 | try: 93 | if mode == 1: 94 | remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 95 | remote.connect((addr, port[0])) 96 | local = remote.getsockname() 97 | reply += socket.inet_aton(local[0]) + struct.pack(">H", 98 | local[1]) 99 | print 'Tcp connect to', addr, port[0] 100 | else: 101 | reply = "\x05\x07\x00\x01" # Command not supported 102 | print 'command not supported' 103 | except socket.error: 104 | # Connection refused 105 | reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' 106 | self.send_encrpyt(sock, reply) 107 | if reply[1] == '\x00': 108 | if mode == 1: 109 | self.handle_tcp(sock, remote) 110 | except socket.error: 111 | print 'socket error' 112 | 113 | 114 | def main(host=''): 115 | server = ThreadingTCPServer((host, PORT), Socks5Server) 116 | server.allow_reuse_address = True 117 | print "starting server at port %d ..." % PORT 118 | server.serve_forever() 119 | 120 | if __name__ == '__main__': 121 | encrypt_table = ''.join(get_table(KEY)) 122 | decrypt_table = string.maketrans(encrypt_table, string.maketrans('', '')) 123 | arg = sys.argv 124 | if len(arg) == 1: 125 | host = '' 126 | print "Use default host" 127 | else: 128 | host = arg[1] 129 | print "Use host %s" % host 130 | main(host) 131 | --------------------------------------------------------------------------------