Exemplo n.º 1
0
    def _attempt_finish_socks_handshake(self):
        # Receive the first byte of the server reply using the
        # underlying recv() primitive, and suspend this operation if
        # it comes back with EAGAIN, or fail it if it gives an error.
        # Callers of connect_ex expect to get EINPROGRESS, not EAGAIN.
        logger.debug("Attempting to read SOCKS reply.")
        try:
            resp0 = self._sock.recv(1)
        except socket.error as e:
            if e.errno in _ERRNO_RETRY:
                logger.debug("SOCKS reply not yet available.")
                return errno.EINPROGRESS

            logger.debug("Connection failure: %s", e)
            self._connecting = False
            self._conn_err = e.errno
            return e.errno

        if resp0 != "\x05":
            self._connecting = False
            raise error.SOCKSv5Error(
                "Protocol error: server reply begins with 0x%02x, not 0x05" %
                ord(resp0))

        # We are now committed to receiving and processing the server
        # response.
        resp = self._recv_all(3)
        if resp[0] != "\x00":
            self._connecting = False
            val = ord(resp[0])
            if val in socks5_errors:
                self._conn_err = socks5_errors[val]
                logger.debug("Connection failure at protocol level: %s",
                             os.strerror(self._conn_err))
                return self._conn_err
            else:
                raise error.SOCKSv5Error("Unrecognized SOCKSv5 error: %d" %
                                         val)

        # Read and discard the rest of the reply, which consists of an
        # address type (1 byte), variable-length address (depending on the
        # address type), and port number (2 bytes).
        if resp[2] == "\x01":
            self._recv_all(4)
        elif resp[2] == "\x03":
            length = self._recv_all(1)
            self._recv_all(ord(length))
        else:
            self._recv_all(16)
        self._recv_all(2)

        # We are now officially connected.
        logger.debug("Now connected to %s:%d.", *self._peer_addr)
        self._connected = True
        return 0
Exemplo n.º 2
0
    def connect(self, addr_tuple):
        """
        Tell SOCKS server to connect to our destination.
        """

        dst_addr, dst_port = addr_tuple[0], int(addr_tuple[1])

        self._authenticate()

        # Tell SOCKS server to connect to destination.

        self.sendall("\x05\x01\x00\x01%s%s" %
                     (socket.inet_aton(dst_addr), struct.pack(">H", dst_port)))

        resp = self.recv(4)
        if resp[1] != "\x00":
            raise error.SOCKSv5Error("Connection failed.  Server responded "
                                     "with 0x%s." % resp[0].encode("hex"))

        # Depending on address type, get address.

        if resp[3] == "\x01":
            self.recv(4)
        elif resp[3] == "\x03":
            length = self.recv(1)
            self.recv(length)
        else:
            self.recv(16)

        # Get port.

        self.recv(2)
Exemplo n.º 3
0
    def resolve(self, domain):
        """
        Resolve the given domain using Tor's SOCKS resolution extension.
        """

        domain_len = len(domain)
        if domain_len > 255:
            raise error.SOCKSv5Error("Domain must not be longer than 255 "
                                     "characters, but %d given." % domain_len)

        # Tor defines a new command value, \x0f, that is used for domain
        # resolution.

        self._send_all("\x05\xf0\x00\x03%s%s%s" %
                       (chr(domain_len), domain, "\x00\x00"))

        resp = self._recv_all(10)
        if resp[:2] != "\x05\x00":
            raise error.SOCKSv5Error("Invalid server response: 0x%s" %
                                     resp[1].encode("hex"))

        return socket.inet_ntoa(resp[4:8])
