Beispiel #1
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if self._stat_callback:
         self._stat_callback(self._listen_port, len(data))
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         response = encrypt.encrypt_all(self._password, self._method, 1,
                                        data)
         if not response:
             return
     else:
         data = encrypt.encrypt_all(self._password, self._method, 0,
                                    data)
         if not data:
             return
         header_result = parse_header(data)
         if header_result is None:
             return
         addrtype, dest_addr, dest_port, header_length = header_result
         response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         self._server_socket.sendto(response, client_addr)
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
Beispiel #2
0
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         # 这里的拿到的addr仍未域名,下面会调用dns解析
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d from %s:%d' %
                      (common.to_str(remote_addr), remote_port,
                       self._client_address[0], self._client_address[1]))
         self._remote_address = (common.to_str(remote_addr), remote_port)
         # pause reading
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_local:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             # handle_dns_resolved会在DNS解析成功后调用,继续该TCP连接上的处理
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Beispiel #3
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         response = encrypt.encrypt_all(self._password, self._method, 1,
                                        data)
         if not response:
             return
     else:
         data = encrypt.encrypt_all(self._password, self._method, 0,
                                    data)
         if not data:
             return
         header_result = parse_header(data)
         if header_result is None:
             return
         # connecttype, dest_addr, dest_port, header_length = header_result
         response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         self._server_socket.sendto(response, client_addr)
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
    def _handle_stage_addr(self, data):
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('UDP associate')
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error('unknown command %d', cmd)
                    self.destroy()
                    return
            header_result = parse_header(data)
            if header_result is None:
                raise Exception('can not parse header')
            addrtype, remote_addr, remote_port, header_length = header_result
            logging.info('connecting %s:%d' % (common.to_str(remote_addr),
                                               remote_port))
            self._remote_address = (remote_addr, remote_port)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly

                # Here uses the resolve in dns_server, dns_server could perform like a portable module
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            logging.error(e)
            if self._config['verbose']:
                traceback.print_exc()
            # TODO use logging when debug completed
            self.destroy()
    def handle_addr(self, sock, event):
        data = self.sock_recv(sock)
        if not data:
            return
        # self._loop.remove(sock)

        if ord(data[1:2]) != CMD_CONNECT:
            raise Exception('Command not suppored')

        result = parse_header(data[3:])
        if not result:
            raise Exception('Header cannot be parsed')

        self._remote_sock = create_sock(*self._remote_addr)
        self.sock_connect(self._remote_sock, self._remote_addr)

        dest_addr = (to_str(result[1]), result[2])
        logging.info('Connecting to {}:{}'.format(*dest_addr))
        data = '{}:{}\n'.format(*dest_addr).encode('utf-8')
        if self._crypt:
            data = self._crypt.encrypt(data)
        self._data_to_write_to_remote.append(data)

        bind_addr = b'\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00'
        self.send_bind_addr(sock, None, bind_addr)
Beispiel #6
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            try:
                response = cryptor.encrypt_all(self._password, self._method,
                                               data, self._crypto_path)
            except Exception:
                logging.debug("UDP handle_client: encrypt data failed")
                return
            if not response:
                return
        else:
            try:
                data, key, iv = cryptor.decrypt_all(self._password,
                                                    self._method, data,
                                                    self._crypto_path)
            except Exception:
                logging.debug('UDP handle_client: decrypt data failed')
                return
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            addrtype, dest_addr, dest_port, header_length = header_result
            if self._is_tunnel:
                # remove ss header
                response = data[header_length:]
            else:
                response = b'\x00\x00\x00' + data
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())

        if self._stat_callback:
            activity = {
                'remote_address': client_addr,
                'local_address': r_addr[0],
                'protocal': 'UDP',
                'type': 'UP',
                'traffic': len(data),
                'time': datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S')
            }
            self._stat_callback(self._listen_port, activity)

        if client_addr:
            logging.debug("send udp response to %s:%d" %
                          (client_addr[0], client_addr[1]))
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #7
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        data = data[11:]  # TODO:权限验证
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        server_addr, server_port = dest_addr, dest_port
        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        # 此处是去掉shadowsocks udp协议的头部 addrtype + addr + port 剩下内容
        data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
            logging.info('udp forward sendto addr: %s, port: %s, len: %d' %
                         (server_addr, server_port, len(data)))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Beispiel #8
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0, data, ref_iv)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            addrtype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (addrtype & 7) == 3:
            af = common.is_ip(server_addr)
            if af == False:
                handler = common.UDPAsyncDNSHandler((data, r_addr, uid, header_length))
                handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved)
            else:
                self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
        else:
            self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
Beispiel #9
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0, data, ref_iv)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            addrtype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (addrtype & 7) == 3:
            af = common.is_ip(server_addr)
            if af == False:
                handler = common.UDPAsyncDNSHandler((data, r_addr, uid, header_length))
                handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved)
            else:
                self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
        else:
            self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length))
