Example #1
0
    def get_location(self):
        if time.time() - self.last_ckeck < 60:
            return
        ip = ip_address(socket.getaddrinfo(self.parse.hostname, 0)[0][4][0])

        if ip.is_loopback or ip.is_private:
            from connection import create_connection
            from httputil import read_reaponse_line, read_headers
            try:
                soc = create_connection(('bot.whatismyipaddress.com', 80), ctimeout=None, parentproxy=self, via=self.via)
                soc.sendall(b'GET / HTTP/1.1\r\nConnection: close\r\nHost: bot.whatismyipaddress.com\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\r\n\r\n')
                f = soc.makefile()
                line, version, status, reason = read_reaponse_line(f)
                _, headers = read_headers(f)
                assert status == 200
                ip = soc.recv(int(headers['Content-Length']))
                if not ip:
                    soc.close()
                    raise ValueError('%s: ip address is empty' % self.name)
                self.country_code = ip_to_country_code(ip)
                soc.close()
            except Exception:
                sys.stderr.write(traceback.format_exc())
                sys.stderr.flush()
                self.country_code = None
        else:
            self.country_code = ip_to_country_code(ip)
        self.last_ckeck = time.time()
Example #2
0
    def get_location(self):
        if self.country_code:
            return self.country_code
        if time.time() - self.last_ckeck < 300:
            return self.country_code
        try:
            self.last_ckeck = time.time()
            ip = ip_address(socket.getaddrinfo(self.parse.hostname, 0)[0][4][0])

            if ip.is_loopback or ip.is_private:
                from connection import create_connection
                from httputil import read_reaponse_line, read_headers
                try:
                    soc = create_connection(('bot.whatismyipaddress.com', 80), ctimeout=None, parentproxy=self)
                    soc.sendall(b'GET / HTTP/1.1\r\nConnection: keep_alive\r\nHost: bot.whatismyipaddress.com\r\nAccept-Encoding: identity\r\nUser-Agent: Python-urllib/2.7\r\n\r\n')
                    f = soc.makefile()
                    line, version, status, reason = read_reaponse_line(f)
                    _, headers = read_headers(f)
                    assert status == 200
                    ip = soc.recv(int(headers['Content-Length']))
                    if not ip:
                        soc.close()
                        raise ValueError('%s: ip address is empty' % self.name)
                    self.country_code = ip_to_country_code(ip)
                    soc.close()
                except Exception:
                    sys.stderr.write(traceback.format_exc())
                    sys.stderr.flush()
                    self.country_code = None
            else:
                self.country_code = ip_to_country_code(ip)
        finally:
            return self.country_code
Example #3
0
    def get_location(self):
        if time.time() - self.last_ckeck < 60:
            return
        ip = ip_address(socket.getaddrinfo(self.parse.hostname, 0)[0][4][0])

        if ip.is_loopback or ip.is_private:
            from connection import create_connection
            from httputil import read_reaponse_line, read_headers
            try:
                soc = create_connection(('bot.whatismyipaddress.com', 80),
                                        ctimeout=None,
                                        parentproxy=self)
                soc.sendall(
                    b'GET / HTTP/1.1\r\nConnection: close\r\nHost: bot.whatismyipaddress.com\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0\r\n\r\n'
                )
                f = soc.makefile()
                line, version, status, reason = read_reaponse_line(f)
                _, headers = read_headers(f)
                assert status == 200
                ip = soc.recv(int(headers['Content-Length']))
                if not ip:
                    soc.close()
                    raise ValueError('%s: ip address is empty' % self.name)
                self.country_code = ip_to_country_code(ip)
                soc.close()
            except Exception:
                sys.stderr.write(traceback.format_exc())
                sys.stderr.flush()
                self.country_code = None
        else:
            self.country_code = ip_to_country_code(ip)
        self.last_ckeck = time.time()