Exemplo n.º 4
0
 def resolve(self, hostname):
     "Resolves the given domain name over the proxy"
     host = hostname.encode("utf-8")
     # First connect to the local proxy
     self.negotiate()
     send_queue(socks._BaseSocket.getsockname(self))
     req = struct.pack('BBB', 0x05, 0xF0, 0x00)
     req += chr(0x03).encode() + chr(len(host)).encode() + host
     req = req + struct.pack(">H", 8444)
     socks._BaseSocket.sendall(self, req)
     # Get the response
     ip = ""
     resp = socks._BaseSocket.recv(self, 4)
     if resp[0:1] != chr(0x05).encode():
         socks._BaseSocket.close(self)
         raise error.SOCKSv5Error("SOCKS Server error")
     elif resp[1:2] != chr(0x00).encode():
         # Connection failed
         socks._BaseSocket.close(self)
         if ord(resp[1:2]) <= 8:
             raise error.SOCKSv5Error("SOCKS Server error {}".format(
                 ord(resp[1:2])))
         else:
             raise error.SOCKSv5Error("SOCKS Server error 9")
     # Get the bound address/port
     elif resp[3:4] == chr(0x01).encode():
         ip = socket.inet_ntoa(socks._BaseSocket.recv(self, 4))
     elif resp[3:4] == chr(0x03).encode():
         resp = resp + socks._BaseSocket.recv(self, 1)
         ip = socks._BaseSocket.recv(self, ord(resp[4:5]))
     else:
         socks._BaseSocket.close(self)
         raise error.SOCKSv5Error("SOCKS Server error.")
     boundport = struct.unpack(">H", socks._BaseSocket.recv(self, 2))[0]
     socks._BaseSocket.close(self)
     return ip
Exemplo n.º 5
0
    def connect(self, addr_tuple):
        """
        Tell SOCKS server to connect to our destination.
        """

        dst_addr, dst_port = addr_tuple[0], int(addr_tuple[1])

        self._authenticate()

        # Tell SOCKS server to connect to destination.

        self.sendall("\x05\x01\x00\x01%s%s" %
                     (socket.inet_aton(dst_addr), struct.pack(">H", dst_port)))

        resp = self._recv_all(4)
        if resp[1] != "\x00":
            val = int(resp[1].encode("hex"), 16)
            if 0 <= val < len(socks5_errors):
                raise error.SOCKSv5Error("SOCKSv5 connection failed because: "
                                         "%s" % socks5_errors[val])
            else:
                raise error.SOCKSv5Error("Unexpected SOCKSv5 error: %d" % val)

        # Depending on address type, get address.

        if resp[3] == "\x01":
            self._recv_all(4)
        elif resp[3] == "\x03":
            length = self._recv_all(1)
            self._recv_all(length)
        else:
            self._recv_all(16)

        # Get port.

        self._recv_all(2)
Exemplo n.º 6
0
    def _authenticate(self):
        """
        Authenticate to our SOCKSv5 server.
        """

        assert (proxy_addr is not None) and (proxy_port is not None)

        # Connect to SOCKSv5 server.  We use version 5 and one authentication
        # method, which is "no authentication".

        self._sock.connect((proxy_addr, proxy_port))
        self._send_all("\x05\x01\x00")
        resp = self._recv_all(2)
        if resp != "\x05\x00":
            raise error.SOCKSv5Error("Invalid server response: 0x%s" %
                                     resp.encode("hex"))

        send_queue(self.getsockname())
Exemplo n.º 7
0
    def _authenticate(self):
        """
        Authenticate to our SOCKSv5 server.
        """

        assert (proxy_addr is not None) and (proxy_port is not None)

        # Connect to SOCKSv5 server.  We use version 5 and one authentication
        # method, which is "no authentication".

        try:
            orig_socket.connect(self, (proxy_addr, proxy_port))
        except Exception as err:
            logger.warning("connect() failed: %s" % err)
            sys.exit(1)

        self.sendall("\x05\x01\x00")

        resp = self._recv_all(2)
        if resp != "\x05\x00":
            raise error.SOCKSv5Error("Invalid server response: 0x%s" %
                                     resp.encode("hex"))

        send_queue(self.getsockname())