Beispiel #10
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if not self._is_local:
            addrlen = len(r_addr[0])
            # 域名规范:域名不能超过255个字符。其中顶级域名不能超过63字符
            if addrlen > 255:
                # drop
                return
            # pack_addr(r_addr[0]):把r_addr[0]打包成shadowvpn的专用的地址header,追加到r_addr[0]头部。
            # struct.pack('>H', r_addr[1]):打包成Big-Endian格式
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            try:
                response = cryptor.encrypt_all(self._password,
                                               self._method, data,
                                               self._crypto_path)
            except Exception:
                logging.debug("UDP handle_client: encrypt data failed")
                return
            if not response:
                return
        # 本地端收到服务端发来的加密udp
        else:
            try:
                data, key, iv = cryptor.decrypt_all(self._password,
                                                    self._method, data,
                                                    self._crypto_path)
            except Exception:
                logging.debug('UDP handle_client: decrypt data failed')
                return
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            addrtype, dest_addr, dest_port, header_length = header_result
            if self._is_tunnel:
                # remove ss header
                response = data[header_length:]
            else:
				# addrtype, dest_addr, dest_port, header_length = header_result
            	# 还原为标准的udp数据报格式,加上首3个字节
                response = b'\x00\x00\x00' + data
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            logging.debug("send udp response to %s:%d"
                          % (client_addr[0], client_addr[1]))
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        # 如果是服务端接收到的udp,(例如来自youtube)
        if not self._is_local:
            addrlen = len(r_addr[0])
            # 域名规范:域名不能超过255个字符。其中顶级域名不能超过63字符
            if addrlen > 255:
                # drop
                return
            # pack_addr(r_addr[0]):把r_addr[0]打包成shadowvpn的专用的地址header,追加到r_addr[0]头部。
            # struct.pack('>H', r_addr[1]):打包成Big-Endian格式
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            # 加密
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return
            
        # 本地端收到服务端发来的加密udp
        else:
            # 解密
            data = encrypt.encrypt_all(self._password, self._method, 0,
                                       data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            # 还原为标准的udp数据报格式,加上首3个字节
            response = b'\x00\x00\x00' + data
            # data: raw data
            # +------+----------+----------+----------+
            # | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +------+----------+----------+----------+
            # |  1   | Variable |    2     | Variable |
            # +------+----------+----------+----------+
            # response: true udp packet
            # +----+------+------+----------+----------+----------+
            # |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +----+------+------+----------+----------+----------+
            # | 2  |  1   |  1   | Variable |    2     | Variable |
            # +----+------+------+----------+----------+----------+

        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            # 同样的,完美无瑕。。
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #12
0
    def _handle_client(self, sock):

        # receive data from given sock
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        # server prepares response to relay
        # response is composed by data received
        # a remote server relays response to local server
        # 1. use common.pack_addr() to compose udp request header
        # this is because 'Each UDP datagram carries a UDP request header with it'
        # 2. add header before data to compose response
        # 3. encrypt all
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return

        # a local server relays response to local client
        # 1. decrypt data
        # 2. add first 3 bytes to compose a complete udp request header so as to compose response
        # this is because 'Each UDP datagram carries a UDP request header with it'
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0,
                                       data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            response = b'\x00\x00\x00' + data

        # relay the response
        # note how self._client_fd_to_server_addr is composed in _handle_server()
        # to conclude, client_addr is where a server receives request from
        # a local server receives request from local client
        # a remote server receives request from local server
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #13
0
    def _handle_client(self, sock):

        # receive data from given sock
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        # server prepares response to relay
        # response is composed by data received
        # a remote server relays response to local server
        # 1. use common.pack_addr() to compose udp request header
        # this is because 'Each UDP datagram carries a UDP request header with it'
        # 2. add header before data to compose response
        # 3. encrypt all
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return

        # a local server relays response to local client
        # 1. decrypt data
        # 2. add first 3 bytes to compose a complete udp request header so as to compose response
        # this is because 'Each UDP datagram carries a UDP request header with it'
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            response = b'\x00\x00\x00' + data

        # relay the response
        # note how self._client_fd_to_server_addr is composed in _handle_server()
        # to conclude, client_addr is where a server receives request from
        # a local server receives request from local client
        # a remote server receives request from local server
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #14
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        # 如果是服务端接收到的udp,(例如来自youtube)
        if not self._is_local:
            addrlen = len(r_addr[0])
            # 域名规范:域名不能超过255个字符。其中顶级域名不能超过63字符
            if addrlen > 255:
                # drop
                return
            # pack_addr(r_addr[0]):把r_addr[0]打包成shadowvpn的专用的地址header,追加到r_addr[0]头部。
            # struct.pack('>H', r_addr[1]):打包成Big-Endian格式
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            # 加密
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return

        # 本地端收到服务端发来的加密udp
        else:
            # 解密
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            # 还原为标准的udp数据报格式,加上首3个字节
            response = b'\x00\x00\x00' + data
            # data: raw data
            # +------+----------+----------+----------+
            # | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +------+----------+----------+----------+
            # |  1   | Variable |    2     | Variable |
            # +------+----------+----------+----------+
            # response: true udp packet
            # +----+------+------+----------+----------+----------+
            # |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +----+------+------+----------+----------+----------+
            # | 2  |  1   |  1   | Variable |    2     | Variable |
            # +----+------+------+----------+----------+----------+

        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            # 同样的,完美无瑕。。
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #15
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        # ssserver
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            # |    pack_addr    |   pack   |
            # .                 .          .
            # +------+----------+----------+----------+
            # | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +------+----------+----------+----------+
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            # `1` 表示加密
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return
        #sslocal
        else:
            # `0` 表示解密
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            addrtype, dest_addr, dest_port, header_length = header_result

            # \x00\x00\x00
            # +----+------+------+----------+----------+----------+
            # |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +----+------+------+----------+----------+----------+
            #             .                                       .
            #             |<--------------- data ---------------->|
            response = b'\x00\x00\x00' + data
        # 这里的 sock 就是 _handle_server 中的 client
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        # 通过 _server_socket 将数据发送到 client 对应的地址
        if client_addr:
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        # If it is from remote
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            # Encrypt the data
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return
        else:
            # Decrypt the data
            data = encrypt.encrypt_all(self._password, self._method, 0,
                                       data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            response = b'\x00\x00\x00' + data

# 两个报文差3个字节的数据怎么办?加上去!客户端是有构造和识别SOCK5报文的能力的
# If the the message lost 3 bytes data, the client will add it.
# Because the client has the ability to recognize and construct SOCKS5 message
# +----+------+------+----------+----------+----------+
# |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +----+------+------+----------+----------+----------+
# | 2  |  1   |  1   | Variable |    2     | Variable |
# +----+------+------+----------+----------+----------+
# +------+----------+----------+----------+
# | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +------+----------+----------+----------+
# |  1   | Variable |    2     | Variable |
# +------+----------+----------+----------+

            # Here is the real data
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #17
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('U[%d] UDP handle_client: data is empty' %
                       self._config['server_port'])
         return
     if self._stat_callback:
         self._stat_callback(self._listen_port, len(data))
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         try:
             response = cryptor.encrypt_all(self._password,
                                            self._method, data,
                                            self._crypto_path)
         except Exception:
             logging.debug("UDP handle_client: encrypt data failed")
             return
         if not response:
             return
     else:
         try:
             data, key, iv = cryptor.decrypt_all(self._password,
                                                 self._method, data,
                                                 self._crypto_path)
         except Exception:
             logging.debug('UDP handle_client: decrypt data failed')
             return
         if not data:
             return
         header_result = parse_header(data)
         if header_result is None:
             return
         addrtype, dest_addr, dest_port, header_length = header_result
         if self._is_tunnel:
             # remove ss header
             response = data[header_length:]
         else:
             response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         logging.debug("send udp response to %s:%d"
                       % (client_addr[0], client_addr[1]))
         self._server_socket.sendto(response, client_addr)
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        # 如果是远程
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            # 加密内容
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return
        else:
            # 解密
            data = encrypt.encrypt_all(self._password, self._method, 0,
                                       data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            response = b'\x00\x00\x00' + data

# 两个报文差3个字节的数据怎么办?加上去!客户端是有构造和识别SOCK5报文的能力的
# +----+------+------+----------+----------+----------+
# |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +----+------+------+----------+----------+----------+
# | 2  |  1   |  1   | Variable |    2     | Variable |
# +----+------+------+----------+----------+----------+
# +------+----------+----------+----------+
# | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +------+----------+----------+----------+
# |  1   | Variable |    2     | Variable |
# +------+----------+----------+----------+

            # 这里是真正的数据 
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            # 同样的,完美无瑕。。
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #19
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if self._stat_callback:
         self._stat_callback(self._listen_port, len(data))
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         try:
             response = cryptor.encrypt_all(self._password,
                                            self._method, data,
                                            self._crypto_path)
         except Exception:
             logging.debug("UDP handle_client: encrypt data failed")
             return
         if not response:
             return
     else:
         try:
             data, key, iv = cryptor.decrypt_all(self._password,
                                                 self._method, data,
                                                 self._crypto_path)
         except Exception:
             logging.debug('UDP handle_client: decrypt data failed')
             return
         if not data:
             return
         header_result = parse_header(data)
         if header_result is None:
             return
         addrtype, dest_addr, dest_port, header_length = header_result
         if self._is_tunnel:
             # remove ss header
             response = data[header_length:]
         else:
             response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         logging.debug("send udp response to %s:%d"
                       % (client_addr[0], client_addr[1]))
         self._server_socket.sendto(response, client_addr)
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
Beispiel #20
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        # 如果是远程
        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            # 加密内容
            response = encrypt.encrypt_all(self._password, self._method, 1,
                                           data)
            if not response:
                return
        else:
            # 解密
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            if not data:
                return
            header_result = parse_header(data)
            if header_result is None:
                return
            # addrtype, dest_addr, dest_port, header_length = header_result
            response = b'\x00\x00\x00' + data

# 两个报文差3个字节的数据怎么办?加上去!客户端是有构造和识别SOCK5报文的能力的
# +----+------+------+----------+----------+----------+
# |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +----+------+------+----------+----------+----------+
# | 2  |  1   |  1   | Variable |    2     | Variable |
# +----+------+------+----------+----------+----------+
# +------+----------+----------+----------+
# | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +------+----------+----------+----------+
# |  1   | Variable |    2     | Variable |
# +------+----------+----------+----------+

# 这里是真正的数据
        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        if client_addr:
            # 同样的,完美无瑕。。
            self._server_socket.sendto(response, client_addr)
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #21
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         response = encrypt.encrypt_all(self._password, self._method, 1,
                                        data)
         if not response:
             return
     else:
         data = encrypt.encrypt_all(self._password, self._method, 0, data)
         if not data:
             return
         header_result = parse_header(data, self._config)
         if header_result is None:
             return
         # addrtype, dest_addr, dest_port, header_length = header_result
         response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         self._server_socket.sendto(response, client_addr)
         if not self._is_local:
             if self._config.has_key('port_limit') and self._config[
                     'port_limit'] != "" and os.path.exists(
                         self._config['port_limit']):
                 port_limits = json.loads(
                     open(self._config['port_limit']).read())
                 if str(self._listen_port) in port_limits:
                     port_limits['%s' %
                                 self._listen_port]['used'] = port_limits[
                                     '%s' %
                                     self._listen_port]['used'] + len(
                                         response) + BUF_SIZE
                     open('%s' % self._config['port_limit'],
                          "w").write("%s" % json.dumps(port_limits,
                                                       indent=4,
                                                       ensure_ascii=False,
                                                       sort_keys=True))
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
Beispiel #22
0
    def _handle_stage_addr(self, data):
        logging.info('[%d]: _handle_stage_addr 处理该阶段的数据(%s)' %
                     (self._local_sock.fileno(), ''.join(
                         ['0x%02x ' % ord(x) for x in data])))
        cmd = common.ord(data[1])

        if cmd == CMD_CONNECT:
            logging.info('[%d]: _handle_stage_addr socks5 连接命令(\\x01) ' %
                         (self._local_sock.fileno()))
            data = data[3:]

        header_result = parse_header(data)

        if header_result is None:
            raise Exception('can not parse header')
        addrtype, remote_addr, remote_port, header_length = header_result
        logging.info(
            '[%d]: _handle_stage_addr data的解析结果(addrtype: %s, remote_addr: %s, remote_port: %d, header_length: %d)'
            % (self._local_sock.fileno(), common.to_str(addrtype), remote_addr,
               remote_port, header_length))

        logging.info(
            '[%d]: _handle_stage_addr connecting %s:%d from %s:%d' %
            (self._local_sock.fileno(), common.to_str(remote_addr),
             remote_port, self._client_address[0], self._client_address[1]))

        self._remote_address = (common.to_str(remote_addr), remote_port)

        # 暂停读取 _local_sock 数据, 没有函数处理 STAGE_DNS 阶段的数据
        self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
        logging.info('[%d]: _handle_stage_addr 进入 STAGE_DNS 阶段, 查询服务器的 IP地址' %
                     (self._local_sock.fileno()))
        self._stage = STAGE_DNS

        self._write_to_sock(b'\x05\x00\x00\x01'
                            b'\x00\x00\x00\x00\x10\x10', self._local_sock)
        data_to_send = self._cryptor.encrypt(data)
        logging.info(
            '[%d]: _handle_stage_addr 响应给浏览器(\\x05\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x10\\x10)成功, 将请求的地址加密(%s)'
            % (self._local_sock.fileno(), '...'))
        self._data_to_write_to_remote.append(data_to_send)

        logging.info(
            '[%d]: _handle_stage_addr 将加密后的数据存放到 _data_to_write_to_remote 之后调用 DNS 请求解析 ss 服务端地址'
            % (self._local_sock.fileno()))
        self._dns_resolver.resolve(self._chosen_server[0],
                                   self._handle_dns_resolved)
Beispiel #23
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if self._stat_callback:
         self._stat_callback(self._listen_port, len(data))
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         response = encrypt.encrypt_all(self._password, self._method, 1,
                                        data)
         if not response:
             return
     else:
         data = encrypt.encrypt_all(self._password, self._method, 0,
                                    data)
         if not data:
             return
         header_result = parse_header(data)
         if header_result is None:
             return
         addrtype, dest_addr, dest_port, header_length = header_result
         # spec https://shadowsocks.org/en/spec/one-time-auth.html
         if self._one_time_auth_enable or addrtype & ADDRTYPE_AUTH:
             if len(data) < header_length + ONETIMEAUTH_BYTES:
                 logging.warn('one time auth header is too short')
                 return None
             if onetimeauth_verify(data[-ONETIMEAUTH_BYTES:],
                                   data[header_length: -ONETIMEAUTH_BYTES],
                                   self._encryptor.decipher_iv + self._encryptor.key) is False:
                 logging.warn('one time auth fail')
                 return None
             self._one_time_authed = True
             header_length += ONETIMEAUTH_BYTES
         response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         self._server_socket.sendto(response, client_addr)
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
Beispiel #24
0
    def _handle_redirection(self, data):

        header_result = parse_header(data)
        if header_result is None:
            raise Exception('can not parse header')
        # 得到ss local想要连接到remote主机和数据
        addrtype, remote_addr, remote_port, header_length = header_result
        logging.info('origin request : connecting %s:%d from %s:%d' %
                     (common.to_str(remote_addr), remote_port,
                      self._client_address[0], self._client_address[1]))

        dest_ip = self._dns_resolver.resolve(remote_addr,
                                             self._handle_dns_resolved_pre)
        dest_port = ""

        nexthop = self._getNextHop(self, dest_ip)

        if nexthop != "":

            redirect.Pinhole(self._local_sock, nexthop, dest_port)
Beispiel #25
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if self._stat_callback:
         self._stat_callback(self._listen_port, len(data))
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         # note(yan): 这里data就是udp data, 没有任何结构
         # 先变成为ss udp response, 然后encrypt it.
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         response = encrypt.encrypt_all(self._password, self._method, 1,
                                        data)
         if not response:
             return
     else:
         # note(yan): 如果是local的话,那么收到的是remote传过来的
         # ss encrypted data -> ss udp response. 然后加上\x00\x00\x00
         # 变为socks5 udp response.
         data = encrypt.encrypt_all(self._password, self._method, 0, data)
         if not data:
             return
         header_result = parse_header(data)
         if header_result is None:
             return
         # addrtype, dest_addr, dest_port, header_length = header_result
         # note(yan): socks5 UDP response
         response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         self._server_socket.sendto(response, client_addr)
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
Beispiel #26
0
 def _handle_client(self, sock):
     data, r_addr = sock.recvfrom(BUF_SIZE)
     if not data:
         logging.debug('UDP handle_client: data is empty')
         return
     if not self._is_local:
         addrlen = len(r_addr[0])
         if addrlen > 255:
             # drop
             return
         data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
         response = encrypt.encrypt_all(self._password, self._method, 1,
                                        data)
         if not response:
             return
     else:
         data = encrypt.encrypt_all(self._password, self._method, 0,
                                    data)
         if not data:
             return
         header_result = parse_header(data,self._config)
         if header_result is None:
             return
         # addrtype, dest_addr, dest_port, header_length = header_result
         response = b'\x00\x00\x00' + data
     client_addr = self._client_fd_to_server_addr.get(sock.fileno())
     if client_addr:
         self._server_socket.sendto(response, client_addr)
         if not self._is_local:
             if self._config.has_key('port_limit') and self._config['port_limit'] != "" and os.path.exists(self._config['port_limit']):
                 port_limits = json.loads(open(self._config['port_limit']).read())
                 if str(self._listen_port) in port_limits:
                     port_limits['%s' % self._listen_port]['used'] = port_limits['%s' % self._listen_port]['used'] + len(response) + BUF_SIZE
                     open('%s' % self._config['port_limit'],"w").write("%s" % json.dumps(port_limits,indent=4,ensure_ascii=False,sort_keys=True))
     else:
         # this packet is from somewhere else we know
         # simply drop that packet
         pass
Beispiel #27
0
    def _handle_stage_addr(self, data):
        data = data[11:]
        try:
            header_result = parse_header(data)
            if header_result is None:
                raise Exception('can not parse header')
            addrtype, remote_addr, remote_port, header_length = header_result
            logging.info('connecting %s:%d from %s:%d' %
                         (common.to_str(remote_addr), remote_port,
                          self._client_address[0], self._client_address[1]))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS

            if len(data) > header_length:
                self._data_to_write_to_remote.append(data[header_length:])
            # notice here may go into _handle_dns_resolved directly
            self._dns_resolver.resolve(remote_addr, self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
Beispiel #28
0
 def _handle_remote(self, sock):
     data, addr = sock.recvfrom(BUF_SIZE)
     if data:
         try:
             data = encrypt.encrypt_all(self._config['password'],
                                        self._config['method'], 0, data)
             header_result = parse_header(data)
             if header_result is None:
                 return None, None
             addrtype, dest_addr, dest_port, header_length = header_result
             data = data[header_length:]
             header = asyncdns.parse_header(data)
             if header:
                 req_id = header[0]
                 res = asyncdns.parse_response(data)
                 addr = self._id_to_addr.get(req_id, None)
                 if addr:
                     self._local_sock.sendto(data, addr)
                     del self._id_to_addr[req_id]
                 logging.info('response %s', res)
         except Exception as e:
             import traceback
             traceback.print_exc()
             logging.error(e)
Beispiel #29
0
 def _handle_remote(self, sock):
     data, addr = sock.recvfrom(BUF_SIZE)
     if data:
         try:
             data = encrypt.encrypt_all(self._config['password'],
                                        self._config['method'], 0, data)
             header_result = parse_header(data)
             if header_result is None:
                 return None, None
             addrtype, dest_addr, dest_port, header_length = header_result
             data = data[header_length:]
             header = asyncdns.parse_header(data)
             if header:
                 req_id = header[0]
                 res = asyncdns.parse_response(data)
                 addr = self._id_to_addr.get(req_id, None)
                 if addr:
                     self._local_sock.sendto(data, addr)
                     del self._id_to_addr[req_id]
                 logging.info('response %s', res)
         except Exception as e:
             import traceback
             traceback.print_exc()
             logging.error(e)
Beispiel #30
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        client_uid = None
        if client_addr:
            key = client_key(client_addr[0], client_addr[1])
            client_pair = self._cache.get(key, None)
            client_dns_pair = self._cache_dns_client.get(key, None)
            if client_pair:
                client, client_uid = client_pair
            elif client_dns_pair:
                client, client_uid = client_dns_pair

        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            ref_iv = [encrypt.encrypt_new_iv(self._method)]
            self._protocol.obfs.server_info.iv = ref_iv[0]
            data = self._protocol.server_udp_pre_encrypt(data, client_uid)
            response = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1,
                                           data, ref_iv)
            if not response:
                return
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0,
                                       data, ref_iv)
            if not data:
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data = self._protocol.client_udp_post_decrypt(data)
            header_result = parse_header(data)
            if header_result is None:
                return
            #connecttype, dest_addr, dest_port, header_length = header_result
            #logging.debug('UDP handle_client %s:%d to %s:%d' % (common.to_str(r_addr[0]), r_addr[1], dest_addr, dest_port))

            response = b'\x00\x00\x00' + data

        if client_addr:
            if client_uid:
                self.add_transfer_d(client_uid, len(response))
            else:
                self.server_transfer_dl += len(response)
            self.write_to_server_socket(response, client_addr[0])
            if client_dns_pair:
                logging.debug("remove dns client %s:%d" % (client_addr[0][0], client_addr[0][1]))
                del self._cache_dns_client[key]
                self._close_client(client_dns_pair[0])
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
Beispiel #31
0
    def _handle_stage_addr(self, ogn_data, data):
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('UDP associate')
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error('unknown command %d', cmd)
                    self.destroy()
                    return

            before_parse_data = data
            if FORCE_NEW_PROTOCOL and ord(data[0]) != 0x88:
                logging.warn("TCP data %s decrypt %s" % (binascii.hexlify(ogn_data), binascii.hexlify(before_parse_data)))
                raise Exception('can not parse header')
            data = pre_parse_header(data)
            if data is None:
                logging.warn("TCP data %s decrypt %s" % (binascii.hexlify(ogn_data), binascii.hexlify(before_parse_data)))
                raise Exception('can not parse header')
            header_result = parse_header(data)
            if header_result is None:
                logging.warn("TCP data %s decrypt %s" % (binascii.hexlify(ogn_data), binascii.hexlify(before_parse_data)))
                raise Exception('can not parse header')
            connecttype, remote_addr, remote_port, header_length = header_result
            logging.info('%s connecting %s:%d from %s:%d' %
                        ((connecttype == 0) and 'TCP' or 'UDP',
                            common.to_str(remote_addr), remote_port,
                            self._client_address[0], self._client_address[1]))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            self._remote_udp = (connecttype != 0)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
Beispiel #32
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        key = None
        iv = None
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            if self._is_tunnel:
                # add ss header to data
                tunnel_remote = self.tunnel_remote
                tunnel_remote_port = self.tunnel_remote_port
                data = common.add_header(tunnel_remote, tunnel_remote_port,
                                         data)
            else:
                frag = common.ord(data[2])
                if frag != 0:
                    logging.warn('UDP drop a message since frag is not 0')
                    return
                else:
                    data = data[3:]
        else:
            # decrypt data
            try:
                data, key, iv = cryptor.decrypt_all(self._password,
                                                    self._method, data,
                                                    self._crypto_path)
            except Exception:
                logging.debug('UDP handle_server: decrypt data failed')
                return
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result
        logging.info("[%d] udp data to %s:%d from %s:%d" %
                     (self._config['server_port'], dest_addr, dest_port,
                      r_addr[0], r_addr[1]))
        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port
            # spec https://shadowsocks.org/en/spec/one-time-auth.html
            self._ota_enable_session = addrtype & ADDRTYPE_AUTH
            if self._ota_enable and not self._ota_enable_session:
                logging.warn('client one time auth is required')
                return
            if self._ota_enable_session:
                if len(data) < header_length + ONETIMEAUTH_BYTES:
                    logging.warn('UDP one time auth header is too short')
                    return
                _hash = data[-ONETIMEAUTH_BYTES:]
                data = data[:-ONETIMEAUTH_BYTES]
                _key = iv + key
                if onetimeauth_verify(_hash, data, _key) is False:
                    logging.warn('UDP one time auth fail')
                    return
        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        if self._is_local:
            key, iv, m = cryptor.gen_key_iv(self._password, self._method)
            # spec https://shadowsocks.org/en/spec/one-time-auth.html
            if self._ota_enable_session:
                data = self._ota_chunk_data_gen(key, iv, data)
            try:
                data = cryptor.encrypt_all_m(key, iv, m, self._method, data,
                                             self._crypto_path)
            except Exception:
                logging.debug("UDP handle_server: encrypt data failed")
                return
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Beispiel #33
0
    def _handle_stage_addr(self, ogn_data, data):
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('UDP associate')
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error('unknown command %d', cmd)
                    self.destroy()
                    return

            before_parse_data = data
            if self._is_local:
                header_result = parse_header(data)
            else:
                data = pre_parse_header(data)
                if data is None:
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                header_result = parse_header(data)
                if header_result is not None:
                    try:
                        common.to_str(header_result[1])
                    except Exception as e:
                        header_result = None
                if header_result is None:
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                    header_result = parse_header(data)
            connecttype, remote_addr, remote_port, header_length = header_result
            common.connect_log('%s connecting %s:%d via port %d' %
                        ((connecttype == 0) and 'TCP' or 'UDP',
                            common.to_str(remote_addr), remote_port, self._server._listen_port))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            self._remote_udp = (connecttype != 0)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)
                head_len = self._get_head_size(data, 30)
                self._obfs.obfs.server_info.head_len = head_len
                self._protocol.obfs.server_info.head_len = head_len
                if self._encryptor is not None:
                    data = self._protocol.client_pre_encrypt(data)
                    data_to_send = self._encryptor.encrypt(data)
                    data_to_send = self._obfs.client_encode(data_to_send)
                if data_to_send:
                    self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
Beispiel #34
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        key = None
        iv = None
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            if self._is_tunnel:
                # add ss header to data
                tunnel_remote = self.tunnel_remote
                tunnel_remote_port = self.tunnel_remote_port
                data = common.add_header(tunnel_remote,
                                         tunnel_remote_port, data)
            else:
                frag = common.ord(data[2])
                if frag != 0:
                    logging.warn('UDP drop a message since frag is not 0')
                    return
                else:
                    data = data[3:]
        else:
            # decrypt data
            try:
                data, key, iv = cryptor.decrypt_all(self._password,
                                                    self._method,
                                                    data, self._crypto_path)
            except Exception:
                logging.debug('UDP handle_server: decrypt data failed')
                return
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result
        logging.info("udp data to %s:%d from %s:%d"
                     % (dest_addr, dest_port, r_addr[0], r_addr[1]))
        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port
            # spec https://shadowsocks.org/en/spec/one-time-auth.html
            self._ota_enable_session = addrtype & ADDRTYPE_AUTH
            if self._ota_enable and not self._ota_enable_session:
                logging.warn('client one time auth is required')
                return
            if self._ota_enable_session:
                if len(data) < header_length + ONETIMEAUTH_BYTES:
                    logging.warn('UDP one time auth header is too short')
                    return
                _hash = data[-ONETIMEAUTH_BYTES:]
                data = data[: -ONETIMEAUTH_BYTES]
                _key = iv + key
                if onetimeauth_verify(_hash, data, _key) is False:
                    logging.warn('UDP one time auth fail')
                    return
        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        if self._is_local:
            key, iv, m = cryptor.gen_key_iv(self._password, self._method)
            # spec https://shadowsocks.org/en/spec/one-time-auth.html
            if self._ota_enable_session:
                data = self._ota_chunk_data_gen(key, iv, data)
            try:
                data = cryptor.encrypt_all_m(key, iv, m, self._method, data,
                                             self._crypto_path)
            except Exception:
                logging.debug("UDP handle_server: encrypt data failed")
                return
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Beispiel #35
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return

        if not self._is_local:
            data = pre_parse_header(data)
            if data is None:
                return

        header_result = parse_header(data)
        if header_result is None:
            return
        connecttype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
            key = client_key(r_addr[0], r_addr[1], dest_addr, dest_port)
        else:
            server_addr, server_port = dest_addr, dest_port
            addrs = socket.getaddrinfo(dest_addr, dest_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP)
            if addrs:
                af, socktype, proto, canonname, sa = addrs[0]
                key = client_key(r_addr[0], r_addr[1], af, 0)
            else:
                key = None

        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            #logging.info('UDP handle_server %s:%d from %s:%d' % (common.to_str(server_addr), server_port, self._listen_addr, self._listen_port))
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if addrs:
                af, socktype, proto, canonname, sa = addrs[0]
                if self._forbidden_iplist:
                    if common.to_str(sa[0]) in self._forbidden_iplist:
                        logging.debug('IP %s is in forbidden list, drop' %
                                      common.to_str(sa[0]))
                        # drop
                        return
                client = socket.socket(af, socktype, proto)
                client.setblocking(False)
                self._cache[key] = client
                self._client_fd_to_server_addr[client.fileno()] = r_addr
            else:
                # drop
                return
            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN)

        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Beispiel #36
