merge from dev
This commit is contained in:
commit
6763a94a1d
3 changed files with 77 additions and 14 deletions
10
README.md
10
README.md
|
@ -1,6 +1,8 @@
|
||||||
shadowsocks
|
shadowsocks
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
Current version: 0.9
|
||||||
|
|
||||||
shadowsocks is a lightweight tunnel proxy which can help you get through firewalls
|
shadowsocks is a lightweight tunnel proxy which can help you get through firewalls
|
||||||
|
|
||||||
usage
|
usage
|
||||||
|
@ -11,6 +13,7 @@ First, make sure you have Python 2.6 or 2.7.
|
||||||
$ python --version
|
$ python --version
|
||||||
Python 2.6.8
|
Python 2.6.8
|
||||||
|
|
||||||
|
|
||||||
Then edit `config.json`, change the following values:
|
Then edit `config.json`, change the following values:
|
||||||
|
|
||||||
server your server ip or hostname
|
server your server ip or hostname
|
||||||
|
@ -35,6 +38,13 @@ You can use args to override settings from `config.json`.
|
||||||
python local.py -s server_name -p server_port -l local_port -k password
|
python local.py -s server_name -p server_port -l local_port -k password
|
||||||
python server.py -p server_port -k password
|
python server.py -p server_port -k password
|
||||||
|
|
||||||
|
You may want to install gevent for better performance.
|
||||||
|
|
||||||
|
$ apt-get install python-gevent
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
$ sudo easy_install gevent
|
||||||
|
|
||||||
troubleshooting
|
troubleshooting
|
||||||
---------------
|
---------------
|
||||||
|
|
40
local.py
40
local.py
|
@ -20,6 +20,14 @@
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import gevent, gevent.monkey
|
||||||
|
gevent.monkey.patch_all(dns=gevent.version_info[0]>=1)
|
||||||
|
except ImportError:
|
||||||
|
gevent = None
|
||||||
|
print >>sys.stderr, 'warning: gevent not found, using threading instead'
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import select
|
import select
|
||||||
|
@ -27,7 +35,6 @@ import SocketServer
|
||||||
import struct
|
import struct
|
||||||
import string
|
import string
|
||||||
import hashlib
|
import hashlib
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
@ -43,9 +50,18 @@ def get_table(key):
|
||||||
table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i)))
|
table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i)))
|
||||||
return table
|
return table
|
||||||
|
|
||||||
|
def send_all(sock, data):
|
||||||
|
bytes_sent = 0
|
||||||
|
while True:
|
||||||
|
r = sock.send(data[bytes_sent:])
|
||||||
|
if r < 0:
|
||||||
|
return r
|
||||||
|
bytes_sent += r
|
||||||
|
if bytes_sent == len(data):
|
||||||
|
return bytes_sent
|
||||||
|
|
||||||
class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
||||||
pass
|
allow_reuse_address = True
|
||||||
|
|
||||||
|
|
||||||
class Socks5Server(SocketServer.StreamRequestHandler):
|
class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
|
@ -55,11 +71,20 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
while True:
|
while True:
|
||||||
r, w, e = select.select(fdset, [], [])
|
r, w, e = select.select(fdset, [], [])
|
||||||
if sock in r:
|
if sock in r:
|
||||||
if remote.send(self.encrypt(sock.recv(4096))) <= 0:
|
data = sock.recv(4096)
|
||||||
|
if len(data) <= 0:
|
||||||
break
|
break
|
||||||
|
result = send_all(remote, self.encrypt(data))
|
||||||
|
if result < len(data):
|
||||||
|
raise Exception('failed to send all data')
|
||||||
|
|
||||||
if remote in r:
|
if remote in r:
|
||||||
if sock.send(self.decrypt(remote.recv(4096))) <= 0:
|
data = remote.recv(4096)
|
||||||
|
if len(data) <= 0:
|
||||||
break
|
break
|
||||||
|
result = send_all(sock, self.decrypt(data))
|
||||||
|
if result < len(data):
|
||||||
|
raise Exception('failed to send all data')
|
||||||
finally:
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
remote.close()
|
remote.close()
|
||||||
|
@ -90,7 +115,7 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
addr = socket.inet_ntoa(addr_ip)
|
addr = socket.inet_ntoa(addr_ip)
|
||||||
addr_to_send += addr_ip
|
addr_to_send += addr_ip
|
||||||
elif addrtype == 3:
|
elif addrtype == 3:
|
||||||
addr_len = sock.recv(1)
|
addr_len = self.rfile.read(1)
|
||||||
addr = self.rfile.read(ord(addr_len))
|
addr = self.rfile.read(ord(addr_len))
|
||||||
addr_to_send += addr_len + addr
|
addr_to_send += addr_len + addr
|
||||||
else:
|
else:
|
||||||
|
@ -103,12 +128,13 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
try:
|
try:
|
||||||
reply = "\x05\x00\x00\x01"
|
reply = "\x05\x00\x00\x01"
|
||||||
reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222)
|
reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222)
|
||||||
sock.send(reply)
|
self.wfile.write(reply)
|
||||||
# reply immediately
|
# reply immediately
|
||||||
if '-6' in sys.argv[1:]:
|
if '-6' in sys.argv[1:]:
|
||||||
remote = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
remote = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||||
else:
|
else:
|
||||||
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
remote.connect((SERVER, REMOTE_PORT))
|
remote.connect((SERVER, REMOTE_PORT))
|
||||||
self.send_encrypt(remote, addr_to_send)
|
self.send_encrypt(remote, addr_to_send)
|
||||||
logging.info('connecting %s:%d' % (addr, port[0]))
|
logging.info('connecting %s:%d' % (addr, port[0]))
|
||||||
|
@ -122,6 +148,7 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
os.chdir(os.path.dirname(__file__) or '.')
|
os.chdir(os.path.dirname(__file__) or '.')
|
||||||
|
print 'shadowsocks v0.9'
|
||||||
|
|
||||||
with open('config.json', 'rb') as f:
|
with open('config.json', 'rb') as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
@ -148,7 +175,6 @@ if __name__ == '__main__':
|
||||||
decrypt_table = string.maketrans(encrypt_table, string.maketrans('', ''))
|
decrypt_table = string.maketrans(encrypt_table, string.maketrans('', ''))
|
||||||
try:
|
try:
|
||||||
server = ThreadingTCPServer(('', PORT), Socks5Server)
|
server = ThreadingTCPServer(('', PORT), Socks5Server)
|
||||||
server.allow_reuse_address = True
|
|
||||||
logging.info("starting server at port %d ..." % PORT)
|
logging.info("starting server at port %d ..." % PORT)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
|
|
37
server.py
37
server.py
|
@ -20,6 +20,14 @@
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import gevent, gevent.monkey
|
||||||
|
gevent.monkey.patch_all(dns=gevent.version_info[0]>=1)
|
||||||
|
except ImportError:
|
||||||
|
gevent = None
|
||||||
|
print >>sys.stderr, 'warning: gevent not found, using threading instead'
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import select
|
import select
|
||||||
|
@ -27,7 +35,6 @@ import SocketServer
|
||||||
import struct
|
import struct
|
||||||
import string
|
import string
|
||||||
import hashlib
|
import hashlib
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
@ -43,9 +50,18 @@ def get_table(key):
|
||||||
table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i)))
|
table.sort(lambda x, y: int(a % (ord(x) + i) - a % (ord(y) + i)))
|
||||||
return table
|
return table
|
||||||
|
|
||||||
|
def send_all(sock, data):
|
||||||
|
bytes_sent = 0
|
||||||
|
while True:
|
||||||
|
r = sock.send(data[bytes_sent:])
|
||||||
|
if r < 0:
|
||||||
|
return r
|
||||||
|
bytes_sent += r
|
||||||
|
if bytes_sent == len(data):
|
||||||
|
return bytes_sent
|
||||||
|
|
||||||
class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
||||||
pass
|
allow_reuse_address = True
|
||||||
|
|
||||||
|
|
||||||
class Socks5Server(SocketServer.StreamRequestHandler):
|
class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
|
@ -55,11 +71,20 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
while True:
|
while True:
|
||||||
r, w, e = select.select(fdset, [], [])
|
r, w, e = select.select(fdset, [], [])
|
||||||
if sock in r:
|
if sock in r:
|
||||||
if remote.send(self.decrypt(sock.recv(4096))) <= 0:
|
data = sock.recv(4096)
|
||||||
|
if len(data) <= 0:
|
||||||
break
|
break
|
||||||
|
result = send_all(remote, self.decrypt(data))
|
||||||
|
if result < len(data):
|
||||||
|
raise Exception('failed to send all data')
|
||||||
if remote in r:
|
if remote in r:
|
||||||
if sock.send(self.encrypt(remote.recv(4096))) <= 0:
|
data = remote.recv(4096)
|
||||||
|
if len(data) <= 0:
|
||||||
break
|
break
|
||||||
|
result = send_all(sock, self.encrypt(data))
|
||||||
|
if result < len(data):
|
||||||
|
raise Exception('failed to send all data')
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
remote.close()
|
remote.close()
|
||||||
|
@ -87,6 +112,7 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
try:
|
try:
|
||||||
logging.info('connecting %s:%d' % (addr, port[0]))
|
logging.info('connecting %s:%d' % (addr, port[0]))
|
||||||
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
remote.connect((addr, port[0]))
|
remote.connect((addr, port[0]))
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
# Connection refused
|
# Connection refused
|
||||||
|
@ -99,6 +125,8 @@ class Socks5Server(SocketServer.StreamRequestHandler):
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
os.chdir(os.path.dirname(__file__) or '.')
|
os.chdir(os.path.dirname(__file__) or '.')
|
||||||
|
|
||||||
|
print 'shadowsocks v0.9'
|
||||||
|
|
||||||
with open('config.json', 'rb') as f:
|
with open('config.json', 'rb') as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
|
@ -122,7 +150,6 @@ if __name__ == '__main__':
|
||||||
ThreadingTCPServer.address_family = socket.AF_INET6
|
ThreadingTCPServer.address_family = socket.AF_INET6
|
||||||
try:
|
try:
|
||||||
server = ThreadingTCPServer(('', PORT), Socks5Server)
|
server = ThreadingTCPServer(('', PORT), Socks5Server)
|
||||||
server.allow_reuse_address = True
|
|
||||||
logging.info("starting server at port %d ..." % PORT)
|
logging.info("starting server at port %d ..." % PORT)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
|
|
Loading…
Reference in a new issue