Example #1
0
def handle_ip_proxy(sock, ip, port, client_address):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    rule = g.user_rules.check_host(ip, port)
    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        return try_loop("ip user", [rule], sock, ip, port, client_address)

    try:
        host = get_sni(sock)
        return handle_domain_proxy(sock, host, port, client_address)
    except SniNotExist as e:
        xlog.debug("ip:%s:%d get sni fail", ip, port)

    record = g.ip_cache.get(ip)
    if record and record["r"] == "socks":
        rule_list = ["socks"]
    else:
        rule_list = ["direct", "socks"]

    try_loop("ip", rule_list, sock, ip, port, client_address)
Example #2
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    sock.target = "%s:%d" % (host, port)
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == "www.twitter.com":
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        return try_loop("domain user", [rule], sock, host, port, client_address, left_buf)

    record = g.domain_cache.get(host)
    if record:
        rule = record["r"]
        if rule == "gae":
            rule_list = ["gae", "socks", "redirect_https", "direct"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

        if not g.domain_cache.accept_gae(host):
            rule_list.remove("gae")
    elif g.gfwlist.check(host):
        rule_list = ["gae", "socks", "redirect_https", "direct"]
    else:
        rule_list = ["direct", "gae", "socks", "redirect_https"]

    try_loop("domain", rule_list, sock, host, port, client_address, left_buf)
Example #3
0
    def try_redirect(self):
        if not self.support_redirect:
            return False

        try:
            dst = self.conn.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
        except:
            self.support_redirect = False
            return False

        try:
            dst_port, srv_ip = struct.unpack("!2xH4s8x", dst)
            ip_str = socket.inet_ntoa(srv_ip)
            if dst_port != g.config.proxy_port and not utils.is_private_ip(
                    ip_str):
                xlog.debug("Redirect to:%s:%d from:%s", ip_str, dst_port,
                           self.client_address)
                handle_ip_proxy(self.conn, ip_str, dst_port,
                                self.client_address)
                return True
            else:
                return False
        except Exception as e:
            xlog.exception("redirect except:%r", e)

        return True
Example #4
0
def handle_ip_proxy(sock, ip, port, client_address):
    sock = SocketWrap(sock, client_address[0], client_address[1])
    rule = g.user_rules.check_host(ip, port)
    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        if rule == "direct":
            try:
                do_direct(sock, ip, [ip], port, client_address)
                xlog.info("host:%s:%d user direct", ip, port)
            except ConnectFail:
                xlog.warn("ip:%s:%d user rule:%s connect fail", ip, port, rule)
                sock.close()
            return
        elif rule == "socks":
            do_socks(sock, ip, port, client_address)
            xlog.info("host:%s:%d user socks", ip, port)
            return
        elif rule == "black":
            xlog.info("ip:%s:%d user rule:%s", ip, port, rule)
            sock.close()
            return
        else:
            xlog.error("get rule:%s unknown", rule)
            sock.close()
            return

    try:
        host = get_sni(sock)
        return handle_domain_proxy(sock, host, port, client_address)
    except SniNotExist as e:
        xlog.debug("ip:%s:%d get sni fail", ip, port)

    record = g.ip_cache.get(ip)
    if record:
        rule = record["r"]
    else:
        rule = "direct"

    if rule == "direct":
        try:
            do_direct(sock, ip, [ip], port, client_address)
            xlog.info("host:%s:%d direct", ip, port)
            return
        except ConnectFail:
            xlog.debug("%s:%d try direct fail", ip, port)
            rule = "socks"
            g.ip_cache.update_rule(ip, port, "socks")
    if rule == "socks":
        do_socks(sock, ip, port, client_address)
        xlog.info("host:%s:%d socks", ip, port)
        return

    xlog.error("get rule:%s unknown", rule)
    sock.close()
    return
Example #5
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    global fake_host
    if not fake_host and g.gae_proxy:
        fake_host = g.gae_proxy.web_control.get_fake_host()

    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    sock.target = "%s:%d" % (host, port)
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == fake_host:
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        return try_loop("domain user", [rule], sock, host, port,
                        client_address, left_buf)

    record = g.domain_cache.get(host)
    ips = g.dns_srv.query(host)

    if check_local_network.IPv6.is_ok() and have_ipv6(ips):
        rule_list = ["direct", "gae", "socks", "redirect_https"]
    elif record:
        rule = record["r"]
        if rule == "gae" or not g.ip_region.check_ips(record["ip"]):
            rule_list = ["gae", "socks", "redirect_https", "direct"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

        if not g.domain_cache.accept_gae(host):
            rule_list.remove("gae")
    elif g.gfwlist.check(host):
        rule_list = ["gae", "socks", "redirect_https", "direct"]
    else:
        ips = g.dns_srv.query(host)
        if g.ip_region.check_ips(ips):
            rule_list = ["direct", "gae", "socks", "redirect_https"]
        else:
            rule_list = ["gae", "socks", "redirect_https", "direct"]

    if not g.config.auto_direct and "direct" in rule_list:
        try:
            rule_list.remove("direct")
            rule_list.remove("redirect_https")
        except:
            pass

    if not g.config.auto_gae and "gae" in rule_list:
        try:
            rule_list.remove("gae")
        except:
            pass

    try_loop("domain", rule_list, sock, host, port, client_address, left_buf)
Example #6
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    global fake_host
    if not fake_host and g.gae_proxy:
        fake_host = g.gae_proxy.web_control.get_fake_host()

    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    sock.target = "%s:%d" % (host, port)
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == fake_host:
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        return try_loop("domain user", [rule], sock, host, port, client_address, left_buf)

    record = g.domain_cache.get(host)
    ips = g.dns_srv.query(host)

    if check_local_network.IPv6.is_ok() and have_ipv6(ips):
        rule_list = ["direct", "gae", "socks", "redirect_https"]
    elif record:
        rule = record["r"]
        if rule == "gae" or not g.ip_region.check_ips(record["ip"]):
            rule_list = ["gae", "socks", "redirect_https", "direct"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

        if not g.domain_cache.accept_gae(host):
            rule_list.remove("gae")
    elif g.gfwlist.check(host):
        rule_list = ["gae", "socks", "redirect_https", "direct"]
    else:
        ips = g.dns_srv.query(host)
        if g.ip_region.check_ips(ips):
            rule_list = ["direct", "gae", "socks", "redirect_https"]
        else:
            rule_list = ["gae", "socks", "redirect_https", "direct"]

    if not g.config.auto_direct and "direct" in rule_list:
        try:
            rule_list.remove("direct")
            rule_list.remove("redirect_https")
        except:
            pass

    if not g.config.auto_gae and "gae" in rule_list:
        try:
            rule_list.remove("gae")
        except:
            pass

    try_loop("domain", rule_list, sock, host, port, client_address, left_buf)
Example #7
0
 def cn_query(self, cn_host, client_ip) -> map:
     url_template = 'http://119.29.29.29/d?dn={}&ip={}'
     if is_private_ip(client_ip):
         url = url_template.format(cn_host, '')
     else:
         url = url_template.format(cn_host, client_ip)
     r = self.s_cn.get(url)
     result = r.text.split(';')[0]
     ip = result if result else ''
     ttl = 3600
     return make_resp(cn_host, ip, ttl)
Example #8
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    global fake_host
    if not fake_host and g.gae_proxy:
        fake_host = g.gae_proxy.web_control.get_fake_host()

    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    sock.target = "%s:%d" % (host, port)
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == fake_host:
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        return try_loop("domain user", [rule], sock, host, port,
                        client_address, left_buf)

    if g.config.block_advertisement and g.gfwlist.is_advertisement(host):
        xlog.info("block advertisement %s:%d", host, port)
        sock.close()
        return

    #ips = g.dns_srv.query(host)
    #if check_local_network.IPv6.is_ok() and have_ipv6(ips) and port == 443:
    #    rule_list = ["direct", "gae", "socks", "redirect_https"]
    # gae is more faster then direct.

    record = g.domain_cache.get(host)
    if record and record["r"] != "unknown":
        rule = record["r"]
        if rule == "gae":
            rule_list = ["gae", "socks", "redirect_https", "direct"]
        elif rule == "socks":
            rule_list = ["socks", "gae", "redirect_https", "direct"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

        if not g.domain_cache.accept_gae(host):
            rule_list.remove("gae")
    elif g.gfwlist.is_white(host):
        rule_list = ["direct", "gae", "socks", "redirect_https"]
    elif g.gfwlist.check(host):
        rule_list = ["gae", "socks", "redirect_https", "direct"]
    else:
        ips = g.dns_srv.query(host)
        if g.ip_region.check_ips(ips):
            rule_list = ["direct", "socks", "redirect_https"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

    try_loop("domain", rule_list, sock, host, port, client_address, left_buf)
Example #9
0
def handle_ip_proxy(sock, ip, port, client_address):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    rule = g.user_rules.check_host(ip, port)
    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        return try_loop("ip user", [rule], sock, ip, port, client_address)

    try:
        host = get_sni(sock)
        if host:
            ips = g.dns_srv.query(host)
            if not ips:
                cn = "CN" if g.ip_region.check_ip(ip) else "XX"
                ips.append("%s|%s" % (ip, cn))
                g.domain_cache.set_ips(host, ips)
            return handle_domain_proxy(sock, host, port, client_address)
    except SniNotExist as e:
        xlog.debug("ip:%s:%d get sni fail", ip, port)

    record = g.ip_cache.get(ip)
    if record and record["r"] != "unknown":
        rule = record["r"]
        if rule == "gae":
            rule_list = ["gae", "socks", "direct"]
        elif rule == "socks":
            rule_list = ["socks", "gae", "direct"]
        else:
            rule_list = ["direct", "gae", "socks"]
    elif g.ip_region.check_ip(ip):
        rule_list = ["direct", "socks"]
    else:
        rule_list = ["direct", "gae", "socks"]

    if not g.config.auto_direct:
        for rule in ["direct", "redirect_https"]:
            try:
                rule_list.remove(rule)
            except:
                pass
    elif g.config.auto_direct6 and "direct" in rule_list:
        rule_list.insert(rule_list.index("direct"), "direct6")

    if not g.config.enable_fake_ca and port == 443 or not g.config.auto_gae:
        try:
            rule_list.remove("gae")
        except:
            pass

    try_loop("ip", rule_list, sock, ip, port, client_address)
Example #10
0
    def close(self, s1, e):
        if s1 not in self.sock_dict:
            # xlog.warn("sock not in dict")
            return

        s2 = self.sock_dict[s1]
        if s1 in self.send_buf:
            left1 = self.send_buf[s1].size
        else:
            left1 = 0

        if utils.is_private_ip(s1.ip):
            local_sock = s1
            remote_sock = s2
        else:
            local_sock = s2
            remote_sock = s1

        create_time = time.time() - remote_sock.create_time
        xlog.debug(
            "pipe close %s->%s run_time:%d upload:%d,%d download:%d,%d, by remote:%d, left:%d e:%r",
            local_sock, remote_sock, create_time, local_sock.recved_data,
            local_sock.recved_times, remote_sock.recved_data,
            remote_sock.recved_times, s1 == remote_sock, left1, e)

        if local_sock.recved_data > 0 and local_sock.recved_times == 1 and remote_sock.port == 443 and \
                ((s1 == local_sock and create_time > 30) or (s1 == remote_sock)):
            host = remote_sock.host
            xlog.debug("SNI:%s fail.", host)
            #g.domain_cache.update_rule(host, 443, "gae")

        del self.sock_dict[s1]
        self.try_remove(self.read_set, s1)
        self.try_remove(self.write_set, s1)
        self.try_remove(self.error_set, s1)
        if s1 in self.send_buf:
            del self.send_buf[s1]
        s1.close()

        if s2 in self.send_buf and self.send_buf[s2].size:
            xlog.debug("pipe close %s e:%s, but s2:%s have data(%d) to send",
                       s1, e, s2, self.send_buf[s2].size)
            self.send_buf[s2].add("")
            return

        if s2 in self.sock_dict:
            self.try_remove(self.read_set, s2)
            self.try_remove(self.write_set, s2)
            self.try_remove(self.error_set, s2)
            del self.sock_dict[s2]
            if s2 in self.send_buf:
                del self.send_buf[s2]
            s2.close()
Example #11
0
    def close(self, s1, e):
        if s1 not in self.sock_dict:
            # xlog.warn("sock not in dict")
            return

        s2 = self.sock_dict[s1]
        if s1 in self.send_buf:
            left1 = self.send_buf[s1].size
        else:
            left1 = 0

        if utils.is_private_ip(s1.ip):
            local_sock = s1
            remote_sock = s2
        else:
            local_sock = s2
            remote_sock = s1

        create_time = time.time() - remote_sock.create_time
        xlog.debug("pipe close %s->%s run_time:%d upload:%d,%d download:%d,%d, by remote:%d, left:%d e:%r",
                   local_sock, remote_sock, create_time,
                   local_sock.recved_data, local_sock.recved_times,
                   remote_sock.recved_data, remote_sock.recved_times,
                   s1==remote_sock, left1, e)

        if local_sock.recved_data > 0 and local_sock.recved_times == 1 and remote_sock.port == 443 and \
                ((s1 == local_sock and create_time > 30) or (s1 == remote_sock)):
            host = remote_sock.host
            xlog.debug("SNI:%s fail.", host)
            #g.domain_cache.update_rule(host, 443, "gae")

        del self.sock_dict[s1]
        self.try_remove(self.read_set, s1)
        self.try_remove(self.write_set, s1)
        self.try_remove(self.error_set, s1)
        if s1 in self.send_buf:
            del self.send_buf[s1]
        s1.close()

        if s2 in self.send_buf and self.send_buf[s2].size:
            xlog.debug("pipe close %s e:%s, but s2:%s have data(%d) to send",
                       s1, e, s2, self.send_buf[s2].size)
            self.send_buf[s2].add("")
            return

        if s2 in self.sock_dict:
            self.try_remove(self.read_set, s2)
            self.try_remove(self.write_set, s2)
            self.try_remove(self.error_set, s2)
            del self.sock_dict[s2]
            if s2 in self.send_buf:
                del self.send_buf[s2]
            s2.close()
Example #12
0
    def close(self, s1, e):
        # xlog.debug("%s close", s1)
        if s1 not in self.sock_dict:
            # xlog.warn("sock not in dict")
            return

        s2 = self.sock_dict[s1]

        if utils.is_private_ip(s1.ip):
            local_sock = s1
            remote_sock = s2
        else:
            local_sock = s2
            remote_sock = s1

        create_time = time.time() - remote_sock.create_time
        xlog.debug(
            "pipe close %s->%s run_time:%.2f upload:%d(%d)->%d(%d) download:%d(%d)->%d(%d), by remote:%d, server left:%d client left:%d e:%r",
            local_sock, remote_sock, create_time, local_sock.recved_data,
            local_sock.recved_times, remote_sock.sent_data,
            remote_sock.sent_times, remote_sock.recved_data,
            remote_sock.recved_times, local_sock.sent_data,
            local_sock.sent_times, s1 == remote_sock, remote_sock.buf_size,
            local_sock.buf_size, e)

        if local_sock.recved_data > 0 and local_sock.recved_times == 1 and remote_sock.port == 443 and \
                ((s1 == local_sock and create_time > 30) or (s1 == remote_sock)):
            host = remote_sock.host
            xlog.debug("SNI:%s fail.", host)
            #g.domain_cache.update_rule(host, 443, "gae")

        del self.sock_dict[s1]
        self.try_remove(self.read_set, s1)
        self.try_remove(self.write_set, s1)
        self.try_remove(self.error_set, s1)
        s1.close()

        if s2.buf_size:
            xlog.debug("pipe close %s e:%s, but s2:%s have data(%d) to send",
                       s1, e, s2, s2.buf_size)
            s2.add_dat("")  # add empty block to close socket.
            return

        if s2 in self.sock_dict:
            del self.sock_dict[s2]
            self.try_remove(self.read_set, s2)
            self.try_remove(self.write_set, s2)
            self.try_remove(self.error_set, s2)
            s2.close()
Example #13
0
def handle_ip_proxy(sock, ip, port, client_address):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    rule = g.user_rules.check_host(ip, port)
    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        return try_loop("ip user", [rule], sock, ip, port, client_address)

    if g.config.auto_direct and g.ip_region.check_ip(ip):
        rule_list = ["direct", "gae", "socks", "redirect_https"]
    else:
        if g.config.auto_direct or g.config.auto_gae:
            try:
                host = get_sni(sock)
                if host:
                    return handle_domain_proxy(sock, host, port,
                                               client_address)
            except SniNotExist as e:
                xlog.debug("ip:%s:%d get sni fail", ip, port)

        if not g.config.auto_direct:
            rule_list = ["socks"]
        else:
            record = g.ip_cache.get(ip)
            if record and record["r"] == "socks":
                rule_list = ["socks"]
            else:
                rule_list = ["direct", "socks"]

    if not g.config.auto_direct and "direct" in rule_list:
        try:
            rule_list.remove("direct")
            rule_list.remove("redirect_https")
        except:
            pass

    if not g.config.auto_gae and "gae" in rule_list:
        try:
            rule_list.remove("gae")
        except:
            pass

    try_loop("ip", rule_list, sock, ip, port, client_address)
Example #14
0
def handle_ip_proxy(sock, ip, port, client_address):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    rule = g.user_rules.check_host(ip, port)
    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        return try_loop("ip user", [rule], sock, ip, port, client_address)

    if g.config.auto_direct and g.ip_region.check_ip(ip):
        rule_list = ["direct", "gae", "socks", "redirect_https"]
    else:
        if g.config.auto_direct or g.config.auto_gae:
            try:
                host = get_sni(sock)
                if host:
                    return handle_domain_proxy(sock, host, port, client_address)
            except SniNotExist as e:
                xlog.debug("ip:%s:%d get sni fail", ip, port)

        if not g.config.auto_direct:
            rule_list = ["socks"]
        else:
            record = g.ip_cache.get(ip)
            if record and record["r"] == "socks":
                rule_list = ["socks"]
            else:
                rule_list = ["direct", "socks"]

    if not g.config.auto_direct and "direct" in rule_list:
        try:
            rule_list.remove("direct")
            rule_list.remove("redirect_https")
        except:
            pass

    if not g.config.auto_gae and "gae" in rule_list:
        try:
            rule_list.remove("gae")
        except:
            pass

    try_loop("ip", rule_list, sock, ip, port, client_address)
Example #15
0
    def query_by_https(self, host, cli_ip):
        url_template = bjdns2_url + '/?dn={}&ip={}'

        # if host == self.bjdns2_host:
        #     return self.bjdns2_ip, 3600

        # else:
        if is_private_ip(cli_ip):
            url = url_template.format(host, '')
        else:
            url = url_template.format(host, cli_ip)

        r = self.session.get(url)
        result = json.loads(r.text)
        if result['Status'] == 0:
            self.cache.write(cli_ip, result['Question'][0], result, None)
            ip, ttl = resp_from_json(result)
            return ip, ttl
        else:
            return '', 0
Example #16
0
    def handle(self):
        self.__class__.handle_num += 1

        try:
            dst = self.conn.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
            dst_port, srv_ip = struct.unpack("!2xH4s8x", dst)
            ip_str = socket.inet_ntoa(srv_ip)
            if dst_port != g.config.proxy_port and not utils.is_private_ip(
                    ip_str):
                xlog.debug("Redirect to:%s:%d from:%s", ip_str, dst_port,
                           self.client_address)
                return handle_ip_proxy(self.conn, ip_str, dst_port,
                                       self.client_address)
        except:
            pass

        sockets = [self.conn]
        try:
            r, w, e = select.select(sockets, [], [])
            socks_version = self.conn.recv(1, socket.MSG_PEEK)
            if not socks_version:
                return

            if socks_version == "\x04":
                self.socks4_handler()
            elif socks_version == "\x05":
                self.socks5_handler()
            elif socks_version == "C":
                self.https_handler()
            elif socks_version in ["G", "P", "D", "O", "H", "T"]:
                self.http_handler()
            else:
                xlog.warn("socks version:%s[%s] not supported", socks_version,
                          utils.str2hex(socks_version))
                return

        except socket.error as e:
            xlog.warn('socks handler read error:%r', e)
        except Exception as e:
            xlog.exception("any err:%r", e)
Example #17
0
def handle_ip_proxy(sock, ip, port, client_address):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    rule = g.user_rules.check_host(ip, port)
    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        return try_loop("ip user", [rule], sock, ip, port, client_address)

    try:
        host = get_sni(sock)
        if host:
            ips = g.dns_srv.query(host)
            if not ips:
                cn = "CN" if g.ip_region.check_ip(ip) else "XX"
                ips.append("%s|%s" % (ip, cn))
                g.domain_cache.set_ips(host, ips)
            return handle_domain_proxy(sock, host, port, client_address)
    except SniNotExist as e:
        xlog.debug("ip:%s:%d get sni fail", ip, port)

    record = g.ip_cache.get(ip)
    if record and record["r"] != "unknown":
        rule = record["r"]
        if rule == "gae":
            rule_list = ["gae", "socks", "direct"]
        elif rule == "socks":
            rule_list = ["socks", "gae", "direct"]
        else:
            rule_list = ["direct", "gae", "socks"]
    elif g.ip_region.check_ip(ip):
        rule_list = ["direct", "socks"]
    else:
        rule_list = ["direct", "gae", "socks"]

    try_loop("ip", rule_list, sock, ip, port, client_address)
Example #18
0
    def handle(self):
        self.__class__.handle_num += 1

        try:
            dst = self.conn.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
            dst_port, srv_ip = struct.unpack("!2xH4s8x", dst)
            ip_str = socket.inet_ntoa(srv_ip)
            if dst_port != g.config.proxy_port and not utils.is_private_ip(ip_str):
                xlog.debug("Redirect to:%s:%d from:%s", ip_str, dst_port, self.client_address)
                return handle_ip_proxy(self.conn, ip_str, dst_port, self.client_address)
        except:
            pass

        sockets = [self.conn]
        try:
            r, w, e = select.select(sockets, [], [])
            socks_version = self.conn.recv(1, socket.MSG_PEEK)
            if not socks_version:
                return

            if socks_version == "\x04":
                self.socks4_handler()
            elif socks_version == "\x05":
                self.socks5_handler()
            elif socks_version == "C":
                self.https_handler()
            elif socks_version in ["G", "P", "D", "O", "H", "T"]:
                self.http_handler()
            else:
                xlog.warn("socks version:%s[%s] not supported", socks_version, utils.str2hex(socks_version))
                return

        except socket.error as e:
            xlog.warn('socks handler read error:%r', e)
        except Exception as e:
            xlog.exception("any err:%r", e)
Example #19
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    sock.target = "%s:%d" % (host, port)
    start_time = time.time()
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == "www.twitter.com":
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        if rule == "direct":
            ips = g.dns_srv.query(host)

            try:
                do_direct(sock, host, ips, port, client_address, left_buf)
                xlog.info("host:%s:%d user direct", host, port)
            except ConnectFail:
                xlog.warn("host:%s:%d user rule:%s connect fail", host, port,
                          rule)
                sock.close()
            return
        elif rule == "redirect_https":
            ips = g.dns_srv.query(host)

            try:
                do_redirect_https(sock, host, ips, port, client_address,
                                  left_buf)
                xlog.info("host:%s:%d user redirect_https", host, port)
            except RedirectHttpsFail:
                xlog.warn("host:%s:%d user rule:%s connect fail", host, port,
                          rule)
                sock.close()
            return
        elif rule == "gae":
            if not is_gae_workable():
                xlog.debug("host:%s:%d user rule:%s, but gae not work", host,
                           port, rule)
                sock.close()
                return

            try:
                host = get_sni(sock)
                do_gae(sock, host, port, client_address, left_buf)
                xlog.info("host:%s:%d user gae", host, port)
            except ssl.SSLError as e:
                xlog.warn("host:%s:%d user rule gae, GetReqTimeout:%d e:%r",
                          host, port, (time.time() - start_time) * 1000, e)
                sock.close()
            except simple_http_server.GetReqTimeout as e:
                # xlog.warn("host:%s:%d user rule gae, GetReqTimeout:%d e:%r", host, port, (time.time()-start_time)*1000, e)
                sock.close()
            except Exception as e:
                xlog.warn("host:%s:%d user rule:%s except:%r", host, port,
                          rule, e)
                sock.close()
            return
        elif rule == "socks":
            do_socks(sock, host, port, client_address, left_buf)
            xlog.info("host:%s:%d user rule:socks", host, port)
            return
        elif rule == "black":
            xlog.info("host:%s:%d user rule black", host, port)
            sock.close()
            return
        else:
            xlog.error("get rule:%s unknown", rule)
            sock.close()
            return

    record = g.domain_cache.get(host)
    if not record:
        rule = "direct"
    else:
        rule = record["r"]

    if not rule or rule == "direct":
        if g.config.auto_direct:
            ips = g.dns_srv.query(host)

            try:
                if port == 80 and g.gfwlist.check(host):
                    do_redirect_https(sock, host, ips, port, client_address,
                                      left_buf)
                    xlog.info("%s:%d redirect_https", host, port)
                    return
                else:
                    do_direct(sock, host, ips, port, client_address, left_buf)
                    xlog.info("%s:%d direct", host, port)
                    return
            except (ConnectFail, RedirectHttpsFail) as e:
                xlog.debug("%s:%d try direct/redirect fail:%r", host, port, e)
                rule = "gae"
        else:
            rule = "gae"

    if rule == "gae":
        if g.config.auto_gae and is_gae_workable(
        ) and g.domain_cache.accept_gae(host, port):
            try:
                sni_host = get_sni(sock)
                do_gae(sock, host, port, client_address, left_buf)
                xlog.info("%s:%d gae", host, port)
                return
            except SniNotExist:
                xlog.debug("domain:%s get sni fail", host)
                rule = "socks"
            except (SslWrapFail, simple_http_server.ParseReqFail) as e:
                xlog.warn("domain:%s sni:%s fail:%r", host, sni_host, e)
                g.domain_cache.report_gae_deny(host, port)
                sock.close()
                return
            except simple_http_server.GetReqTimeout:
                # Happen sometimes, don't known why.
                # xlog.warn("host:%s:%d try gae, GetReqTimeout:%d", host, port,
                #          (time.time() - start_time) * 1000)
                sock.close()
                return
            except Exception as e:
                xlog.warn("host:%s:%d cache rule:%s except:%r", host, port,
                          rule, e)
                g.domain_cache.report_gae_deny(host, port)
                sock.close()
                return

        else:
            rule = "socks"

    if rule == "socks":
        do_socks(sock, host, port, client_address, left_buf)
        xlog.info("%s:%d socks", host, port)
        return
    else:
        xlog.error("domain:%s get rule:%s unknown", host, rule)
        sock.close()
        return
Example #20
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    global fake_host

    if not fake_host and g.gae_proxy:
        fake_host = g.gae_proxy.web_control.get_fake_host()

    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    # Check user rules
    sock.target = "%s:%d" % (host, port)
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == fake_host:
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        return try_loop("domain user", [rule], sock, host, port,
                        client_address, left_buf)

    if g.config.block_advertisement and g.gfwlist.is_advertisement(host):
        xlog.info("block advertisement %s:%d", host, port)
        sock.close()
        return

    #ips = g.dns_query.query(host)
    #if check_local_network.IPv6.is_ok() and have_ipv6(ips) and port == 443:
    #    rule_list = ["direct", "gae", "socks", "redirect_https"]
    # gae is more faster then direct.

    rule = g.domain_cache.get_rule(host)
    if rule != "unknown":
        if rule == "gae":
            rule_list = ["gae", "socks", "redirect_https", "direct"]
        elif rule == "socks":
            rule_list = ["socks", "gae", "redirect_https", "direct"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

        if not g.domain_cache.accept_gae(host):
            rule_list.remove("gae")
    elif g.config.country_code == "CN":
        if g.gfwlist.in_white_list(host):
            rule_list = ["direct", "gae", "socks", "redirect_https"]
        elif g.gfwlist.in_block_list(host):
            if g.config.pac_policy == "black_X-Tunnel":
                rule_list = ["socks", "redirect_https", "direct", "gae"]
            else:
                rule_list = ["gae", "socks", "redirect_https", "direct"]
        else:
            ips = g.dns_query.query_recursively(host, 1)
            if g.ip_region.check_ips(ips):
                rule_list = ["direct", "socks", "redirect_https"]
            else:
                rule_list = ["direct", "gae", "socks", "redirect_https"]
    else:
        rule_list = ["direct", "socks", "gae", "redirect_https"]

    # check config.
    if not g.config.auto_direct:
        for rule in ["direct", "redirect_https"]:
            try:
                rule_list.remove(rule)
            except:
                pass
    elif g.config.auto_direct6 and "direct" in rule_list:
        rule_list.insert(rule_list.index("direct"), "direct6")

    if not g.config.enable_fake_ca and port == 443 or not g.config.auto_gae:
        try:
            rule_list.remove("gae")
        except:
            pass

    xlog.debug("connect to %s:%d from:%s:%d, rule:%s", host, port,
               client_address[0], client_address[1], utils.to_str(rule_list))
    try_loop("domain", rule_list, sock, host, port, client_address, left_buf)
Example #21
0
def handle_ip_proxy(sock, ip, port, client_address):
    xlog.debug("handle_ip_proxy to %s:%d from:%s:%d", ip, port,
               client_address[0], client_address[1])

    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    if g.config.pac_policy == "all_X-Tunnel":
        rule = "socks"
    else:
        rule = g.user_rules.check_host(ip, port)

    if not rule:
        if utils.is_private_ip(ip):
            rule = "direct"

    if rule:
        return try_loop("ip user", [rule], sock, ip, port, client_address)

    if port == 443:
        try:
            host = get_sni(sock)
            if host and not utils.check_ip_valid(host):
                xlog.debug("ip connect to %s:%d translate to %s", ip, port,
                           host)
                return handle_domain_proxy(sock, host, port, client_address)
        except SniNotExist as e:
            xlog.debug("ip:%s:%d get sni fail", ip, port)

    record = g.ip_cache.get(ip)
    if record and record["r"] != "unknown":
        rule = record["r"]
        if rule == "gae":
            rule_list = ["gae", "socks", "direct"]
        elif rule == "socks":
            rule_list = ["socks", "gae", "direct"]
        else:
            rule_list = ["direct", "gae", "socks"]
    elif g.ip_region.check_ip(ip):
        rule_list = ["direct", "socks"]
    else:
        rule_list = ["direct", "gae", "socks"]

    if not g.config.auto_direct:
        for rule in ["direct", "redirect_https"]:
            try:
                rule_list.remove(rule)
            except:
                pass
    elif g.config.auto_direct6 and "direct" in rule_list:
        rule_list.insert(rule_list.index("direct"), "direct6")

    if not g.config.enable_fake_ca and port == 443 or not g.config.auto_gae:
        try:
            rule_list.remove("gae")
        except:
            pass

    if g.config.pac_policy == "all_X-Tunnel":
        rule_list = [
            "socks",
        ]

    try_loop("ip", rule_list, sock, ip, port, client_address)
Example #22
0
def handle_domain_proxy(sock, host, port, client_address, left_buf=""):
    global fake_host
    if not fake_host and g.gae_proxy:
        fake_host = g.gae_proxy.web_control.get_fake_host()

    if not isinstance(sock, SocketWrap):
        sock = SocketWrap(sock, client_address[0], client_address[1])

    sock.target = "%s:%d" % (host, port)
    rule = g.user_rules.check_host(host, port)
    if not rule:
        if host == fake_host:
            rule = "gae"
        elif utils.check_ip_valid(host) and utils.is_private_ip(host):
            rule = "direct"

    if rule:
        return try_loop("domain user", [rule], sock, host, port, client_address, left_buf)

    if g.config.block_advertisement and g.gfwlist.is_advertisement(host):
        xlog.info("block advertisement %s:%d", host, port)
        sock.close()
        return

    #ips = g.dns_srv.query(host)
    #if check_local_network.IPv6.is_ok() and have_ipv6(ips) and port == 443:
    #    rule_list = ["direct", "gae", "socks", "redirect_https"]
    # gae is more faster then direct.

    record = g.domain_cache.get(host)
    if record and record["r"] != "unknown":
        rule = record["r"]
        if rule == "gae":
            rule_list = ["gae", "socks", "redirect_https", "direct"]
        else:
            rule_list = ["direct", "gae", "socks", "redirect_https"]

        if not g.domain_cache.accept_gae(host):
            rule_list.remove("gae")
    elif g.gfwlist.is_white(host):
        rule_list = ["direct", "gae", "socks", "redirect_https"]
    elif g.gfwlist.check(host):
        rule_list = ["gae", "socks", "redirect_https", "direct"]
    else:
        ips = g.dns_srv.query(host)
        if g.ip_region.check_ips(ips):
            rule_list = ["direct", "gae", "socks", "redirect_https"]
        else:
            rule_list = ["gae", "socks", "redirect_https", "direct"]

    if not g.config.auto_direct and "direct" in rule_list:
        try:
            rule_list.remove("direct")
            rule_list.remove("redirect_https")
        except:
            pass

    if not g.config.enable_fake_ca and port == 443 and "gae" in rule_list:
        try:
            rule_list.remove("gae")
        except:
            pass

    if not g.config.auto_gae and "gae" in rule_list:
        try:
            rule_list.remove("gae")
        except:
            pass

    try_loop("domain", rule_list, sock, host, port, client_address, left_buf)
Example #23
0
 def test_private_ip(self):
     ip = 'bat-bing-com.a-0001.a-msedge.net.'
     res = utils.is_private_ip(ip)
     self.assertFalse(res)