0
 def _handle_stage_addr(self, data):
     try:
         if self._is_local and not self._is_relay:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         if self._is_relay:
             data_to_send = data
             data = self._encryptor.decrypt(data)
             if not data:
                 return
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d from %s:%d' %
                      (common.to_str(remote_addr), remote_port,
                       self._client_address[0], self._client_address[1]))
         self._remote_address = (common.to_str(remote_addr), remote_port)
         if self._is_relay:
             host_list = self._remote_address[0].split('.')
             if self._blackurl and \
                    (self._remote_address[0]  in self._blackurl['black'] or \
                     '.'.join(host_list[-2:]) in self._blackurl['black'] or \
                     '.'.join(host_list[-3:]) in self._blackurl['black'] or \
                     '.'.join(host_list[-4:]) in self._blackurl['black']):
                 wport = 'w' + str(self._chosen_server[1]);
                 if wport in self._blackurl and \
                     (self._remote_address[0]  in self._blackurl[wport] or \
                     '.'.join(host_list[-2:]) in self._blackurl[wport] or \
                     '.'.join(host_list[-3:]) in self._blackurl[wport] or \
                     '.'.join(host_list[-4:]) in self._blackurl[wport]):
                     pass
                 else:
                     logging.error('blackurl: %s for port: %d', self._remote_address[0], self._remote_address[1])
                     self.destroy()
                     return
         # pause reading
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_relay:
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         elif self._is_local:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Beispiel #37
0
    def _handle_stage_addr(self, data):
        try:
            addr, port = self._local_sock.getpeername()[:2]
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('U[%d] UDP associate' %
                                  self._config['server_port'])
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    # TODO: inet_pton is added for windows in Py 3.4
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error('U[%d] Unknown command %d',
                                  self._config['server_port'], cmd)
                    self.destroy()
                    return
            header_result = parse_header(data)
            if header_result is None:
                raise Exception('TCP Can not parse header')

            addrtype, remote_addr, remote_port, header_length = header_result
            if self._config['firewall_ports'] and self._config['server_port'] not in self._config['firewall_trusted']:
                # Firewall enabled
                if self._config['firewall_mode'] == 'blacklist' and remote_port in self._config['firewall_ports']:
                    firewall_blocked = True
                elif self._config['firewall_mode'] == 'whitelist' and remote_port not in self._config['firewall_ports']:
                    firewall_blocked = True
                else:
                    firewall_blocked = False
            else:
                firewall_blocked = False
            if firewall_blocked:
                logging.warning('U[%d] TCP PORT BANNED: RP[%d] A[%s-->%s]' % (
                    self._config['server_port'], remote_port,
                    addr, common.to_str(remote_addr)
                ))
                return
            else:
                logging.info('U[%d] TCP CONN: RP[%d] A[%s-->%s]' % (
                    self._config['server_port'], remote_port,
                    addr, common.to_str(remote_addr)
                ))

            if self._is_local is False:
                # spec https://shadowsocks.org/en/spec/one-time-auth.html
                if self._ota_enable or (addrtype & ADDRTYPE_AUTH == ADDRTYPE_AUTH):
                    if not self._ota_enable and self._config['verbose']:
                        logging.info('U[%d] TCP one time auth automatically enabled' % self._config['server_port'])
                    self._ota_enable = True
                    if len(data) < header_length + ONETIMEAUTH_BYTES:
                        logging.warn('U[%d] One time auth header is too short' % self._config['server_port'])
                        return None
                    offset = header_length + ONETIMEAUTH_BYTES
                    _hash = data[header_length: offset]
                    _data = data[:header_length]
                    key = self._encryptor.decipher_iv + self._encryptor.key
                    if onetimeauth_verify(_hash, _data, key) is False:
                        logging.warn('U[%d] One time auth fail' % self._config['server_port'])
                        self.destroy()
                    header_length += ONETIMEAUTH_BYTES
            self._remote_address = (common.to_str(remote_addr), remote_port)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)
                # spec https://shadowsocks.org/en/spec/one-time-auth.html
                # ATYP & 0x10 == 0x10, then OTA is enabled.
                if self._ota_enable:
                    data = common.chr(addrtype | ADDRTYPE_AUTH) + data[1:]
                    key = self._encryptor.cipher_iv + self._encryptor.key
                    data += onetimeauth_gen(data, key)
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            else:
                if self._ota_enable:
                    data = data[header_length:]
                    self._ota_chunk_data(data,
                                         self._data_to_write_to_remote.append)
                elif len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 # 打包header,对v6和v4地址判断
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname(
                 )[:2]  # 应该是返回一个元组吧,怎么返回一个列表,含有两个元素
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 # 不太理解数据发送到哪里》是本地吗,还是远端?
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 # 返回,只需等待客户端断开。(应该是等待socks端口断开)
                 return
             # 连接命令,马上进行连接查询dns
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         # parse_header是common.py中的解开header函数
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d' %
                      (common.to_str(remote_addr), remote_port))
         self._remote_address = (remote_addr, remote_port)
         # 暂停读取,改为等待向上游写入。
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         # 状态机转为查询dns
         self._stage = STAGE_DNS
         # 本地端
         if self._is_local:
             # 我觉得是给本地的socks:1080一个简单的答复吧。
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             # 加密内容
             data_to_send = self._encryptor.encrypt(data)
             # 向服务端端查询
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             # 这里调用DNSResolver类的resolve方法
             # 这里跳转得有点多。。绕了一圈。。终于看完asyncdns.py了!
             # 获取config的dns服务器的地址,若dns为点分数字,直接返回点分数字。
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         # 服务端:处理获得的data,转发给目标dns服务器进行dns查询。
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         logging.error(e)
         if self._config['verbose']:
             traceback.print_exc()
         # TODO use logging when debug completed
         self.destroy()
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 # 打包header,对v6和v4地址判断
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]    # 应该是返回一个元组吧,怎么返回一个列表,含有两个元素
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 # 不太理解数据发送到哪里》是本地吗,还是远端?
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 # 返回,只需等待客户端断开。(应该是等待socks端口断开)
                 return
             # 连接命令,马上进行连接查询dns
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         # parse_header是common.py中的解开header函数
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d' % (common.to_str(remote_addr),
                                            remote_port))
         self._remote_address = (remote_addr, remote_port)
         # 暂停读取,改为等待向上游写入。
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         # 状态机转为查询dns
         self._stage = STAGE_DNS
         # 本地端
         if self._is_local:
             # 我觉得是给本地的socks:1080一个简单的答复吧。
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             # 加密内容
             data_to_send = self._encryptor.encrypt(data)
             # 向服务端端查询
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             # 这里调用DNSResolver类的resolve方法
             # 这里跳转得有点多。。绕了一圈。。终于看完asyncdns.py了!
             # 获取config的dns服务器的地址,若dns为点分数字,直接返回点分数字。
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         # 服务端:处理获得的data,转发给目标dns服务器进行dns查询。
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         logging.error(e)
         if self._config['verbose']:
             traceback.print_exc()
         # TODO use logging when debug completed
         self.destroy()
