예제 #1
0
파일: httpd.py 프로젝트: fdslight/netbus
    def __handle_request_header(self):
        size = self.reader.size()

        byte_data = self.reader.read()
        p = byte_data.find(b"\r\n\r\n")

        # 检查头部长度合法性
        if p < 8 and size > 4096:
            self.delete_handler(self.fileno)
            return

        if p < 8: return

        p = p + 4
        self.reader._putvalue(byte_data[p:])

        s = byte_data.decode("iso-8859-1")
        try:
            rq, kv = httputils.parse_htt1x_request_header(s)
        except httputils.Http1xHeaderErr:
            self.delete_handler(self.fileno)
            return

        if not self.__check_request_header(rq[0], kv):
            self.send_header("400 Bad Request", [])
            self.delete_this_no_sent_data()
            return

        self.__total_length = self.__get_content_length(rq[0], kv)
        self.__is_parsed_header = True
        self.__send_header_to_web_gw(rq, kv)
예제 #2
0
파일: tunnels.py 프로젝트: ybbhai/fdslight
    def do_http_handshake(self):
        size = self.reader.size()
        data = self.reader.read()

        p = data.find(b"\r\n\r\n")

        if p < 10 and size > 2048:
            logging.print_general(
                "wrong_http_header_length_for_request_header", self.__address)
            self.delete_handler(self.fileno)
            return

        if p < 0:
            self.reader._putvalue(data)
            return
        p += 4

        self.reader._putvalue(data[p:])

        s = data[0:p].decode("iso-8859-1")

        try:
            request, kv_pairs = httputils.parse_htt1x_request_header(s)
        except httputils.Http1xHeaderErr:
            logging.print_general("wrong_http_request_protocol",
                                  self.__address)
            self.delete_handler(self.fileno)
            return

        method, url, version = request
        upgrade = self.get_http_kv_value("upgrade", kv_pairs)
        origin = self.get_http_kv_value("origin", kv_pairs)

        if upgrade != "websocket" and method != "GET":
            logging.print_general(
                "http_handshake_method_fail:upgrade:%s,method:%s" % (
                    upgrade,
                    method,
                ), self.__address)
            self.response_http_error("400 Bad Request")
            return

        if not origin:
            logging.print_general("http_origin_none", self.__address)
            self.response_http_error("403 Forbidden")
            return

        self.__http_ws_key = self.get_http_kv_value("sec-websocket-key",
                                                    kv_pairs)
        if not self.__http_ws_key:
            logging.print_general("http_websocket_key_not_found",
                                  self.__address)
            self.response_http_error("400 Bad Request")
            return

        self.__http_handshake_ok = True
        logging.print_general("http_handshake_ok", self.__address)
        self.response_http_ok()
예제 #3
0
    def __do_handshake(self, byte_data):
        try:
            sts = byte_data.decode("iso-8859-1")
        except UnicodeDecodeError:
            self.response_error()
            return False

        try:
            rs = httputils.parse_htt1x_request_header(sts)
        except:
            self.response_error()
            return False

        req, headers = rs

        dic = {}
        for k, v in headers:
            k = k.lower()
            dic[k] = v

        if "sec-websocket-key" not in dic: return False
        ws_version = dic.get("sec-websocket-version", 0)

        is_err = False
        try:
            ws_version = int(ws_version)
            if ws_version != 13: is_err = True
        except ValueError:
            is_err = True
        if is_err:
            self.response_error()
            return False

        if not self.on_handshake(req, headers):
            self.response_error()
            return False

        sec_ws_key = dic["sec-websocket-key"]
        resp_sec_key = websocket.gen_handshake_key(sec_ws_key)

        resp_headers = [("Upgrade", "websocket"), ("Connection", "Upgrade"),
                        ("Sec-WebSocket-Accept", resp_sec_key)]

        resp_headers += self.__ext_handshake_resp_headers

        resp_sts = httputils.build_http1x_resp_header(
            "101 Switching Protocols", resp_headers, version="1.1")

        self.writer.write(resp_sts.encode("iso-8859-1"))
        self.add_evt_write(self.fileno)

        return True