Example #4
0
def do_tunnel(soc, netloc, pp):
    s = ['CONNECT %s:%s HTTP/1.1\r\n' % (netloc[0], netloc[1]), ]
    if pp.username:
        a = '%s:%s' % (pp.username, pp.password)
        s.append('Proxy-Authorization: Basic %s\r\n' % base64.b64encode(a.encode()))
    s.append('Host: %s:%s\r\n\r\n' % (netloc[0], netloc[1]))
    soc.sendall(''.join(s).encode())
    remoterfile = soc.makefile('rb', 0)
    line, version, status, reason = read_reaponse_line(remoterfile)
    if status != 200:
        raise IOError(0, 'create tunnel via %s failed!' % pp.name)
    read_header_data(remoterfile)
Example #5
0
def do_tunnel(soc, netloc, pp):
    s = [
        'CONNECT %s:%s HTTP/1.1\r\n' % (netloc[0], netloc[1]),
    ]
    if pp.username:
        a = '%s:%s' % (pp.username, pp.password)
        s.append('Proxy-Authorization: Basic %s\r\n' %
                 base64.b64encode(a.encode()))
    s.append('Host: %s:%s\r\n\r\n' % (netloc[0], netloc[1]))
    soc.sendall(''.join(s).encode())
    remoterfile = soc.makefile('rb', 0)
    line, version, status, reason = read_reaponse_line(remoterfile)
    if status != 200:
        raise IOError(0, 'create tunnel via %s failed!' % pp.name)
    read_header_data(remoterfile)
Example #6
0
 def get_location(self):
     if time.time() - self.last_ckeck < 60:
         return
     from connection import create_connection
     from httputil import read_reaponse_line, read_headers
     try:
         soc = create_connection(('bot.whatismyipaddress.com', 80), ctimeout=None, parentproxy=self, via=self.via)
         soc.sendall(b'GET / HTTP/1.0\r\nHost: bot.whatismyipaddress.com\r\n\r\n')
         f = soc.makefile()
         line, version, status, reason = read_reaponse_line(f)
         _, headers = read_headers(f)
         assert status == 200
         ip = soc.recv(int(headers['Content-Length']))
         if not ip:
             soc.close()
             raise ValueError('%s: ip address is empty' % self.name)
         self.country_code = ip_to_country_code(ip)
         soc.close()
     except Exception as e:
         sys.stderr.write(traceback.format_exc())
         sys.stderr.flush()
         self.country_code = None
     self.last_ckeck = time.time()