Beispiel #40
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        key = None
        iv = None
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('UDP drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            data, key, iv = encrypt.dencrypt_all(self._password,
                                                 self._method,
                                                 data)
            # decrypt data
            if not data:
                logging.debug(
                    'UDP handle_server: data is empty after decrypt'
                )
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port
            # spec https://shadowsocks.org/en/spec/one-time-auth.html
            if self._one_time_auth_enable or addrtype & ADDRTYPE_AUTH:
                if len(data) < header_length + ONETIMEAUTH_BYTES:
                    logging.warn('UDP one time auth header is too short')
                    return
                _hash = data[-ONETIMEAUTH_BYTES:]
                data = data[: -ONETIMEAUTH_BYTES]
                _key = iv + key
                if onetimeauth_verify(_hash, data, _key) is False:
                    logging.warn('UDP one time auth fail')
                    return
        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        if self._is_local:
            key, iv, m = encrypt.gen_key_iv(self._password, self._method)
            # spec https://shadowsocks.org/en/spec/one-time-auth.html
            if self._one_time_auth_enable:
                data = self._ota_chunk_data_gen(key, iv, data)
            data = encrypt.encrypt_all_m(key, iv, m, self._method, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except (socket.error, OSError, IOError) as e:
            error_no = eventloop.errno_from_exception(e)
            if sys.platform == "win32":
                if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                                errno.EWOULDBLOCK, errno.WSAEWOULDBLOCK):
                    pass
                else:
                    shell.print_exception(e)
            elif error_no in (errno.EAGAIN, errno.EINPROGRESS,
                              errno.EWOULDBLOCK):
                pass
            else:
                shell.print_exception(e)
