diff --git a/shadowsocks/common.py b/shadowsocks/common.py index 68017d5..5a3c9b1 100644 --- a/shadowsocks/common.py +++ b/shadowsocks/common.py @@ -283,6 +283,31 @@ class IPNetwork(object): else: return False +class PortRange(object): + def __init__(self, range_str): + self.range = set() + if type(range_str) == str: + range_str = range_str.split(',') + for item in range_str: + try: + int_range = item.split('-') + if len(int_range) == 1: + self.range.add(int(item)) + elif len(int_range) == 2: + int_range[0] = int(int_range[0]) + int_range[1] = int(int_range[1]) + if int_range[0] < 0: + int_range[0] = 0 + if int_range[1] > 65535: + int_range[1] = 65535 + i = int_range[0] + while i <= int_range[1]: + self.range.add(i) + except Exception as e: + logging.error(e) + + def __contains__(self, val): + return val in self.range def test_inet_conv(): ipv4 = b'8.8.4.4' diff --git a/shadowsocks/shell.py b/shadowsocks/shell.py index ed0cc42..0d6d338 100644 --- a/shadowsocks/shell.py +++ b/shadowsocks/shell.py @@ -23,7 +23,7 @@ import json import sys import getopt import logging -from shadowsocks.common import to_bytes, to_str, IPNetwork +from shadowsocks.common import to_bytes, to_str, IPNetwork, PortRange from shadowsocks import encrypt @@ -261,6 +261,11 @@ def get_config(is_local): except Exception as e: logging.error(e) sys.exit(2) + try: + config['forbidden_port'] = PortRange(config.get('forbidden_port', '')) + except Exception as e: + logging.error(e) + sys.exit(2) try: config['ignore_bind'] = \ IPNetwork(config.get('ignore_bind', '127.0.0.0/8,::1/128')) diff --git a/shadowsocks/tcprelay.py b/shadowsocks/tcprelay.py index 77331d8..7e3f91b 100644 --- a/shadowsocks/tcprelay.py +++ b/shadowsocks/tcprelay.py @@ -160,6 +160,10 @@ class TCPRelayHandler(object): self._forbidden_iplist = config['forbidden_ip'] else: self._forbidden_iplist = None + if 'forbidden_port' in config: + self._forbidden_portset = config['forbidden_port'] + else: + self._forbidden_portset = None if is_local: self._chosen_server = self._get_a_server() fd_to_handlers[local_sock.fileno()] = self @@ -511,10 +515,15 @@ class TCPRelayHandler(object): if len(addrs) == 0: raise Exception("getaddrinfo failed for %s:%d" % (ip, port)) af, socktype, proto, canonname, sa = addrs[0] - if not self._remote_udp and self._forbidden_iplist: - if common.to_str(sa[0]) in self._forbidden_iplist: - raise Exception('IP %s is in forbidden list, reject' % - common.to_str(sa[0])) + if not self._remote_udp: + if self._forbidden_iplist: + if common.to_str(sa[0]) in self._forbidden_iplist: + raise Exception('IP %s is in forbidden list, reject' % + common.to_str(sa[0])) + if self._forbidden_portset: + if sa[1] in self._forbidden_portset: + raise Exception('Port %d is in forbidden list, reject' % + sa[1]) remote_sock = socket.socket(af, socktype, proto) self._remote_sock = remote_sock self._fd_to_handlers[remote_sock.fileno()] = self @@ -652,7 +661,21 @@ class TCPRelayHandler(object): else: data = obfs_decode[0] try: - data = self._protocol.server_post_decrypt(data) + newdata = self._protocol.server_post_decrypt(data) + if data and not newdata: + data = self._protocol.server_pre_encrypt(data) + data = self._encryptor.encrypt(data) + data = self._obfs.server_encode(data) + try: + self._write_to_sock(data, self._local_sock) + except Exception as e: + shell.print_exception(e) + if self._config['verbose']: + traceback.print_exc() + logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) + self.destroy() + return + data = newdata except Exception as e: shell.print_exception(e) logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) diff --git a/shadowsocks/udprelay.py b/shadowsocks/udprelay.py index 3781d7d..5af77b0 100644 --- a/shadowsocks/udprelay.py +++ b/shadowsocks/udprelay.py @@ -301,6 +301,10 @@ class TCPRelayHandler(object): self._forbidden_iplist = config['forbidden_ip'] else: self._forbidden_iplist = None + if 'forbidden_port' in config: + self._forbidden_portset = config['forbidden_port'] + else: + self._forbidden_portset = None #fd_to_handlers[local_sock.fileno()] = self #local_sock.setblocking(False) #loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR) @@ -1077,6 +1081,10 @@ class UDPRelay(object): common.to_str(sa[0])) # drop return + if self._forbidden_portset: + if sa[1] in self._forbidden_portset: + raise Exception('Port %d is in forbidden list, reject' % + sa[1]) client = socket.socket(af, socktype, proto) client.setblocking(False) is_dns = False