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