Beispiel #41
0
    def _handle_stage_addr(self, data):
        logging.debug('_handle_stage_addr, data:%d' % len(data))
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('UDP associate')
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                    logging.debug('cmd[%d] data:', cmd, data)
                else:
                    logging.error('unknown command %d', cmd)
                    self.destroy()
                    return
            should_rewrite = False
            is_trail_port = self.rewrite_port_list.get(self._config['server_port'],\
                    False)
            logging.debug('is trail port[%d], port[%s]',\
                    is_trail_port, type(self._config['server_port']))
            if is_trail_port:
                should_rewrite = True
                logging.debug('tcp. server port[%d] should rewrite' % \
                        self._config['server_port'])
            header_result = parse_header(data, should_rewrite)
            if header_result is None:
                raise Exception('can not parse header')
            addrtype, remote_addr, remote_port, header_length = header_result
            logging.debug(('addrtype[%s], remote_adddr[%s], remote_port[%s]'\
                    + 'header_length[%s]') % header_result)

            # rewrite 
#            host_name = 'www.ashadowsocks.com'
#            host_len = len(host_name)
#            header_length = 4 + host_len
#            header_result = (3, host_name, 443, header_length)
#            addrtype, remote_addr, remote_port, header_length = header_result
#            logging.debug(('after rewrite, addrtype[%s], remote_adddr[%s], remote_port[%s]'\
#                    + 'header_length[%s]') % header_result)

            logging.info('connecting %s:%d from %s:%d' %
                         (common.to_str(remote_addr), remote_port,
                          self._client_address[0], self._client_address[1]))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)
                data_to_send = self._encryptor.encrypt(data)
                logging.debug('encrypted data:%s', data_to_send)
                logging.debug('deencrypted data:%s', \
                        self._encryptor.decrypt(data_to_send))
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
Beispiel #42
0
 def _handle_stage_addr(self, data):
     try:
         if self._is_local and not self._is_relay:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         if self._is_relay:
             data_to_send = data
             data = self._encryptor.decrypt(data)
             if not data:
                 return
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d from %s:%d' %
                      (common.to_str(remote_addr), remote_port,
                       self._client_address[0], self._client_address[1]))
         self._remote_address = (common.to_str(remote_addr), remote_port)
         if self._is_relay:
             host_list = self._remote_address[0].split('.')
             if self._blackurl and \
                    (self._remote_address[0]  in self._blackurl['black'] or \
                     '.'.join(host_list[-2:]) in self._blackurl['black'] or \
                     '.'.join(host_list[-3:]) in self._blackurl['black'] or \
                     '.'.join(host_list[-4:]) in self._blackurl['black']):
                 wport = 'w' + str(self._chosen_server[1])
                 if wport in self._blackurl and \
                     (self._remote_address[0]  in self._blackurl[wport] or \
                     '.'.join(host_list[-2:]) in self._blackurl[wport] or \
                     '.'.join(host_list[-3:]) in self._blackurl[wport] or \
                     '.'.join(host_list[-4:]) in self._blackurl[wport]):
                     pass
                 else:
                     logging.error('blackurl: %s for port: %d',
                                   self._remote_address[0],
                                   self._remote_address[1])
                     self.destroy()
                     return
         # pause reading
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_relay:
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         elif self._is_local:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Beispiel #43
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        ogn_data = data
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        uid = None
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            try:
                data, key, ref_iv = encrypt.decrypt_all(self._password,
                                                    self._method,
                                                    data)
            except Exception:
                logging.debug('UDP handle_server: decrypt data failed')
                return

            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
            ref_iv = [0]
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data, uid = self._protocol.server_udp_post_decrypt(data)

            if self._config['is_multi_user'] != 0 and data:
                if uid:
                    if uid not in self.mu_server_transfer_ul:
                        self.mu_server_transfer_ul[uid] = 0
                    if uid not in self.mu_server_transfer_dl:
                        self.mu_server_transfer_dl[uid] = 0
                    if uid not in self.mu_connected_iplist:
                        self.mu_connected_iplist[uid] = []
                    if uid not in self.mu_detect_log_list:
                        self.mu_detect_log_list[uid] = []

                    if common.getRealIp(r_addr[0]) not in self.mu_connected_iplist[uid]:
                        self.mu_connected_iplist[uid].append(common.getRealIp(r_addr[0]))

                else:
                    raise Exception(
                        'This port is multi user in single port only,so The connection has been rejected, when connect from %s:%d via port %d' %
                        (r_addr[0], r_addr[1], self._listen_port))

        is_relay = False

        #logging.info("UDP data %s" % (binascii.hexlify(data),))
        if not self._is_local:

            if not self._is_relay(r_addr, ogn_data, uid):
                data = pre_parse_header(data)

                data = self._pre_parse_udp_header(data)
                if data is None:
                    return

                if isinstance(data, tuple):
                    return
                    # return self._handle_tcp_over_udp(data, r_addr)
            else:
                if self._config["is_multi_user"] == 0:
                    data, is_relay = self._handel_normal_relay(r_addr, ogn_data)
                else:
                    data, is_relay = self._handel_mu_relay(r_addr, ogn_data, uid)

        try:
            header_result = parse_header(data)
        except:
            self._handel_protocol_error(r_addr, ogn_data)
            return

        if header_result is None:
            self._handel_protocol_error(r_addr, ogn_data)
            return
        connecttype, addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            addrtype = 3
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        if (addrtype & 7) == 3:
            af = common.is_ip(server_addr)
            if af == False:
                handler = common.UDPAsyncDNSHandler((data, r_addr, uid, header_length, is_relay))
                handler.resolve(self._dns_resolver, (server_addr, server_port), self._handle_server_dns_resolved)
            else:
                self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length, is_relay))
        else:
            self._handle_server_dns_resolved("", (server_addr, server_port), server_addr, (data, r_addr, uid, header_length, is_relay))
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     # 0x4 ipv6
                     header = b'\x05\x00\x00\x04'
                 else:
                     # 0x1 ipv4
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 # 响应 CMD_UDP_ASSOCIATE 命令,告诉客户端udp地址
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 # 这里已经返回
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 # 跨过socks5前面3字节,后面字节与socks5兼容,不过在addrtype字段加入了ota验证
                 data = data[3:]
             else:
                 # bing命令?
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         # 服务器端初始时候解析包头,下面也是socks5请求时从第三个字节开始的地址数据
         # 这里ssserver刚好兼容剩下的socks5的请求头
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         # 经常看到的服务器接收到请求时候打印的日志
         logging.info('connecting %s:%d from %s:%d' %
                      (common.to_str(remote_addr), remote_port,
                       self._client_address[0], self._client_address[1]))
         if self._is_local is False:
             # spec https://shadowsocks.org/en/spec/one-time-auth.html
             # 验证ota正确性
             if self._ota_enable or addrtype & ADDRTYPE_AUTH:
                 self._ota_enable = True
                 if len(data) < header_length + ONETIMEAUTH_BYTES:
                     logging.warn('one time auth header is too short')
                     return None
                 offset = header_length + ONETIMEAUTH_BYTES
                 # header后的一段hash值, 10字节one-time-auth
                 _hash = data[header_length: offset]
                 _data = data[:header_length]
                 # iv+key
                 key = self._encryptor.decipher_iv + self._encryptor.key
                 # 验证是否允许
                 if onetimeauth_verify(_hash, _data, key) is False:
                     logging.warn('one time auth fail')
                     self.destroy()
                     return
                 header_length += ONETIMEAUTH_BYTES
         self._remote_address = (common.to_str(remote_addr), remote_port)
         # pause reading 上送数据
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_local:
             # 客户端
             # forward address to remote
             # 告诉浏览器,socks5验证成功
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             # spec https://shadowsocks.org/en/spec/one-time-auth.html
             # ATYP & 0x10 == 1, then OTA is enabled.
             if self._ota_enable:
                 # 自己实现的ota,在浏览器之类发来的socks5请求头部的addrtype中加入ADDRTYPE_AUTH
                 # 然后发往ssserver,修改第一字节,实际是socks5头部的第3字节
                 data = common.chr(addrtype | ADDRTYPE_AUTH) + data[1:]
                 key = self._encryptor.cipher_iv + self._encryptor.key
                 # 附在数据尾部? 这里的data是socks5请求报文第三字节之后的数据
                 data += onetimeauth_gen(data, key)
             # 加密
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             # 选择一个ssserver发送数据
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             # 服务端
             if self._ota_enable:
                 # 过滤前面的远程地址和ota hmac-sha1头
                 data = data[header_length:]
                 self._ota_chunk_data(data,
                                      self._data_to_write_to_remote.append)
             elif len(data) > header_length:
                 # 过滤掉头部还有数据要发送
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             # 解析dns之后remote_sock连接远端web站点
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Beispiel #45
0
    def _handle_stage_addr(self, data):
        try:
            cmd = common.ord(data[1])
            #这个暂时不知道是干嘛用的
            if cmd == CMD_UDP_ASSOCIATE: ##CMD_UDP_ASSOCIATE = 3
                logging.debug('UDP associate')
                if self._local_sock.family == socket.AF_INET6:
                    header = b'\x05\x00\x00\x04'
                else:
                    header = b'\x05\x00\x00\x01'
                addr, port = self._local_sock.getsockname()[:2]
                addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                port_to_send = struct.pack('>H', port)
                self._write_to_sock(header + addr_to_send + port_to_send,
                                    self._local_sock)
                #这里状态变成下一个状态了
                self._stage = STAGE_UDP_ASSOC
                # just wait for the client to disconnect
                return
            #如果是连接请求,将头也就是前面的\x05\x01\x00去掉,从第三位开始处理数据
            elif cmd == CMD_CONNECT:
                # just trim VER CMD RSV
                data = data[3:]
            else:
                logging.error('unknown command %d', cmd)
                self.destroy()
                return
            #这里专门用pasr_header来处理数据
            header_result = parse_header(data)
            if header_result is None:
                raise Exception('can not parse header')
            addrtype, remote_addr, remote_port, header_length = header_result
            #这里开始执行connect命令
            logging.info('connecting %s:%d from %s:%d' %
                         (common.to_str(remote_addr), remote_port,
                          self._client_address[0], self._client_address[1]))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            # pause reading
            #这里是先更改上行流的状态为写,下面的将需要写道remote的数据放到_data_to_write_to_remote
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            #更改状态到下一个状态
            self._stage = STAGE_DNS
            # forward address to remote
            #这里是响应客户端的响应,这个响应的内容其实没多大的意义
            self._write_to_sock((b'\x05\x00\x00\x01'
                                    b'\x00\x00\x00\x00\x10\x10'),
                                self._local_sock)
            # notice here may go into _handle_dns_resolved directly
            #这里直接将sserver服务器的域名解析为ip

            if len(data) > header_length:
                self._data_to_write_to_remote.append(data[header_length:])
            # notice here may go into _handle_dns_resolved directly
            self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)

            
        except Exception as e:
            print '_handle_stage_addr error:%r' % e
            traceback.print_exc()
            #self._log_error(e)
            self.destroy()
