예제 #1
0
  def run_test(self):
    """ Create a connection to stream-server.pl using SOCKS4 """
    s = None
    try:
      try:
        s = socks.socksocket()
        s.setproxy(socks.PROXY_TYPE_SOCKS4, socks_host, socks_port)
        s.connect((IP, 8041))
        plog("INFO", "Connected to " + IP)
        # Request bytes
        s.send(str(self.bytes) + "\n")
        plog("INFO", "Sent request for " + str(self.bytes) + " bytes")
        byte_counter = 0
        while 1:
          buffer = s.recv(4096)
          if buffer:
            #plog("INFO", "Received " + str(len(buffer)) + " bytes")
            byte_counter += len(buffer)
            if byte_counter >= self.bytes:
              plog("INFO", "Received " + str(byte_counter) + " bytes in total")
              s.send("close\n")
              break  
      except socks.Socks4Error, e:
	print("Got Exception: " + str(e))
    finally:
      # Close the socket if open
      if s: s.close()
예제 #2
0
  def ping(self):
    """ Create a connection to dummy_host/_port using Socks4 """
    s = None
    try:
      try:
        s = socks.socksocket()
        s.setproxy(socks.PROXY_TYPE_SOCKS4, socks_host, socks_port)
        s.connect((ping_dummy_host, ping_dummy_port))
      except socks.Socks4Error, e:
	# Don't do nothing, this will actually happen
	# print("Got Exception: " + str(e))
	pass
    finally:
      # Close the socket if open
      if s: s.close()
예제 #3
0
    def do_CONNECT(self):
        host, port = (self.path.split(":") + ["80"])[:2]
        port = int(port)
        if SOCKS5_PROXY:
            sock = socks.socksocket()
        else:
            sock = socket.socket()
        try:
            sock.connect((host, port))
        except Exception as e:
            msg = str(e)
            return self.send_error(400, msg)
        self.log_request(200)
        self.wfile.write(b"HTTP/1.1 200 Connection Established\r\n")
        proxy_agent = "Proxy-agent: " + self.version_string() + "\r\n"
        self.wfile.write(proxy_agent.encode("utf-8"))
        self.wfile.write(b"\r\n")

        try:
            bufsize = 32*1024
            lastactive = time.time()
            csock, ssock = self.connection, sock
            csockclosed, ssockclosed = False, False
            cbuf, sbuf = "", ""

            csock.setblocking(0)
            ssock.setblocking(0)
            while True:
                reads = []
                writes = []
                if not cbuf:
                    if not csockclosed:
                        reads.append(csock)
                else:
                    writes.append(ssock)
                if not sbuf:
                    if not ssockclosed:
                        reads.append(ssock)
                else:
                    writes.append(csock)
                if len(reads) == 0 and len(writes) == 0:
                    # Nothing to read and write, this session is done
                    self.log_message("Gracefully shutdown the session")
                    break
                readable, writable, _ = select.select(reads, writes, [], 1)
                for r in readable:
                    data = r.recv(bufsize)
                    if not data:
                        # EOF
                        if r is csock:
                            csockclosed = True
                        else:
                            ssockclosed = True
                        continue
                    if r is csock:
                        cbuf = data
                    else:
                        sbuf = data
                    lastactive = time.time()
                for w in writable:
                    if w is csock:
                        n = csock.send(sbuf)
                        sbuf = sbuf[n:]
                    else:
                        n = ssock.send(cbuf)
                        cbuf = cbuf[n:]
                    lastactive = time.time()
                if time.time() - lastactive > 60:
                    self.log_message("Killing the idle connection")
                    break
        except socket.error:
            pass
        finally:
            ssock.close()
            # Close csock by the web framework
            self.close_connection = 1