예제 #4
0
    def __do_handshake(self, byte_data):
        try:
            sts = byte_data.decode("iso-8859-1")
        except UnicodeDecodeError:
            self.response_error()
            return False

        try:
            rs = httputils.parse_htt1x_request_header(sts)
        except:
            self.response_error()
            return False

        req, headers = rs

        dic = {}
        for k, v in headers:
            k = k.lower()
            dic[k] = v

        if "sec-websocket-key" not in dic: return False
        ws_version = dic.get("sec-websocket-version", 0)

        is_err = False
        try:
            ws_version = int(ws_version)
            if ws_version != 13: is_err = True
        except ValueError:
            is_err = True
        if is_err:
            self.response_error()
            return False

        if not self.on_handshake(req, headers):
            self.response_error()
            return False

        sec_ws_key = dic["sec-websocket-key"]
        resp_sec_key = websocket.gen_handshake_key(sec_ws_key)

        resp_headers = [("Upgrade", "websocket"), ("Connection", "Upgrade"), ("Sec-WebSocket-Accept", resp_sec_key)]

        resp_headers += self.__ext_handshake_resp_headers

        resp_sts = httputils.build_http1x_resp_header("101 Switching Protocols", resp_headers, version="1.1")

        self.writer.write(resp_sts.encode("iso-8859-1"))
        self.add_evt_write(self.fileno)

        return True
예제 #5
0
    def __handle_http_step1(self):
        rdata = self.reader.read()
        p = rdata.find(b"\r\n\r\n")

        if p < 4:
            self.delete_handler(self.fileno)
            return

        p += 4
        header_data = rdata[0:p]
        try:
            request, mapv = httputils.parse_htt1x_request_header(header_data.decode("iso-8859-1"))
        except httputils.Http1xHeaderErr:
            self.delete_handler(self.fileno)
            return

        body_data = rdata[p:]

        # 使用隧道模式
        if request[0].lower() == "connect":
            self.__handle_http_tunnel_proxy(request, mapv)
            return

        self.__handle_http_no_tunnel_proxy(request, mapv, body_data)