Beispiel #46
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        client_address = r_addr[0]
        key = None
        iv = None
        if not data:
            logging.debug('U[%d] UDP handle_server: data is empty' %
                          self._config['server_port'])
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            if self._is_tunnel:
                # add ss header to data
                tunnel_remote = self.tunnel_remote
                tunnel_remote_port = self.tunnel_remote_port
                data = common.add_header(tunnel_remote,
                                         tunnel_remote_port, data)
            else:
                frag = common.ord(data[2])
                if frag != 0:
                    logging.warning('UDP drop a message since frag is not 0')
                    return
                else:
                    data = data[3:]
        else:
            # decrypt data
            try:
                data, key, iv = cryptor.decrypt_all(self._password,
                                                    self._method,
                                                    data)
            except Exception:
                logging.debug('U[%d] UDP handle_server: decrypt data failed' % self._config[
                    'server_port'])
                return
            if not data:
                logging.debug(
                    'U[%d] UDP handle_server: data is empty after decrypt' % self._config[
                        'server_port']
                )
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._config['firewall_ports'] and self._config['server_port'] not in self._config['firewall_trusted']:
            # Firewall enabled
            if self._config['firewall_mode'] == 'blacklist' and dest_port in self._config['firewall_ports']:
                firewall_blocked = True
            elif self._config['firewall_mode'] == 'whitelist' and dest_port not in self._config['firewall_ports']:
                firewall_blocked = True
            else:
                firewall_blocked = False
        else:
            firewall_blocked = False
        if firewall_blocked:
            logging.warning('U[%d] UDP PORT BANNED: RP[%d] A[%s-->%s]' % (
                self._config['server_port'], dest_port,
                client_address, common.to_str(dest_addr)
            ))
            return
        else:
            logging.info('U[%d] UDP CONN: RP[%d] A[%s-->%s]' % (
                self._config['server_port'], dest_port,
                client_address, common.to_str(dest_addr)
            ))
        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port
        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('U[%d] IP %s is in forbidden list, drop' %
                                  (self._config['server_port'], common.to_str(sa[0])))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        if self._is_local:
            key, iv, m = cryptor.gen_key_iv(self._password, self._method)
            try:
                data = cryptor.encrypt_all_m(key, iv, m, self._method, data,
                                             self._crypto_path)
            except Exception:
                logging.debug("UDP handle_server: encrypt data failed")
                return
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except (socket.error, OSError, IOError) as e:
            error_no = eventloop.errno_from_exception(e)
            if sys.platform == "win32":
                if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                                errno.EWOULDBLOCK, errno.WSAEWOULDBLOCK):
                    pass
                else:
                    shell.print_exception(e)
            elif error_no in (errno.EAGAIN, errno.EINPROGRESS,
                              errno.EWOULDBLOCK):
                pass
            else:
                shell.print_exception(e)
Beispiel #47
0
    def _handle_stage_addr(self, data):
        try:
            # first determine request CMD
            # if the request is UDP ASSOCIATE
            # sslocal composes response header, sends it to client
            # note that ATYP/BND.ADDR/BND.PORT are info of sslocal's _local_sock
            # if the request is CONNECT
            # just trim VER CMD RSV from request header
            # if the request is BIND or else, drop it
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug('UDP associate')
                    if self._local_sock.family == socket.AF_INET6:
                        header = b'\x05\x00\x00\x04'
                    else:
                        header = b'\x05\x00\x00\x01'
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family,
                                                    addr)
                    port_to_send = struct.pack('>H', port)
                    self._write_to_sock(header + addr_to_send + port_to_send,
                                        self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    data = data[3:]
                else:
                    logging.error('unknown command %d', cmd)
                    self.destroy()
                    return

            # further analyse request
            # parse_header() analyses header that only contains type/addr/port
            # note that parse_header() is used in UDPRelay as well
            # note that remote_addr and remote_port must be of dest regardless of self is sslocal or ssremote
            header_result = parse_header(data)
            if header_result is None:
                raise Exception('can not parse header')
            addrtype, remote_addr, remote_port, header_length = header_result
            logging.info('connecting %s:%d from %s:%d' %
                         (common.to_str(remote_addr), remote_port,
                          self._client_address[0], self._client_address[1]))
            self._remote_address = (common.to_str(remote_addr), remote_port)
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS

            # for sslocal
            # 1. send response to client's CONNECT request
            # note that ATYP is v4, BND.ADDR is 0.0.0.0:\x10\x10 ?
            # 2. encrypt data, namely desttype/destaddr/destport, to be sent to ssremote and add it to buffer
            # 3. do sth when ssremote is resolved
            # check _handle_dns_resolved
            # note that _handle_dns_resolved is a callback
            if self._is_local:
                self._write_to_sock((b'\x05\x00\x00\x01'
                                     b'\x00\x00\x00\x00\x10\x10'),
                                    self._local_sock)

                # forward address to remote
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)

                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0],
                                           self._handle_dns_resolved)
            # for a remote server
            # 1. add data without header to buffer
            # 2. do sth when dest is resolved
            # check _handle_dns_resolved 
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr,
                                           self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config['verbose']:
                traceback.print_exc()
            self.destroy()
Beispiel #48
0
    def _write_to_sock(self, data, sock):
        # write data to sock
        # if only some of the data are written, put remaining in the buffer
        # and update the stream to wait for writing
        if not data or not sock:
            return False
        #logging.debug("_write_to_sock %s %s %s" % (self._remote_sock, sock, self._remote_udp))
        uncomplete = False
        if self._remote_udp and sock == self._remote_sock:
            try:
                self._udp_data_send_buffer += data
                #logging.info('UDP over TCP sendto %d %s' % (len(data), binascii.hexlify(data)))
                while len(self._udp_data_send_buffer) > 6:
                    length = struct.unpack('>H', self._udp_data_send_buffer[:2])[0]

                    if length > len(self._udp_data_send_buffer):
                        break

                    data = self._udp_data_send_buffer[:length]
                    self._udp_data_send_buffer = self._udp_data_send_buffer[length:]

                    frag = common.ord(data[2])
                    if frag != 0:
                        logging.warn('drop a message since frag is %d' % (frag,))
                        continue
                    else:
                        data = data[3:]
                    header_result = parse_header(data)
                    if header_result is None:
                        continue
                    connecttype, dest_addr, dest_port, header_length = header_result
                    addrs = socket.getaddrinfo(dest_addr, dest_port, 0,
                            socket.SOCK_DGRAM, socket.SOL_UDP)
                    #logging.info('UDP over TCP sendto %s:%d %d bytes from %s:%d' % (dest_addr, dest_port, len(data), self._client_address[0], self._client_address[1]))
                    if addrs:
                        af, socktype, proto, canonname, server_addr = addrs[0]
                        data = data[header_length:]
                        if af == socket.AF_INET6:
                            self._remote_sock_v6.sendto(data, (server_addr[0], dest_port))
                        else:
                            sock.sendto(data, (server_addr[0], dest_port))

            except Exception as e:
                #trace = traceback.format_exc()
                #logging.error(trace)
                error_no = eventloop.errno_from_exception(e)
                if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                                errno.EWOULDBLOCK):
                    uncomplete = True
                else:
                    shell.print_exception(e)
                    self.destroy()
                    return False
            return True
        else:
            try:
                l = len(data)
                s = sock.send(data)
                if s < l:
                    data = data[s:]
                    uncomplete = True
            except (OSError, IOError) as e:
                error_no = eventloop.errno_from_exception(e)
                if error_no in (errno.EAGAIN, errno.EINPROGRESS,
                                errno.EWOULDBLOCK):
                    uncomplete = True
                else:
                    #traceback.print_exc()
                    shell.print_exception(e)
                    self.destroy()
                    return False
        if uncomplete:
            if sock == self._local_sock:
                self._data_to_write_to_local.append(data)
                self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING)
            elif sock == self._remote_sock:
                self._data_to_write_to_remote.append(data)
                self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            else:
                logging.error('write_all_to_sock:unknown socket')
        else:
            if sock == self._local_sock:
                self._update_stream(STREAM_DOWN, WAIT_STATUS_READING)
            elif sock == self._remote_sock:
                self._update_stream(STREAM_UP, WAIT_STATUS_READING)
            else:
                logging.error('write_all_to_sock:unknown socket')
        return True
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._is_local:
            # if local receives this request, then:
            frag = common.ord(data[2])
# this is no classic UDP
# +----+------+------+----------+----------+----------+
# |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +----+------+------+----------+----------+----------+
# | 2  |  1   |  1   | Variable |    2     | Variable |
# +----+------+------+----------+----------+----------+
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
                # after [3:]