예제 #4
0
    def doCommon(self):
        url = self.path
        pieces = urlparse(url)
        if not all((pieces.scheme, pieces.netloc)):
            return self.send_error(400, "Invalid URL to proxy")

        headers = {}
        for k, v in self.headers.items():
            headers[k.lower()] = v
        omittedRequestHeaders = ("accept-encoding", "host", "proxy-connection")
        for k in omittedRequestHeaders:
            if k in headers:
                del headers[k]
        host, port = pieces.hostname, pieces.port
        conn = httplib.HTTPConnection(host=host, port=port)
        if "authorization" not in headers:
            if pieces.username is not None:
                auth = ":".join((pieces.username, pieces.password or ""))
                auth = base64.b64encode(auth.encode("utf-8")).decode("utf-8")
                headers["authorization"] = "Basic " + auth
        if SOCKS5_PROXY:
            sock = socks.socksocket()
            if port is None:
                port = 80
                if pieces.scheme.lower() == "https":
                    port = 443
            sock.connect((host, int(port)))
            conn.sock = sock
        cl = int(self.headers.get("content-length", "0"))
        body = None
        if cl > 0:
            body = BoundedReader(self.rfile, int(cl))
        elif self.headers.get("transfer-encoding") == "chunked":
            body = ChunkedEncodingValidator(self.rfile)
        path = "?".join(filter(None, (pieces.path, pieces.query)))
        conn.request(self.command, path, body, headers)

        res = conn.getresponse()

        # send_response() sends "Server" and "Date" headers as well as the
        # status code. But those headers might already exist in the response
        # of upstream. Thus here we suppress implicit headers from httplib
        # to prefer the value from upstream.
        blacklist = ("server", "date")
        blacklist = [x for x in blacklist if res.getheader(x) is not None]
        self.set_header_blacklist(blacklist)
        self.send_response(res.status)
        self.set_header_blacklist(None)

        chunked = res.getheader("transfer-encoding") == "chunked"
        closeConn = False
        if res.getheader("content-length") is None and not chunked:
            # Close the connection to indicate EOF since the remote server
            # didn't tell the content length and the response was not
            # chunked-encoding.
            closeConn = True

        connection = res.getheader("connection", default="Keep-Alive")
        if closeConn:
            connection = "Close"
        self.send_header("Connection", connection)

        # Forward headers
        omittedResponseHeaders = ("connection",)
        for k, v in res.getheaders():
            if k not in omittedResponseHeaders:
                self.send_header(k, v)
        self.end_headers()

        # Forward content
        bufsize = 32*1024
        while True:
            buf = res.read(bufsize)
            if not buf:
                if chunked:
                    self.wfile.write(b"0\r\n\r\n")
                break
            if chunked:
                l = "%X\r\n" % (len(buf))
                self.wfile.write(l.encode("utf-8"))
                self.wfile.write(buf)
                self.wfile.write(b'\r\n')
            else:
                self.wfile.write(buf)
        if closeConn:
            self.finish()