예제 #6
0
    def do_handshake(self):
        size = self.reader.size()
        rdata = self.reader.read()
        p = rdata.find(b"\r\n\r\n")

        if p < 5 and size > 2048:
            self.delete_handler(self.fileno)
            return

        s = rdata.decode("iso-8859-1")
        try:
            rq, kv = httputils.parse_htt1x_request_header(s)
        except httputils.Http1xHeaderErr:
            self.delete_handler(self.fileno)
            return

        m, uri, ver = rq

        if ver.lower() != "http/1.1":
            self.delete_handler(self.fileno)
            return

        if m != "GET":
            self.delete_handler(self.fileno)
            return

        upgrade = self.get_kv_value(kv, "upgrade")
        if not upgrade:
            self.send_403_response()
            return
        if upgrade.lower() != "websocket":
            self.send_403_response()
            return

        connection = self.get_kv_value(kv, "connection")
        if not connection:
            self.send_403_response()
            return
        if connection.lower() != "upgrade":
            self.send_403_response()
            return

        sec_ws_key = self.get_kv_value(kv, "sec-websocket-key")
        if not sec_ws_key:
            self.send_403_response()
            return

        origin = self.get_kv_value(kv, "origin")
        if not origin:
            self.send_403_response()
            return
        ws_ver = self.get_kv_value(kv, "sec-websocket-version")

        try:
            v = int(ws_ver)
        except ValueError:
            self.send_403_response()
            return

        if v != 13:
            self.send_403_response()
            return

        sec_ws_proto = self.get_kv_value(kv, "sec-websocket-protocol")
        if not sec_ws_proto:
            self.send_403_response()
            return

        auth_id = self.get_kv_value(kv, "x-auth-id")
        if not auth_id:
            self.send_403_response()
            return

        role = self.get_kv_value(kv, "x-role")
        if not role:
            self.send_403_response()
            return

        self.__role = role.lower()
        if self.__role not in ("cs", "ms",):
            self.send_403_response()
            return

        if self.__role == "ms":
            session_id = self.get_kv_value(kv, "x-session-id")
            if not session_id:
                self.send_403_response()
                return

        resp_headers = [
            ("Content-Length", "0"),
        ]

        resp_headers += [("Connection", "Upgrade",), ("Upgrade", "websocket",)]
        resp_headers += [("Sec-WebSocket-Accept", ws.gen_handshake_key(sec_ws_key))]
        resp_headers += [("Sec-WebSocket-Protocol", "socks2https")]

        logging.print_general("handshake_ok", self.__caddr)

        self.__handshake_ok = True
        self.send_response("101 Switching Protocols", resp_headers)
    def parse_http_header(self):
        """
        :return Boolean: True表示未发生错误,False表示发生错误
        """
        size = self.reader.size()
        rdata = self.reader.read()
        p = rdata.find(b"\r\n\r\n")

        if p < 0 and size > 2048: return False
        if p < 0:
            self.reader._putvalue(rdata)
            return True
        if p < 12: return False

        p += 4
        self.reader._putvalue(rdata[p:])
        s = rdata[0:p].decode("iso-8859-1")
        try:
            req, kv_pairs = httputils.parse_htt1x_request_header(s)
        except httputils.Http1xHeaderErr:
            return False
        # 只支持http/1.1代理
        if req[2].lower() != "http/1.1": return False

        self.__http_request_info = req
        self.__http_request_kv_pairs = kv_pairs
        self.__is_parsed_http_header = True

        if self.__http_request_info[0].lower() == "connect":
            self.__is_http_tunnel_mode = True

        # 核对http请求头
        if not self.http_request_check():
            if self.dispatcher.debug:
                logging.print_general("wrong http request header",
                                      self.__caddr)
            self.delete_handler(self.fileno)
            return

        server_info = self.get_http_remote_server_info()
        if not server_info:
            self.delete_handler(self.fileno)
            return
        if not self.__is_http_tunnel_mode:
            self.http_request_set()
        host_info, port, uri = server_info

        host, addr_type = host_info
        if addr_type == HTTP_HOST_IPv6:
            is_ipv6 = True
        else:
            is_ipv6 = False
        self.__http_uri = uri

        if self.debug:
            logging.print_general("http_proxy_request", (
                host,
                port,
            ))

        if addr_type == HTTP_HOST_IPv6:
            _t = socks2https.ADDR_TYPE_IPv6
        elif addr_type == HTTP_HOST_IP:
            _t = socks2https.ADDR_TYPE_IP
        else:
            _t = socks2https.ADDR_TYPE_DOMAIN

        self.__is_sent_to_convert_client = self.is_need_upper_proxy(host, _t)

        if not self.__is_sent_to_convert_client:
            self.__raw_client_fd = self.create_handler(self.fileno,
                                                       raw_tcp_client,
                                                       (host, port),
                                                       is_ipv6=is_ipv6)
            return True

        self.__packet_id = self.dispatcher.alloc_packet_id(self.fileno)
        self.dispatcher.send_conn_frame(socks2https.FRAME_TYPE_TCP_CONN,
                                        self.__packet_id, host, port, _t)

        return True