# +------+----------+----------+----------+
# | ATYP | DST.ADDR | DST.PORT |   DATA   |
# +------+----------+----------+----------+
# |  1   | Variable |    2     | Variable |
# +------+----------+----------+----------+
# 就是shadowsocks那段
        else:
            # If remote receives
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt the data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            # 如果是local收到,则server_addr server_port都是远程的
            server_addr, server_port = self._get_a_server()
        else:
            # 如果远程收到,则将server_addr这些改成dest_addr dest_port,方便操作
            server_addr, server_port = dest_addr, dest_port

        key = client_key(r_addr[0], r_addr[1], dest_addr, dest_port)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            # 根据server_addr, server_port等的类型决定选用的协议类型
            # Translate the host/port argument into a sequence of 5-tuples
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if addrs:
                af, socktype, proto, canonname, sa = addrs[0]
                # 根据上面的server_addr, server_port建立相应的连接,一环扣一环
                # 这里是主动发出请求,所以要新建一个socket

                # 这里根据上面得到的不同的端口类型就新建不同类型的socket:用于tcp的和同于udp的
                client = socket.socket(af, socktype, proto)
                client.setblocking(False)
                self._cache[key] = client
                self._client_fd_to_server_addr[client.fileno()] = r_addr
            else:
                # drop
                return
            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN)

        if self._is_local:
            # 如果是local,要向远程发,要过墙,所以要加密
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            # 如果是远程,要向dest发请求,所以把除数据的部分除去
            data = data[header_length:]
        if not data:
            return
        try:
            # Send the data
            # 这个sendto同时有udp的和tcp的两种,sendto函数主要用于UDP,但这里两种都用了
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                logging.error(e)
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             # UDP穿透
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d from %s:%d' %
                      (common.to_str(remote_addr), remote_port,
                       self._client_address[0], self._client_address[1]))
         self._remote_address = (common.to_str(remote_addr), remote_port)
         # pause reading
         # 卧槽原来是这里啊!
         # 想了好久要是处于 STAGE_ADDR 状态收到了本应在 STAGE_CONNECTING 阶段转发的数据怎么办
         # 因为之前有一个 parse_header 操作,转发阶段的数据是没有 header 的。
         # 原来是直接暂停了读取,因此在DNS请求完成之前(未跳转到 STAGE_CONNECTING 状态之前)
         # 不会收到待转发的数据
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_local:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Beispiel #51
0
 def _handle_stage_addr(self, data):
     if self._is_local:
         if self._is_tunnel:
             # add ss header to data
             tunnel_remote = self.tunnel_remote
             tunnel_remote_port = self.tunnel_remote_port
             data = common.add_header(tunnel_remote,
                                      tunnel_remote_port, data)
         else:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
     header_result = parse_header(data)
     if header_result is None:
         raise Exception('can not parse header')
     addrtype, remote_addr, remote_port, header_length = header_result
     logging.info('connecting %s:%d from %s:%d' %
                  (common.to_str(remote_addr), remote_port,
                   self._client_address[0], self._client_address[1]))
     if self._is_local is False:
         # spec https://shadowsocks.org/en/spec/one-time-auth.html
         self._ota_enable_session = addrtype & ADDRTYPE_AUTH
         if self._ota_enable and not self._ota_enable_session:
             logging.warn('client one time auth is required')
             return
         if self._ota_enable_session:
             if len(data) < header_length + ONETIMEAUTH_BYTES:
                 logging.warn('one time auth header is too short')
                 return None
             offset = header_length + ONETIMEAUTH_BYTES
             _hash = data[header_length: offset]
             _data = data[:header_length]
             key = self._cryptor.decipher_iv + self._cryptor.key
             if onetimeauth_verify(_hash, _data, key) is False:
                 logging.warn('one time auth fail')
                 self.destroy()
                 return
             header_length += ONETIMEAUTH_BYTES
     self._remote_address = (common.to_str(remote_addr), remote_port)
     # pause reading
     self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
     self._stage = STAGE_DNS
     if self._is_local:
         # jump over socks5 response
         if not self._is_tunnel:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
         # spec https://shadowsocks.org/en/spec/one-time-auth.html
         # ATYP & 0x10 == 0x10, then OTA is enabled.
         if self._ota_enable_session:
             data = common.chr(addrtype | ADDRTYPE_AUTH) + data[1:]
             key = self._cryptor.cipher_iv + self._cryptor.key
             _header = data[:header_length]
             sha110 = onetimeauth_gen(data, key)
             data = _header + sha110 + data[header_length:]
         data_to_send = self._cryptor.encrypt(data)
         self._data_to_write_to_remote.append(data_to_send)
         # notice here may go into _handle_dns_resolved directly
         self._dns_resolver.resolve(self._chosen_server[0],
                                    self._handle_dns_resolved)
     else:
         if self._ota_enable_session:
             data = data[header_length:]
             self._ota_chunk_data(data,
                                  self._data_to_write_to_remote.append)
         elif len(data) > header_length:
             self._data_to_write_to_remote.append(data[header_length:])
         # notice here may go into _handle_dns_resolved directly
         self._dns_resolver.resolve(remote_addr,
                                    self._handle_dns_resolved)
Beispiel #52
0
    def _handle_stage_addr(self, ogn_data, data):
        try:
            if self._is_local:
                cmd = common.ord(data[1])
                if cmd == CMD_UDP_ASSOCIATE:
                    logging.debug("UDP associate")
                    if self._local_sock.family == socket.AF_INET6:
                        header = b"\x05\x00\x00\x04"
                    else:
                        header = b"\x05\x00\x00\x01"
                    addr, port = self._local_sock.getsockname()[:2]
                    addr_to_send = socket.inet_pton(self._local_sock.family, addr)
                    port_to_send = struct.pack(">H", port)
                    self._write_to_sock(header + addr_to_send + port_to_send, self._local_sock)
                    self._stage = STAGE_UDP_ASSOC
                    # just wait for the client to disconnect
                    return
                elif cmd == CMD_CONNECT:
                    # just trim VER CMD RSV
                    data = data[3:]
                else:
                    logging.error("unknown command %d", cmd)
                    self.destroy()
                    return

            before_parse_data = data
            if self._is_local:
                header_result = parse_header(data)
            else:
                if (
                    data is None
                    or FORCE_NEW_PROTOCOL
                    and common.ord(data[0]) != 0x88
                    and (~common.ord(data[0]) & 0xFF) != 0x88
                ):
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                data = pre_parse_header(data)
                if data is None:
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                header_result = parse_header(data)
                if header_result is None:
                    data = self._handel_protocol_error(self._client_address, ogn_data)
                    header_result = parse_header(data)
            connecttype, remote_addr, remote_port, header_length = header_result
            logging.info(
                "%s connecting %s:%d from %s:%d"
                % (
                    (connecttype == 0) and "TCP" or "UDP",
                    common.to_str(remote_addr),
                    remote_port,
                    self._client_address[0],
                    self._client_address[1],
                )
            )
            self._remote_address = (common.to_str(remote_addr), remote_port)
            self._remote_udp = connecttype != 0
            # pause reading
            self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
            self._stage = STAGE_DNS
            if self._is_local:
                # forward address to remote
                self._write_to_sock((b"\x05\x00\x00\x01" b"\x00\x00\x00\x00\x10\x10"), self._local_sock)
                if CLIENT_NEW_PROTOCOL:
                    rnd_len = random.randint(1, 32)
                    total_len = 7 + rnd_len + len(data)
                    data = b"\x88" + struct.pack(">H", total_len) + chr(rnd_len) + (b" " * (rnd_len - 1)) + data
                    crc = (0xFFFFFFFF - binascii.crc32(data)) & 0xFFFFFFFF
                    data += struct.pack("<I", crc)
                data = self._obfs.client_pre_encrypt(data)
                data_to_send = self._encryptor.encrypt(data)
                self._data_to_write_to_remote.append(data_to_send)
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(self._chosen_server[0], self._handle_dns_resolved)
            else:
                if len(data) > header_length:
                    self._data_to_write_to_remote.append(data[header_length:])
                # notice here may go into _handle_dns_resolved directly
                self._dns_resolver.resolve(remote_addr, self._handle_dns_resolved)
        except Exception as e:
            self._log_error(e)
            if self._config["verbose"]:
                traceback.print_exc()
            self.destroy()
