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()
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()
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
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()
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()
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()