예제 #8
0
    def do_handshake(self):
        size = self.reader.size()
        rdata = self.reader.read()
        p = rdata.find(b"\r\n\r\n")

        if p < 5 and size > 2048:
            self.delete_handler(self.fileno)
            return

        s = rdata.decode("iso-8859-1")
        try:
            rq, kv = httputils.parse_htt1x_request_header(s)
        except httputils.Http1xHeaderErr:
            self.delete_handler(self.fileno)
            return

        m, uri, ver = rq

        if ver.lower() != "http/1.1":
            self.delete_handler(self.fileno)
            return

        if m != "GET":
            self.delete_handler(self.fileno)
            return

        upgrade = self.get_kv_value(kv, "upgrade")
        if not upgrade:
            if self.dispatcher.debug:
                sys.stderr.write("no upgrade field\r\n")
            self.send_403_response()
            return
        if upgrade.lower() != "websocket":
            if self.dispatcher.debug:
                sys.stderr.write("it is not websocket field\r\n")
            self.send_403_response()
            return

        connection = self.get_kv_value(kv, "connection")
        if not connection:
            if self.dispatcher.debug:
                sys.stderr.write("no connection field\r\n")
            self.send_403_response()
            return
        if connection.lower() != "upgrade":
            if self.dispatcher.debug:
                sys.stderr.write("connection is not upgrade\r\n")
            self.send_403_response()
            return

        sec_ws_key = self.get_kv_value(kv, "sec-websocket-key")
        if not sec_ws_key:
            if self.dispatcher.debug:
                sys.stderr.write("no websocket key\r\n")
            self.send_403_response()
            return

        origin = self.get_kv_value(kv, "origin")
        if not origin:
            if self.dispatcher.debug:
                sys.stderr.write("no origin key\r\n")
            self.send_403_response()
            return
        ws_ver = self.get_kv_value(kv, "sec-websocket-version")

        try:
            v = int(ws_ver)
        except ValueError:
            self.send_403_response()
            return

        if v != 13:
            if self.dispatcher.debug:
                sys.stderr.write("wrong websocket version\r\n")
            self.send_403_response()
            return

        sec_ws_proto = self.get_kv_value(kv, "sec-websocket-protocol")
        if not sec_ws_proto:
            if self.dispatcher.debug:
                sys.stderr.write("no sec-websocket-protocol\r\n")
            self.send_403_response()
            return

        auth_id = self.get_kv_value(kv, "x-auth-id")
        if not auth_id:
            if self.dispatcher.debug:
                sys.stderr.write("no auth-id field\r\n")
            self.send_403_response()
            return

        is_msg_tunnel = self.get_kv_value(kv, "x-msg-tunnel")
        if not is_msg_tunnel:
            sys.stderr.write("not found X-Msg-Tunnel value\r\n")
            self.send_403_response()
            return

        if not self.dispatcher.auth_id_exists(auth_id):
            if self.dispatcher.debug:
                sys.stderr.write("not found %s service\r\n" % auth_id)
            self.send_403_response()
            return

        if self.dispatcher.auth_id_exists(auth_id) and not is_msg_tunnel:
            self.send_403_response()
            return

        try:
            v = bool(int(is_msg_tunnel))
        except ValueError:
            sys.stderr.write("wrong X-Msg-Tunnel value type\r\n")
            self.send_403_response()
            return

        self.__is_msg_tunnel = v
        if v:
            s = self.get_kv_value(kv, "x-session-id")
            self.__session_id = base64.b64decode(s.encode())
            if not self.dispatcher.session_get(self.__session_id):
                sys.stderr.write("session id not exists\r\n")
                self.send_403_response()
                return
        else:
            self.dispatcher.reg_fwd_conn(auth_id, self.fileno)

        resp_headers = [
            ("Content-Length", "0"),
        ]

        resp_headers += [(
            "Connection",
            "Upgrade",
        ), (
            "Upgrade",
            "websocket",
        )]
        resp_headers += [("Sec-WebSocket-Accept",
                          ws.gen_handshake_key(sec_ws_key))]
        resp_headers += [("Sec-WebSocket-Protocol", "intranet_pass")]

        logging.print_general("handshake_ok", self.__caddr)

        self.__handshake_ok = True
        self.__auth_id = auth_id
        self.send_response("101 Switching Protocols", resp_headers)
        self.tcp_loop_read_num = 10

        if not v: return

        # 注意这里如果是消息隧道一定要等待握手协议发送完毕再告知连接成功,连接成功会发送堆积在服务器上的数据
        self.dispatcher.tell_listener_conn_ok(self.__session_id, self.fileno)