Beispiel #53
0
    def _handle_server(self):
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                common.error_to_file('drop a message since frag is not 0',self._config)
                return
            else:
                data = data[3:]
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        header_result = parse_header(data,self._config)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        key = client_key(r_addr, af)

        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            self._cache[key] = client
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
            if not self._is_local:
                if self._config.has_key('port_limit') and self._config['port_limit'] != "" and os.path.exists(self._config['port_limit']):
                    port_limits = json.loads(open(self._config['port_limit']).read())
                    if str(self._listen_port) in port_limits:
                        port_limits['%s' % self._listen_port]['used'] = port_limits['%s' % self._listen_port]['used'] + len(data) + BUF_SIZE
                        open('%s' % self._config['port_limit'],"w").write("%s" % json.dumps(port_limits,indent=4,ensure_ascii=False,sort_keys=True))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
    def _handle_server(self):
        """
        服务器有UDP连接
        :return:
        """
        server = self._server_socket
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))
        if self._is_local:
            frag = common.ord(data[2])
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)
            # decrypt data
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            server_addr, server_port = self._get_a_server()
        else:
            server_addr, server_port = dest_addr, dest_port

        addrs = self._dns_cache.get(server_addr, None)
        if addrs is None:
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if not addrs:
                # drop
                return
            else:
                self._dns_cache[server_addr] = addrs

        af, socktype, proto, canonname, sa = addrs[0]
        # 给这个客户端返回一个唯一值而已,一个字符串
        key = client_key(r_addr, af)
        client = self._cache.get(key, None)
        if not client:
            # TODO async getaddrinfo
            if self._forbidden_iplist:
                if common.to_str(sa[0]) in self._forbidden_iplist:
                    logging.debug('IP %s is in forbidden list, drop' %
                                  common.to_str(sa[0]))
                    # drop
                    return
            client = socket.socket(af, socktype, proto)
            client.setblocking(False)
            # 记录client的关键字
            self._cache[key] = client
            # 记录client的文件描述符对应的转发地址,若client收到响应udp包则转发到这个地址
            self._client_fd_to_server_addr[client.fileno()] = r_addr

            self._sockets.add(client.fileno())
            self._eventloop.add(client, eventloop.POLL_IN, self)

        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        else:
            data = data[header_length:]
        if not data:
            return
        try:
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                shell.print_exception(e)
Beispiel #55
0
 def _handle_stage_addr(self, data):
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(self._local_sock.family,
                                                 addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(header + addr_to_send + port_to_send,
                                     self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d', cmd)
                 self.destroy()
                 return
         header_result = parse_header(data)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d from %s:%d' %
                      (common.to_str(remote_addr), remote_port,
                       self._client_address[0], self._client_address[1]))
         if self._is_local is False:
             # spec https://shadowsocks.org/en/spec/one-time-auth.html
             self._ota_enable_session = addrtype & ADDRTYPE_AUTH
             if self._ota_enable and not self._ota_enable_session:
                 logging.warn('client one time auth is required')
                 return
             if self._ota_enable_session:
                 if len(data) < header_length + ONETIMEAUTH_BYTES:
                     logging.warn('one time auth header is too short')
                     return None
                 offset = header_length + ONETIMEAUTH_BYTES
                 _hash = data[header_length: offset]
                 _data = data[:header_length]
                 key = self._encryptor.decipher_iv + self._encryptor.key
                 if onetimeauth_verify(_hash, _data, key) is False:
                     logging.warn('one time auth fail')
                     self.destroy()
                     return
                 header_length += ONETIMEAUTH_BYTES
         self._remote_address = (common.to_str(remote_addr), remote_port)
         # pause reading
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_local:
             # forward address to remote
             self._write_to_sock((b'\x05\x00\x00\x01'
                                  b'\x00\x00\x00\x00\x10\x10'),
                                 self._local_sock)
             # spec https://shadowsocks.org/en/spec/one-time-auth.html
             # ATYP & 0x10 == 1, then OTA is enabled.
             if self._ota_enable_session:
                 data = common.chr(addrtype | ADDRTYPE_AUTH) + data[1:]
                 key = self._encryptor.cipher_iv + self._encryptor.key
                 data += onetimeauth_gen(data, key)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(self._chosen_server[0],
                                        self._handle_dns_resolved)
         else:
             if self._ota_enable_session:
                 data = data[header_length:]
                 self._ota_chunk_data(data,
                                      self._data_to_write_to_remote.append)
             elif len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(remote_addr,
                                        self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         self.destroy()
Beispiel #56
0
 def _handle_stage_addr(self, data):
     logging.debug("Running in the TCPRelayHandler class. [_handle_stage_addr]")
     try:
         if self._is_local:
             cmd = common.ord(data[1])
             if cmd == CMD_UDP_ASSOCIATE:
                 logging.debug('UDP associate')
                 if self._local_sock.family == socket.AF_INET6:
                     header = b'\x05\x00\x00\x04'
                 else:
                     header = b'\x05\x00\x00\x01'
                 addr, port = self._local_sock.getsockname()[:2]
                 addr_to_send = socket.inet_pton(
                     self._local_sock.family, addr)
                 port_to_send = struct.pack('>H', port)
                 self._write_to_sock(
                     header + addr_to_send + port_to_send, self._local_sock)
                 self._stage = STAGE_UDP_ASSOC
                 # just wait for the client to disconnect
                 return
             elif cmd == CMD_CONNECT:
                 # just trim VER CMD RSV
                 data = data[3:]
             else:
                 logging.error('unknown command %d' % cmd)
                 common.error_to_file('unknown command %d' % cmd,self._config)
                 self.destroy()
                 return
         header_result = parse_header(data,self._config)
         if header_result is None:
             raise Exception('can not parse header')
         addrtype, remote_addr, remote_port, header_length = header_result
         logging.info('connecting %s:%d from %s:%d' % (common.to_str(
             remote_addr), remote_port, self._client_address[0], self._client_address[1]))
         if self._server._listen_port in self._config['forbid']['port']:
             for i in self._config['forbid']['site']:
                 if str(i) in common.to_str(remote_addr):
                     self.destroy()
         try:
             if common.to_str(self._config['log']['log_enable']) == "True":
                 log_str_one_line = '''[%s]\t%s:%d\t%s:%d [server_port: %s]\n''' % (time.strftime(
                     "%Y-%m-%d %H:%M:%S"), common.to_str(remote_addr), remote_port, self._client_address[0], self._client_address[1],self._server._listen_port)
                 log_str_buf.append(log_str_one_line)
                 if os.path.exists(os.path.split(self._config['log']['log_path'])[0]) is False:
                     os.makedirs(os.path.split(self._config['log']['log_path'])[0])
                 if len(log_str_buf) == 10:
                     f = open("%s" % self._config['log']['log_path'], 'a+')
                     f.write("".join(log_str_buf))
                     f.close()
                     del log_str_buf[:]
         except Exception as e:
             logging.error(
                 "Sorry.Some ERROR happend when I try to log something to file : info: %s" % str(e))
             common.error_to_file("Sorry.Some ERROR happend when I try to log something to file : info: %s" % str(e),self._config)
         self._remote_address = (common.to_str(remote_addr), remote_port)
         # pause reading
         self._update_stream(STREAM_UP, WAIT_STATUS_WRITING)
         self._stage = STAGE_DNS
         if self._is_local:
             # forward address to remote
             self._write_to_sock(
                 (b'\x05\x00\x00\x01' b'\x00\x00\x00\x00\x10\x10'), self._local_sock)
             data_to_send = self._encryptor.encrypt(data)
             self._data_to_write_to_remote.append(data_to_send)
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(
                 self._chosen_server[0], self._handle_dns_resolved)
         else:
             if len(data) > header_length:
                 self._data_to_write_to_remote.append(data[header_length:])
             # notice here may go into _handle_dns_resolved directly
             self._dns_resolver.resolve(
                 remote_addr, self._handle_dns_resolved)
     except Exception as e:
         self._log_error(e)
         if self._config['verbose']:
             traceback.print_exc()
         # TODO use logging when debug completed
         self.destroy()
Beispiel #57
0
    def _handle_client(self, sock):
        data, r_addr = sock.recvfrom(BUF_SIZE)
        common.connect_log('UDP data remote from %s:%d', common.to_str(r_addr[0]), r_addr[1])
        if not data:
            logging.debug('UDP handle_client: data is empty')
            return
        if self._stat_callback:
            self._stat_callback(self._listen_port, len(data))

        client_addr = self._client_fd_to_server_addr.get(sock.fileno())
        client_uid = None
        if client_addr:
            addr = client_addr[0]
            common.connect_log('UDP data to %s:%d', common.to_str(addr[0]), addr[1])
            key = client_key(client_addr[0], client_addr[1])
            client_pair = self._cache.get(key, None)
            client_dns_pair = self._cache_dns_client.get(key, None)
            if client_pair:
                client, client_uid = client_pair
            elif client_dns_pair:
                client, client_uid = client_dns_pair

        if not self._is_local:
            addrlen = len(r_addr[0])
            if addrlen > 255:
                # drop
                return
            data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data
            ref_iv = [encrypt.encrypt_new_iv(self._method)]
            self._protocol.obfs.server_info.iv = ref_iv[0]
            data = self._protocol.server_udp_pre_encrypt(data, client_uid)
            response = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1,
                                           data, ref_iv)
            if not response:
                return
        else:
            ref_iv = [0]
            data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0,
                                       data, ref_iv)
            if not data:
                return
            self._protocol.obfs.server_info.recv_iv = ref_iv[0]
            data = self._protocol.client_udp_post_decrypt(data)
            header_result = parse_header(data)
            if header_result is None:
                return
            #connecttype, dest_addr, dest_port, header_length = header_result
            #logging.debug('UDP handle_client %s:%d to %s:%d' % (common.to_str(r_addr[0]), r_addr[1], dest_addr, dest_port))

            response = b'\x00\x00\x00' + data

        if client_addr:
            if client_uid:
                self.add_transfer_d(client_uid, len(response))
            else:
                self.server_transfer_dl += len(response)
            self.write_to_server_socket(response, client_addr[0])
            if client_dns_pair:
                logging.debug("remove dns client %s:%d" % (client_addr[0][0], client_addr[0][1]))
                del self._cache_dns_client[key]
                self._close_client(client_dns_pair[0])
        else:
            # this packet is from somewhere else we know
            # simply drop that packet
            pass
    def _handle_server(self):
        server = self._server_socket
        # r_addr是发送者的地址
        data, r_addr = server.recvfrom(BUF_SIZE)
        if not data:
            logging.debug('UDP handle_server: data is empty')
            
        # 若本地端从监听1080端口收到本机应用进程(例如chrome)的数据,进行切除header
        if self._is_local:
            # ord:输入char返回Ascii
            frag = common.ord(data[2])
            # this is no classic UDP
            # +----+------+------+----------+----------+----------+
            # |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
            # +----+------+------+----------+----------+----------+
            # | 2  |  1   |  1   | Variable |    2     | Variable |
            # +----+------+------+----------+----------+----------+
            if frag != 0:
                logging.warn('drop a message since frag is not 0')
                return
            else:
                data = data[3:]
                # [3:]之后变成
                # +------+----------+----------+----------+
                # | ATYP | DST.ADDR | DST.PORT |   DATA   |
                # +------+----------+----------+----------+
                # |  1   | Variable |    2     | Variable |
                # +------+----------+----------+----------+
                # 就是shadowsocks那段
                
        # 如果是服务端收到本地端发出的udp数据,先进行解密
        else:
            data = encrypt.encrypt_all(self._password, self._method, 0, data)            
            if not data:
                logging.debug('UDP handle_server: data is empty after decrypt')
                return
        # 处理header
        header_result = parse_header(data)
        if header_result is None:
            return
        addrtype, dest_addr, dest_port, header_length = header_result

        if self._is_local:
            # 如果是local收到,则server_addr server_port都是远程的
            server_addr, server_port = self._get_a_server()
        else:
            # 如果远程收到,则将server_addr这些改成dest_addr dest_port,方便操作
            # dest就是最终目标,例如 www.youtube.com:443
            server_addr, server_port = dest_addr, dest_port
        # r_addr[]是接收到的数据
        key = client_key(r_addr[0], r_addr[1], dest_addr, dest_port)
        client = self._cache.get(key, None)
        # 若callback字典中没有相关记录,进行注册字典
        if not client:
            # TODO async getaddrinfo
            # 根据server_addr, server_port等的类型决定选用的协议类型
            # Translate the host/port argument into a sequence of 5-tuples
            addrs = socket.getaddrinfo(server_addr, server_port, 0,
                                       socket.SOCK_DGRAM, socket.SOL_UDP)
            if addrs:
                af, socktype, proto, canonname, sa = addrs[0]
                # 根据上面的server_addr, server_port建立相应的连接,一环扣一环
                # 这里是主动发出请求,所以要新建一个socket
                # 这里根据上面得到的不同的端口类型就新建不同类型的socket:用于tcp的和同于udp的
                client = socket.socket(af, socktype, proto)
                client.setblocking(False)
                self._cache[key] = client
                self._client_fd_to_server_addr[client.fileno()] = r_addr
            else:
                # drop
                return
            # sockets是一个set集合
            self._sockets.add(client.fileno())
            # 添加进Eventloop,标志设置为可读
            self._eventloop.add(client, eventloop.POLL_IN)
        
        # 如果是local,要向远程发,要过墙,所以要加密
        if self._is_local:
            data = encrypt.encrypt_all(self._password, self._method, 1, data)
            if not data:
                return
        # 如果是远程,要向dest发请求,所以把除数据的部分除去,即除去header。
        else:
            # data已经在上面进行数据解密了。不需要像local一样加密发送。
            # data已经被切除头的3个字节了
            data = data[header_length:]

        if not data:
            return
        
        try:
            # 发送,完美无瑕。。。。
            # 这个sendto同时有udp的和tcp的两种,sendto函数主要用于UDP,但这里两种都用了
            # 调用sendto时候会自动加上那个首3个字节,貌似是x00 x00 x00
            client.sendto(data, (server_addr, server_port))
        except IOError as e:
            err = eventloop.errno_from_exception(e)
            if err in (errno.EINPROGRESS, errno.EAGAIN):
                pass
            else:
                logging.error(e)