Example #7
0
    def _do_GET(self, retry=False):
        try:
            if retry:
                if self.remotesoc:
                    try:
                        self.remotesoc.close()
                    except:
                        pass
                    self.remotesoc = None
                self.failed_parents.append(self.ppname)
                self.count += 1
                if self.count > 10:
                    self.logger.error('for some strange reason retry time exceeded 10, pls check!')
                    return
            if not self.retryable:
                self.close_connection = 1
                self.conf.PARENT_PROXY.notify(self.command, self.shortpath, self.requesthost, False, self.failed_parents, self.ppname)
                return
            if self.getparent():
                self.conf.PARENT_PROXY.notify(self.command, self.shortpath, self.requesthost, False, self.failed_parents, self.ppname)
                return self.send_error(504)

            self.upstream_name = self.ppname if self.pproxy.proxy.startswith('http') else self.requesthost
            iplist = None
            if self.pproxy.name == 'direct' and self.requesthost[0] in self.conf.HOSTS and not self.failed_parents:
                iplist = self.conf.HOSTS.get(self.requesthost[0])
                self._proxylist.insert(0, self.pproxy)
            self.set_timeout()
            self.phase = 'http_connect_via_proxy'
            self.remotesoc = self._http_connect_via_proxy(self.requesthost, iplist)
            self.wbuffer = deque()
            self.wbuffer_size = 0
            # send request header
            self.phase = 'sending request header'
            s = []
            if self.pproxy.proxy.startswith('http'):
                path = self.path
                if iplist:
                    path = self.path.split('/')
                    path[2] = '%s%s' % (iplist[0][1], ((':%d' % self.requesthost[1]) if self.requesthost[1] != 80 else ''))
                    path = ''.join(path)
                s.append('%s %s %s\r\n' % (self.command, self.path, self.request_version))
                if self.pproxy.username:
                    a = '%s:%s' % (self.pproxy.username, self.pproxy.password)
                    self.headers['Proxy-Authorization'] = 'Basic %s' % base64.b64encode(a.encode())
            else:
                s.append('%s /%s %s\r\n' % (self.command, '/'.join(self.path.split('/')[3:]), self.request_version))
            # Does the client want to close connection after this request?
            conntype = self.headers.get('Connection', "")
            if self.request_version >= b"HTTP/1.1":
                client_close = 'close' in conntype.lower()
            else:
                client_close = 'keep_alive' in conntype.lower()
            if 'Upgrade' in self.headers:
                if 'websocket' in self.headers['Upgrade']:
                    self.headers['Upgrade'] = 'websocket'
                    client_close = True
                else:
                    self.logger.warning('Upgrade header found! (%s), FW-Lite do not support this...' % self.headers['Upgrade'])
                    del self.headers['Upgrade']
            else:
                self.headers['Connection'] = 'keep_alive'
            del self.headers['Proxy-Connection']
            for k, v in self.headers.items():
                if isinstance(v, bytes):
                    v = v.decode('latin1')
                s.append("%s: %s\r\n" % ("-".join([w.capitalize() for w in k.split("-")]), v))
            s.append("\r\n")
            data = ''.join(s).encode('latin1')
            self.remotesoc.sendall(data)
            self.traffic_count[0] += len(data)
            # Now remotesoc is connected, set read timeout
            self.remotesoc.settimeout(self.rtimeout)
            remoterfile = self.remotesoc.makefile('rb', 0)
            # Expect
            skip = False
            if 'Expect' in self.headers:
                try:
                    response_line, protocol_version, response_status, response_reason = read_reaponse_line(remoterfile)
                except Exception as e:
                    # TODO: probably the server don't handle Expect well.
                    self.logger.warning('read response line error: %r' % e)
                else:
                    if response_status == 100:
                        hdata = read_header_data(remoterfile)
                        self._wfile_write(response_line + hdata)
                    else:
                        skip = True
            # send request body
            if not skip:
                self.phase = 'sending request body'
                content_length = int(self.headers.get('Content-Length', 0))
                if self.headers.get("Transfer-Encoding") and self.headers.get("Transfer-Encoding") != "identity":
                    if self.rbuffer:
                        self.remotesoc.sendall(b''.join(self.rbuffer))
                    flag = 1
                    req_body_len = 0
                    while flag:
                        trunk_lenth = self.rfile_readline()
                        if self.retryable:
                            self.rbuffer.append(trunk_lenth)
                            req_body_len += len(trunk_lenth)
                        self.remotesoc.sendall(trunk_lenth)
                        trunk_lenth = int(trunk_lenth.strip(), 16) + 2
                        flag = trunk_lenth != 2
                        data = self.rfile_read(trunk_lenth)
                        if self.retryable:
                            self.rbuffer.append(data)
                            req_body_len += len(data)
                        self.remotesoc.sendall(data)
                        if req_body_len > 102400:
                            self.retryable = False
                            self.rbuffer = deque()
                elif content_length > 0:
                    if content_length > 102400:
                        self.retryable = False
                    if self.rbuffer:
                        s = b''.join(self.rbuffer)
                        content_length -= len(s)
                        self.remotesoc.sendall(s)
                    while content_length:
                        data = self.rfile_read(min(self.bufsize, content_length))
                        if not data:
                            break
                        content_length -= len(data)
                        if self.retryable:
                            self.rbuffer.append(data)
                        self.remotesoc.sendall(data)
                # read response line
                timelog = time.clock()
                self.phase = 'reading response_line'
                response_line, protocol_version, response_status, response_reason = read_reaponse_line(remoterfile)
                rtime = time.clock() - timelog
            # read response headers
            while response_status == 100:
                hdata = read_header_data(remoterfile)
                self._wfile_write(response_line + hdata)
                response_line, protocol_version, response_status, response_reason = read_reaponse_line(remoterfile)
            self.phase = 'reading response header'
            header_data, response_header = read_headers(remoterfile)
            conntype = response_header.get('Connection', "")
            if protocol_version >= b"HTTP/1.1":
                remote_close = 'close' in conntype.lower()
            else:
                remote_close = 'keep_alive' in conntype.lower()
            if 'Upgrade' in response_header:
                remote_close = True
            if "Content-Length" in response_header:
                if "," in response_header["Content-Length"]:
                    # Proxies sometimes cause Content-Length headers to get
                    # duplicated.  If all the values are identical then we can
                    # use them but if they differ it's an error.
                    pieces = re.split(r',\s*', response_header["Content-Length"])
                    if any(i != pieces[0] for i in pieces):
                        raise ValueError("Multiple unequal Content-Lengths: %r" %
                                         response_header["Content-Length"])
                    response_header["Content-Length"] = pieces[0]
                content_length = int(response_header["Content-Length"])
            else:
                content_length = None
            buf = io.BytesIO(header_data)
            header_data = b''
            for line in buf:
                if line.startswith('Connection') and 'Upgrade' not in line:
                    header_data += b'Connection: close\r\n' if client_close else b'Connection: keep_alive\r\n'
                else:
                    header_data += line
            self.wfile_write(response_line)
            self.wfile_write(header_data)
            # verify
            if response_status in (301, 302) and self.conf.PARENT_PROXY.bad302(response_header.get('Location')):
                raise IOError(0, 'Bad 302!')
            # read response body
            self.phase = 'reading response body'
            if self.command == 'HEAD' or response_status in (204, 205, 304):
                pass
            elif response_header.get("Transfer-Encoding") and response_header.get("Transfer-Encoding") != "identity":
                flag = 1
                while flag:
                    trunk_lenth = remoterfile.readline()
                    self.wfile_write(trunk_lenth)
                    trunk_lenth = int(trunk_lenth.strip(), 16) + 2
                    flag = trunk_lenth != 2
                    while trunk_lenth:
                        data = self.remotesoc.recv(min(self.bufsize, trunk_lenth))
                        trunk_lenth -= len(data)
                        self.wfile_write(data)
            elif content_length is not None:
                while content_length:
                    data = self.remotesoc.recv(min(self.bufsize, content_length))
                    if not data:
                        raise IOError(0, 'remote socket closed')
                    content_length -= len(data)
                    self.wfile_write(data)
            else:
                # websocket?
                self.close_connection = 1
                self.retryable = False
                self.wfile_write()
                fd = [self.connection, self.remotesoc]
                while fd:
                    ins, _, _ = select.select(fd, [], [], 60)
                    if not ins:
                        break
                    if self.connection in ins:
                        data = self.connection_recv(self.bufsize)
                        if data:
                            self.remotesoc.sendall(data)
                        else:
                            fd.remove(self.connection)
                            self.remotesoc.shutdown(socket.SHUT_WR)
                    if self.remotesoc in ins:
                        data = self.remotesoc.recv(self.bufsize)
                        if data:
                            self._wfile_write(data)
                        else:
                            fd.remove(self.remotesoc)
                            self.connection.shutdown(socket.SHUT_WR)
            self.wfile_write()
            self.phase = 'request finish'
            self.conf.PARENT_PROXY.notify(self.command, self.shortpath, self.requesthost, True if response_status < 400 else False, self.failed_parents, self.ppname, rtime)
            self.pproxy.log(self.requesthost[0], rtime)
            if remote_close or is_connection_dropped([self.remotesoc]):
                self.remotesoc.close()
            else:
                self.HTTPCONN_POOL.put(self.upstream_name, self.remotesoc, self.ppname if '(pooled)' in self.ppname else (self.ppname + '(pooled)'))
            self.remotesoc = None
        except ClientError as e:
            raise
        except NetWorkIOError as e:
            return self.on_GET_Error(e)