예제 #5
0
    def run(self):
        def _circuit_handler(event):
            """ Event handler for handling circuit states. """
            if not event.build_flags or 'IS_INTERNAL' not in event.build_flags:
                if event.id == self._cid:
                    probe.circs.append(event)
                    if self._circuit_built.is_set():
                        if event.status in ('FAILED', 'CLOSED'):
                            self._circuit_finished.set()
                    if not self._circuit_built.is_set():
                        if event.status in ('FAILED', 'BUILT'):
                            self._circuit_built.set()
                elif event.status == 'LAUNCHED' and not self._cid:
                    self._cid = event.id
                    probe.circs.append(event)
                    self._manager.circ_launched.release()

        def _stream_probing(event):
            """
            Event handler for detecting start and end of RTT probing streams.
            """
            if event.target_address == self._dest:
                probe.streams.append(event)
                if event.status == 'CLOSED':
                    self._stream_finished.set()
                elif event.status == 'NEW' and event.purpose == 'USER':
                    self._attach_stream(event)

        def _stream_performance(event):
            """ Event handler for detecting start of performance stream. """
            # Make sure we don't handle a probing stream.
            if not event.target_address.startswith('127.'):
                if event.status == 'NEW' and event.purpose == 'USER':
                    self._controller.remove_event_listener(_stream_performance)
                    self._manager.perf_lock.release()
                    self._attach_stream(event)

        def _stream_bw(event):
            """ Event handler for detecting start of bandwidth stream. """
            # Make sure we don't handle a probing stream.
            if not event.target_address.startswith('127.'):
                if event.status == 'NEW' and event.purpose == 'USER':
                    self._controller.remove_event_listener(_stream_bw)
                    self._attach_stream(event)
                    self._manager.bw_lock.release()

        def _cbt_check(event):
            """ Check for CBT message from tor. """
            cbt_m = match('^circuit_send_next_onion_skin\(\): circuit '
                          '([0-9]+) built in ([0-9]+)msec $', (event.message))
            if cbt_m and cbt_m.group(1) == self._cid:
                assert len(probe.cbt) == 0, \
                    'CBT for %s is already set: %d.' % (self._cid, probe.cbt)
                probe.cbt.add(int(cbt_m.group(2)))
                self._cbt_received.set()

        def devnull(body):
            """ Drop Curl output. """
            return

        socks_ip = self._controller.get_socks_listeners()[0][0]
        socks_port = self._controller.get_socks_listeners()[0][1]

        probe = Probe(path=self.path, circs=[], cbt=set(), streams=[],
                      perf=[], bw=[])

        # Build new circuit.
        circ_path = [node.desc.fingerprint for node in self.path]
        # Launching a circuit must be exclusive since we get the circuit
        # identifier from the LAUNCH event.
        self._manager.circ_launched.acquire()
        self._controller.add_event_listener(_circuit_handler, EventType.CIRC)
        self._controller.add_event_listener(_cbt_check, EventType.INFO)
        self._controller.extend_circuit(path=circ_path)
        self._circuit_built.wait()
        build_status = probe.circs[len(probe.circs) - 1].status
        assert build_status == 'BUILT' or build_status == 'FAILED', \
            'Wrong circuit status: %s.' % build_status
        if build_status == 'FAILED':
            self._controller.remove_event_listener(_circuit_handler)
            self._controller.remove_event_listener(_cbt_check)
            self._manager.write(self, probe, self._dest)
            return

        # Make sure CBT has been set
        self._cbt_received.wait()
        self._controller.remove_event_listener(_cbt_check)

        # RTT probe circuit.
        for _ in range(0, self._num_rttprobes):
            self._stream_finished.clear()
            socket = socksocket()
            socket.setproxy(PROXY_TYPE_SOCKS5, socks_ip, socks_port)
            self._controller.add_event_listener(_stream_probing,
                                                EventType.STREAM)
            try:
                socket.connect((self._dest, 80))
            except Socks5Error, error:
                # tor's socks implementation sends a general error response
                # when the Tor protocol is violated.
                # See stream_end_reason_to_socks5_response()
                err = ("(1, 'general SOCKS server failure')",
                       "(5, 'Connection refused')",
                       "(6, 'TTL expired')")
                if str(error) not in err:
                    raise Socks5Error(str(error))
            # Make sure stream has been closed.
            self._stream_finished.wait()
            self._controller.remove_event_listener(_stream_probing)
            socket.close()
