def _try_request(self): """ Try to consume a REQUEST message and respond whether we will accept the request. Will setup a TCP relay or an UDP socket to accommodate TCP RELAY and UDP ASSOCIATE requests. After a TCP relay is set up the handler will deactivate itself and change the Connection to a TcpRelayConnection. Further data will be passed on to that handler. :return: False if command could not been processes due to lack of bytes, True otherwise """ self._logger.debug("Client has sent PROXY REQUEST") offset, request = conversion.decode_request(0, self.buffer) if request is None: return False self.buffer = self.buffer[offset:] self.state = ConnectionState.PROXY_REQUEST_RECEIVED try: if request.cmd == conversion.REQ_CMD_UDP_ASSOCIATE: self.on_udp_associate_request(self, request) elif request.cmd == conversion.REQ_CMD_BIND: response = conversion.encode_reply( 0x05, conversion.REP_SUCCEEDED, 0x00, conversion.ADDRESS_TYPE_IPV4, "127.0.0.1", 1081) self.transport.write(response) self.state = ConnectionState.PROXY_REQUEST_ACCEPTED elif request.cmd == conversion.REQ_CMD_CONNECT: self._logger.info( "TCP req to %s:%d support it. Returning HOST UNREACHABLE", *request.destination) response = conversion.encode_reply( 0x05, conversion.REP_HOST_UNREACHABLE, 0x00, conversion.ADDRESS_TYPE_IPV4, "0.0.0.0", 0) self.transport.write(response) else: self.deny_request(request, "CMD not recognized") except: response = conversion.encode_reply( 0x05, conversion.REP_COMMAND_NOT_SUPPORTED, 0x00, conversion.ADDRESS_TYPE_IPV4, "0.0.0.0", 0) self.transport.write(response) self._logger.exception( "Exception thrown, returning unsupported command response") return True
def _try_request(self): """ Try to consume a REQUEST message and respond whether we will accept the request. Will setup a TCP relay or an UDP socket to accommodate TCP RELAY and UDP ASSOCIATE requests. After a TCP relay is set up the handler will deactivate itself and change the Connection to a TcpRelayConnection. Further data will be passed on to that handler. :return: False if command could not been processes due to lack of bytes, True otherwise """ self._logger.debug("Client has sent PROXY REQUEST") offset, request = conversion.decode_request(0, self.buffer) if request is None: return False self.buffer = self.buffer[offset:] self.state = ConnectionState.PROXY_REQUEST_RECEIVED try: if request.cmd == conversion.REQ_CMD_UDP_ASSOCIATE: self.on_udp_associate_request(self, request) elif request.cmd == conversion.REQ_CMD_BIND: response = conversion.encode_reply(0x05, conversion.REP_SUCCEEDED, 0x00, conversion.ADDRESS_TYPE_IPV4, "127.0.0.1", 1081) self.transport.write(response) self.state = ConnectionState.PROXY_REQUEST_ACCEPTED elif request.cmd == conversion.REQ_CMD_CONNECT: self._logger.info("TCP req to %s:%d support it. Returning HOST UNREACHABLE", *request.destination) response = conversion.encode_reply(0x05, conversion.REP_HOST_UNREACHABLE, 0x00, conversion.ADDRESS_TYPE_IPV4, "0.0.0.0", 0) self.transport.write(response) else: self.deny_request(request, "CMD not recognized") except: response = conversion.encode_reply(0x05, conversion.REP_COMMAND_NOT_SUPPORTED, 0x00, conversion.ADDRESS_TYPE_IPV4, "0.0.0.0", 0) self.transport.write(response) self._logger.exception("Exception thrown, returning unsupported command response") return True
def deny_request(self, request, reason): """ Deny SOCKS5 request @param Request request: the request to deny """ self.state = ConnectionState.CONNECTED response = conversion.encode_reply(0x05, conversion.REP_COMMAND_NOT_SUPPORTED, 0x00, conversion.ADDRESS_TYPE_IPV4, "0.0.0.0", 0) self.transport.write(response) self._logger.error("DENYING SOCKS5 request, reason: %s" % reason)
def on_udp_associate_request(self, connection, request): # The DST.ADDR and DST.PORT fields contain the address and port that the client expects # to use to send UDP datagrams on for the association. The server MAY use this information # to limit access to the association. self._udp_socket = SocksUDPConnection(self, request.destination) ip = self.transport.getHost().host port = self._udp_socket.get_listen_port() self._logger.info("Accepting UDP ASSOCIATE request to %s:%d", ip, port) response = conversion.encode_reply( 0x05, conversion.REP_SUCCEEDED, 0x00, conversion.ADDRESS_TYPE_IPV4, ip, port) self.transport.write(response)