Compare commits
10 Commits
893f9099b3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ff694b2c2 | |||
| e332ec93e9 | |||
| c668f44c68 | |||
| 8b302646ed | |||
| 2ab8c6bf5d | |||
| f7d7aee3a6 | |||
| 0168be7c92 | |||
| 0b0379b830 | |||
| 91e6237794 | |||
| 3c82f02343 |
@ -10,7 +10,7 @@ cache:
|
|||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get update -qq
|
- sudo apt-get update -qq
|
||||||
- sudo apt-get install -qq build-essential dnsutils iproute nginx bc
|
- sudo apt-get install -qq build-essential dnsutils iproute nginx bc
|
||||||
- sudo dd if=/dev/urandom of=/usr/share/nginx/www/file bs=1M count=10
|
- sudo dd if=/dev/urandom of=/usr/share/nginx/html/file bs=1M count=10
|
||||||
- sudo sh -c "echo '127.0.0.1 localhost' > /etc/hosts"
|
- sudo sh -c "echo '127.0.0.1 localhost' > /etc/hosts"
|
||||||
- sudo service nginx restart
|
- sudo service nginx restart
|
||||||
- pip install pep8 pyflakes nose coverage PySocks
|
- pip install pep8 pyflakes nose coverage PySocks
|
||||||
|
|||||||
16
README.md
16
README.md
@ -28,6 +28,15 @@ CentOS:
|
|||||||
yum install python-setuptools && easy_install pip
|
yum install python-setuptools && easy_install pip
|
||||||
pip install git+https://github.com/shadowsocks/shadowsocks.git@master
|
pip install git+https://github.com/shadowsocks/shadowsocks.git@master
|
||||||
|
|
||||||
|
For CentOS 7, if you need AEAD ciphers, you need install libsodium
|
||||||
|
```
|
||||||
|
dnf install libsodium python34-pip
|
||||||
|
pip3 install git+https://github.com/shadowsocks/shadowsocks.git@master
|
||||||
|
```
|
||||||
|
Linux distributions with [snap](http://snapcraft.io/):
|
||||||
|
|
||||||
|
snap install shadowsocks
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
||||||
See [Install Shadowsocks Server on Windows](https://github.com/shadowsocks/shadowsocks/wiki/Install-Shadowsocks-Server-on-Windows).
|
See [Install Shadowsocks Server on Windows](https://github.com/shadowsocks/shadowsocks/wiki/Install-Shadowsocks-Server-on-Windows).
|
||||||
@ -51,9 +60,14 @@ To check the log:
|
|||||||
Check all the options via `-h`. You can also use a [Configuration] file
|
Check all the options via `-h`. You can also use a [Configuration] file
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
|
If you installed the [snap](http://snapcraft.io/) package, you have to prefix the commands with `shadowsocks.`,
|
||||||
|
like this:
|
||||||
|
|
||||||
|
shadowsocks.ssserver -p 443 -k password -m aes-256-cfb
|
||||||
|
|
||||||
### Usage with Config File
|
### Usage with Config File
|
||||||
|
|
||||||
[Create configeration file and run](https://github.com/shadowsocks/shadowsocks/wiki/Configuration-via-Config-File)
|
[Create configuration file and run](https://github.com/shadowsocks/shadowsocks/wiki/Configuration-via-Config-File)
|
||||||
|
|
||||||
To start:
|
To start:
|
||||||
|
|
||||||
|
|||||||
@ -408,22 +408,20 @@ ciphers = {
|
|||||||
|
|
||||||
|
|
||||||
def run_method(method):
|
def run_method(method):
|
||||||
from shadowsocks.crypto import openssl
|
|
||||||
|
|
||||||
print(method, ': [stream]', 32)
|
print(method, ': [stream]', 32)
|
||||||
cipher = MbedTLSStreamCrypto(method, b'k' * 32, b'i' * 16, 1)
|
cipher = MbedTLSStreamCrypto(method, b'k' * 32, b'i' * 16, 1)
|
||||||
decipher = openssl.OpenSSLStreamCrypto(method, b'k' * 32, b'i' * 16, 0)
|
decipher = MbedTLSStreamCrypto(method, b'k' * 32, b'i' * 16, 0)
|
||||||
|
|
||||||
util.run_cipher(cipher, decipher)
|
util.run_cipher(cipher, decipher)
|
||||||
|
|
||||||
|
|
||||||
def run_aead_method(method, key_len=16):
|
def run_aead_method(method, key_len=16):
|
||||||
from shadowsocks.crypto import openssl
|
|
||||||
|
|
||||||
print(method, ': [payload][tag]', key_len)
|
print(method, ': [payload][tag]', key_len)
|
||||||
key_len = int(key_len)
|
key_len = int(key_len)
|
||||||
cipher = MbedTLSAeadCrypto(method, b'k' * key_len, b'i' * key_len, 1)
|
cipher = MbedTLSAeadCrypto(method, b'k' * key_len, b'i' * key_len, 1)
|
||||||
decipher = openssl.OpenSSLAeadCrypto(
|
decipher = MbedTLSAeadCrypto(
|
||||||
method,
|
method,
|
||||||
b'k' * key_len, b'i' * key_len, 0
|
b'k' * key_len, b'i' * key_len, 0
|
||||||
)
|
)
|
||||||
@ -432,12 +430,11 @@ def run_aead_method(method, key_len=16):
|
|||||||
|
|
||||||
|
|
||||||
def run_aead_method_chunk(method, key_len=16):
|
def run_aead_method_chunk(method, key_len=16):
|
||||||
from shadowsocks.crypto import openssl
|
|
||||||
|
|
||||||
print(method, ': chunk([size][tag][payload][tag]', key_len)
|
print(method, ': chunk([size][tag][payload][tag]', key_len)
|
||||||
key_len = int(key_len)
|
key_len = int(key_len)
|
||||||
cipher = MbedTLSAeadCrypto(method, b'k' * key_len, b'i' * key_len, 1)
|
cipher = MbedTLSAeadCrypto(method, b'k' * key_len, b'i' * key_len, 1)
|
||||||
decipher = openssl.OpenSSLAeadCrypto(
|
decipher = MbedTLSAeadCrypto(
|
||||||
method,
|
method,
|
||||||
b'k' * key_len, b'i' * key_len, 0
|
b'k' * key_len, b'i' * key_len, 0
|
||||||
)
|
)
|
||||||
|
|||||||
@ -346,6 +346,8 @@ def run_method(method):
|
|||||||
|
|
||||||
def run_aead_method(method, key_len=16):
|
def run_aead_method(method, key_len=16):
|
||||||
|
|
||||||
|
if not loaded:
|
||||||
|
load_openssl(None)
|
||||||
print(method, ': [payload][tag]', key_len)
|
print(method, ': [payload][tag]', key_len)
|
||||||
cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(method))
|
cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(method))
|
||||||
if not cipher:
|
if not cipher:
|
||||||
@ -362,6 +364,8 @@ def run_aead_method(method, key_len=16):
|
|||||||
|
|
||||||
def run_aead_method_chunk(method, key_len=16):
|
def run_aead_method_chunk(method, key_len=16):
|
||||||
|
|
||||||
|
if not loaded:
|
||||||
|
load_openssl(None)
|
||||||
print(method, ': chunk([size][tag][payload][tag]', key_len)
|
print(method, ': chunk([size][tag][payload][tag]', key_len)
|
||||||
cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(method))
|
cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(method))
|
||||||
if not cipher:
|
if not cipher:
|
||||||
|
|||||||
@ -79,18 +79,15 @@ class LRUCache(collections.MutableMapping):
|
|||||||
least = self._last_visits[0]
|
least = self._last_visits[0]
|
||||||
if now - least <= self.timeout:
|
if now - least <= self.timeout:
|
||||||
break
|
break
|
||||||
if self.close_callback is not None:
|
|
||||||
for key in self._time_to_keys[least]:
|
|
||||||
if key in self._store:
|
|
||||||
if now - self._keys_to_last_time[key] > self.timeout:
|
|
||||||
value = self._store[key]
|
|
||||||
if value not in self._closed_values:
|
|
||||||
self.close_callback(value)
|
|
||||||
self._closed_values.add(value)
|
|
||||||
self._last_visits.popleft()
|
self._last_visits.popleft()
|
||||||
for key in self._time_to_keys[least]:
|
for key in self._time_to_keys[least]:
|
||||||
if key in self._store:
|
if key in self._store:
|
||||||
if now - self._keys_to_last_time[key] > self.timeout:
|
if now - self._keys_to_last_time[key] > self.timeout:
|
||||||
|
if self.close_callback is not None:
|
||||||
|
value = self._store[key]
|
||||||
|
if value not in self._closed_values:
|
||||||
|
self.close_callback(value)
|
||||||
|
self._closed_values.add(value)
|
||||||
del self._store[key]
|
del self._store[key]
|
||||||
del self._keys_to_last_time[key]
|
del self._keys_to_last_time[key]
|
||||||
c += 1
|
c += 1
|
||||||
@ -140,6 +137,7 @@ def test():
|
|||||||
|
|
||||||
c = LRUCache(timeout=0.1, close_callback=close_cb)
|
c = LRUCache(timeout=0.1, close_callback=close_cb)
|
||||||
c['s'] = 1
|
c['s'] = 1
|
||||||
|
c['t'] = 1
|
||||||
c['s']
|
c['s']
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
c['s']
|
c['s']
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
from __future__ import absolute_import, division, print_function, \
|
from __future__ import absolute_import, division, print_function, \
|
||||||
with_statement
|
with_statement
|
||||||
|
|
||||||
|
import os
|
||||||
|
import atexit
|
||||||
import errno
|
import errno
|
||||||
import traceback
|
import traceback
|
||||||
import socket
|
import socket
|
||||||
@ -35,6 +37,9 @@ STAT_SEND_LIMIT = 50
|
|||||||
class Manager(object):
|
class Manager(object):
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
|
atexit.register(self.cleanup)
|
||||||
|
self._is_unix = False
|
||||||
|
self._mngr_address = None
|
||||||
self._config = config
|
self._config = config
|
||||||
self._relays = {} # (tcprelay, udprelay)
|
self._relays = {} # (tcprelay, udprelay)
|
||||||
self._loop = eventloop.EventLoop()
|
self._loop = eventloop.EventLoop()
|
||||||
@ -57,6 +62,8 @@ class Manager(object):
|
|||||||
else:
|
else:
|
||||||
addr = manager_address
|
addr = manager_address
|
||||||
family = socket.AF_UNIX
|
family = socket.AF_UNIX
|
||||||
|
self._is_unix = True
|
||||||
|
self._mngr_address = manager_address
|
||||||
self._control_socket = socket.socket(family,
|
self._control_socket = socket.socket(family,
|
||||||
socket.SOCK_DGRAM)
|
socket.SOCK_DGRAM)
|
||||||
self._control_socket.bind(addr)
|
self._control_socket.bind(addr)
|
||||||
@ -78,6 +85,13 @@ class Manager(object):
|
|||||||
a_config['password'] = password
|
a_config['password'] = password
|
||||||
self.add_port(a_config)
|
self.add_port(a_config)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
if self._is_unix:
|
||||||
|
try:
|
||||||
|
os.unlink(self._mngr_address)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def add_port(self, config):
|
def add_port(self, config):
|
||||||
port = int(config['server_port'])
|
port = int(config['server_port'])
|
||||||
servers = self._relays.get(port, None)
|
servers = self._relays.get(port, None)
|
||||||
|
|||||||
23
snapcraft.yaml
Normal file
23
snapcraft.yaml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
name: shadowsocks
|
||||||
|
version: 2.9.1-1
|
||||||
|
summary: A fast tunnel proxy that helps you bypass firewalls
|
||||||
|
description: A fast tunnel proxy that helps you bypass firewalls
|
||||||
|
confinement: strict
|
||||||
|
grade: stable
|
||||||
|
|
||||||
|
apps:
|
||||||
|
sslocal:
|
||||||
|
command: bin/sslocal
|
||||||
|
plugs: [network, network-bind]
|
||||||
|
aliases: [sslocal]
|
||||||
|
|
||||||
|
ssserver:
|
||||||
|
command: bin/ssserver
|
||||||
|
plugs: [network, network-bind]
|
||||||
|
aliases: [ssserver]
|
||||||
|
|
||||||
|
parts:
|
||||||
|
shadowsocks:
|
||||||
|
plugin: python
|
||||||
|
python-version: python2
|
||||||
|
source: https://github.com/shadowsocks/shadowsocks/archive/2.9.1.tar.gz
|
||||||
@ -102,11 +102,10 @@ fi
|
|||||||
run_test tests/test_udp_src.sh
|
run_test tests/test_udp_src.sh
|
||||||
run_test tests/test_command.sh
|
run_test tests/test_command.sh
|
||||||
|
|
||||||
coverage combine && coverage report --include=shadowsocks/*
|
# coverage combine && coverage report --include=shadowsocks/*
|
||||||
rm -rf htmlcov
|
# rm -rf htmlcov
|
||||||
rm -rf tmp
|
# rm -rf tmp
|
||||||
coverage html --include=shadowsocks/*
|
# coverage html --include=shadowsocks/*
|
||||||
|
# coverage report --include=shadowsocks/* | tail -n1 | rev | cut -d' ' -f 1 | rev > /tmp/shadowsocks-coverage
|
||||||
coverage report --include=shadowsocks/* | tail -n1 | rev | cut -d' ' -f 1 | rev > /tmp/shadowsocks-coverage
|
|
||||||
|
|
||||||
exit $result
|
exit $result
|
||||||
|
|||||||
@ -10,3 +10,10 @@ pushd openssl-$OPENSSL_VER
|
|||||||
# sudo ldconfig # test multiple libcrypto
|
# sudo ldconfig # test multiple libcrypto
|
||||||
popd
|
popd
|
||||||
rm -rf openssl-$OPENSSL_VER || exit 1
|
rm -rf openssl-$OPENSSL_VER || exit 1
|
||||||
|
|
||||||
|
rm /usr/bin/openssl || exit 1
|
||||||
|
rm -r /usr/include/openssl || exit 1
|
||||||
|
ln -s /usr/local/bin/openssl /usr/bin/openssl || exit 1
|
||||||
|
ln -s /usr/local/include/openssl /usr/include/openssl || exit 1
|
||||||
|
echo /usr/local/lib >> /etc/ld.so.conf || exit 1
|
||||||
|
ldconfig -v || exit 1
|
||||||
|
|||||||
@ -24,9 +24,17 @@
|
|||||||
from __future__ import absolute_import, division, print_function, \
|
from __future__ import absolute_import, division, print_function, \
|
||||||
with_statement
|
with_statement
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
|
import socket
|
||||||
import argparse
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def inet_pton(str_ip):
|
||||||
|
try:
|
||||||
|
return socket.inet_pton(socket.AF_INET, str_ip)
|
||||||
|
except socket.error:
|
||||||
|
return None
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='See README')
|
parser = argparse.ArgumentParser(description='See README')
|
||||||
@ -37,17 +45,22 @@ if __name__ == '__main__':
|
|||||||
ips = {}
|
ips = {}
|
||||||
banned = set()
|
banned = set()
|
||||||
for line in sys.stdin:
|
for line in sys.stdin:
|
||||||
if 'can not parse header when' in line:
|
if 'can not parse header when' not in line:
|
||||||
ip = line.split()[-1].split(':')[-2]
|
continue
|
||||||
if ip not in ips:
|
ip_str = line.split()[-1].rsplit(':', 1)[0]
|
||||||
ips[ip] = 1
|
ip = inet_pton(ip_str)
|
||||||
print(ip)
|
if ip is None:
|
||||||
sys.stdout.flush()
|
continue
|
||||||
else:
|
if ip not in ips:
|
||||||
ips[ip] += 1
|
ips[ip] = 1
|
||||||
if ip not in banned and ips[ip] >= config.count:
|
sys.stdout.flush()
|
||||||
banned.add(ip)
|
else:
|
||||||
cmd = 'iptables -A INPUT -s %s -j DROP' % ip
|
ips[ip] += 1
|
||||||
print(cmd, file=sys.stderr)
|
if ip not in banned and ips[ip] >= config.count:
|
||||||
sys.stderr.flush()
|
banned.add(ip)
|
||||||
os.system(cmd)
|
print('ban ip %s' % ip_str)
|
||||||
|
cmd = ['iptables', '-A', 'INPUT', '-s', ip_str, '-j', 'DROP',
|
||||||
|
'-m', 'comment', '--comment', 'autoban']
|
||||||
|
print(' '.join(cmd), file=sys.stderr)
|
||||||
|
sys.stderr.flush()
|
||||||
|
subprocess.call(cmd)
|
||||||
|
|||||||
Reference in New Issue
Block a user