예제 #6
0
    def run(self):
        def _circuit_handler(event):
            """ Event handler for handling circuit states. """
            if not event.build_flags or 'IS_INTERNAL' not in event.build_flags:
                if event.id == self._cid:
                    probe.circs.append(event)
                    if self._circuit_built.is_set():
                        if event.status in ('FAILED', 'CLOSED'):
                            self._circuit_finished.set()
                    if not self._circuit_built.is_set():
                        if event.status in ('FAILED', 'BUILT'):
                            self._circuit_built.set()
                elif event.status == 'LAUNCHED' and not self._cid:
                    self._cid = event.id
                    probe.circs.append(event)
                    self._manager.circ_launched.release()

        def _stream_probing(event):
            """
            Event handler for detecting start and end of RTT probing streams.
            """
            if event.target_address == self._dest:
                probe.streams.append(event)
                if event.status == 'CLOSED':
                    self._stream_finished.set()
                elif event.status == 'NEW' and event.purpose == 'USER':
                    self._attach_stream(event)

        def _stream_performance(event):
            """ Event handler for detecting start of performance stream. """
            # Make sure we don't handle a probing stream.
            if not event.target_address.startswith('127.'):
                if event.status == 'NEW' and event.purpose == 'USER':
                    self._controller.remove_event_listener(_stream_performance)
                    self._manager.perf_lock.release()
                    self._attach_stream(event)

        def _stream_bw(event):
            """ Event handler for detecting start of bandwidth stream. """
            # Make sure we don't handle a probing stream.
            if not event.target_address.startswith('127.'):
                if event.status == 'NEW' and event.purpose == 'USER':
                    self._controller.remove_event_listener(_stream_bw)
                    self._attach_stream(event)
                    self._manager.bw_lock.release()

        def _cbt_check(event):
            """ Check for CBT message from tor. """
            cbt_m = match(
                '^circuit_send_next_onion_skin\(\): circuit '
                '([0-9]+) built in ([0-9]+)msec $', (event.message))
            if cbt_m and cbt_m.group(1) == self._cid:
                assert len(probe.cbt) == 0, \
                    'CBT for %s is already set: %d.' % (self._cid, probe.cbt)
                probe.cbt.add(int(cbt_m.group(2)))
                self._cbt_received.set()

        def devnull(body):
            """ Drop Curl output. """
            return

        socks_ip = self._controller.get_socks_listeners()[0][0]
        socks_port = self._controller.get_socks_listeners()[0][1]

        probe = Probe(path=self.path,
                      circs=[],
                      cbt=set(),
                      streams=[],
                      perf=[],
                      bw=[])

        # Build new circuit.
        circ_path = [node.desc.fingerprint for node in self.path]
        # Launching a circuit must be exclusive since we get the circuit
        # identifier from the LAUNCH event.
        self._manager.circ_launched.acquire()
        self._controller.add_event_listener(_circuit_handler, EventType.CIRC)
        self._controller.add_event_listener(_cbt_check, EventType.INFO)
        self._controller.extend_circuit(path=circ_path)
        self._circuit_built.wait()
        build_status = probe.circs[len(probe.circs) - 1].status
        assert build_status == 'BUILT' or build_status == 'FAILED', \
            'Wrong circuit status: %s.' % build_status
        if build_status == 'FAILED':
            self._controller.remove_event_listener(_circuit_handler)
            self._controller.remove_event_listener(_cbt_check)
            self._manager.write(self, probe, self._dest)
            return

        # Make sure CBT has been set
        self._cbt_received.wait()
        self._controller.remove_event_listener(_cbt_check)

        # RTT probe circuit.
        for _ in range(0, self._num_rttprobes):
            self._stream_finished.clear()
            socket = socksocket()
            socket.setproxy(PROXY_TYPE_SOCKS5, socks_ip, socks_port)
            self._controller.add_event_listener(_stream_probing,
                                                EventType.STREAM)
            try:
                socket.connect((self._dest, 80))
            except Socks5Error, error:
                # tor's socks implementation sends a general error response
                # when the Tor protocol is violated.
                # See stream_end_reason_to_socks5_response()
                err = ("(1, 'general SOCKS server failure')",
                       "(5, 'Connection refused')", "(6, 'TTL expired')")
                if str(error) not in err:
                    raise Socks5Error(str(error))
            # Make sure stream has been closed.
            self._stream_finished.wait()
            self._controller.remove_event_listener(_stream_probing)
            socket.close()