diff options
| author | Lu <[email protected]> | 2018-08-13 17:26:51 +0800 |
|---|---|---|
| committer | Lu <[email protected]> | 2018-08-13 17:26:51 +0800 |
| commit | 41843ef4785b8184801fd63597610d0a381507ae (patch) | |
| tree | 0328a6dd09fbbb2669308de2460e52eb6ee49fef /src | |
| parent | a6b2e830a329d2e2fa9a9eb184a8fb5413fd3021 (diff) | |
增加HTTP Upgrade应答码处理功能,透转WebSocket协议。修正多配置命中场景下优先级反转等问题。增加MasterLog记录功能。
Diffstat (limited to 'src')
| -rw-r--r-- | src/http1.cc | 39 | ||||
| -rw-r--r-- | src/httpaction.cc | 22 | ||||
| -rw-r--r-- | src/httpscan.cc | 39 | ||||
| -rw-r--r-- | src/main.cc | 1 | ||||
| -rw-r--r-- | src/opts.cc | 29 | ||||
| -rw-r--r-- | src/opts.h | 203 | ||||
| -rw-r--r-- | src/pxyconn.cc | 11 | ||||
| -rw-r--r-- | src/ssl.cc | 3 |
8 files changed, 198 insertions, 149 deletions
diff --git a/src/http1.cc b/src/http1.cc index 6b95e7c..f40aecb 100644 --- a/src/http1.cc +++ b/src/http1.cc @@ -113,7 +113,7 @@ public: /* Hack, 直接覆盖Accept-Encoding,用空格等长替换 */ if (strcasecmp(str_last_header_field_.c_str(), "Accept-Encoding") == 0) { - memset((void *)data, 0x20, len); + memset((void *) data, 0x20, len); } str_last_value_field_ += std::string(data, data + len); @@ -358,7 +358,7 @@ ssize_t Http1Request::ConstructFromMemory(const char * buf, size_t buflen) Http1RequestParserCallbacks::CallbackSettings(), buf, buflen); /* 解析失败 */ - if(sz_parsed && parser_->http_errno > 0) + if (sz_parsed && parser_->http_errno > 0) { throw std::runtime_error(string_format("Failed at http parsing: errcode=%u, %s, %s", parser_->http_errno, http_errno_name(static_cast<http_errno>(parser_->http_errno)), @@ -416,7 +416,12 @@ void Http1Request::Construct() /* 请求头部与请求体的分隔符 */ evbuffer_add_printf(evbuf_output_ptr, "\r\n"); - evbuffer_add(evbuf_output_ptr, body_content_->data(), body_content_->size()); + + /* 请求体 */ + if (body_content_ != nullptr) + { + evbuffer_add(evbuf_output_ptr, body_content_->data(), body_content_->size()); + } /* 替换原有的请求 */ evbuf_content_raw_ = std::move(evbuf_construct); @@ -601,6 +606,7 @@ public: } std::string DumpToString() override; + bool Upgrade() { return upgrade_; } private: int resp_code_{-1}; @@ -610,6 +616,7 @@ private: bool forward_{true}; bool readonly_{false}; bool bypass_{false}; + bool upgrade_{false}; /* Tags */ section_state_t section_state[kSectionMax]{kStateBegin}; @@ -622,7 +629,8 @@ private: struct __body_content { __body_content(body_content_ptr_t __ptr, bool __is_complete) - : ptr(std::move(__ptr)), is_complete(__is_complete) {} + : ptr(std::move(__ptr)), is_complete(__is_complete) + {} body_content_ptr_t ptr{nullptr}; bool is_complete{false}; @@ -746,19 +754,19 @@ int Http1ResponseParserCallbacks::CallbackOnHeaderComplete(http_parser * parser) resp_ptr->headers_.ConstructByHttpParserComplete(); /* Lookup Content-Type and Content-Length */ - resp_ptr->headers_.ForEachValueOfHeader("Content-Type", [resp_ptr](const std::string & f, const std::string &v) + resp_ptr->headers_.ForEachValueOfHeader("Content-Type", [resp_ptr](const std::string & f, const std::string & v) { resp_ptr->content_type = v; return false; }); - resp_ptr->headers_.ForEachValueOfHeader("Content-Length", [resp_ptr](const std::string & f, const std::string &v) + resp_ptr->headers_.ForEachValueOfHeader("Content-Length", [resp_ptr](const std::string & f, const std::string & v) { resp_ptr->content_length = v; return false; }); - resp_ptr->headers_.ForEachValueOfHeader("Content-Encoding", [resp_ptr](const std::string & f, const std::string &v) + resp_ptr->headers_.ForEachValueOfHeader("Content-Encoding", [resp_ptr](const std::string & f, const std::string & v) { resp_ptr->content_encoding = v; return false; @@ -844,7 +852,7 @@ ssize_t Http1Response::ConstructFromMemory(const char * buf, size_t buflen) Http1ResponseParserCallbacks::CallbackSettings(), buf, buflen); /* 暂停状态,为了调用外部回调函数 */ - if(sz_parsed && parser_->http_errno == 31) + if (sz_parsed && parser_->http_errno == 31) return sz_parsed; /* 解析错误 */ @@ -855,6 +863,7 @@ ssize_t Http1Response::ConstructFromMemory(const char * buf, size_t buflen) http_errno_description(static_cast<http_errno>(parser_->http_errno)))); } + if (parser_->upgrade) upgrade_ = true; return sz_parsed; } @@ -908,7 +917,7 @@ void Http1Response::Construct() evbuffer_add_printf(evbuf_ptr, "\r\n"); } - for(auto & body_segment : body_contents_) + for (auto & body_segment : body_contents_) { if (body_segment.ptr == nullptr || !body_segment.is_complete) continue; auto * body_segment_ptr = body_segment.ptr.get(); @@ -1063,7 +1072,17 @@ int Http1Connection::on_connection_read_response(pxy_conn_ctx_t * conn_ctx, pxy_ return 0; } - if (forward_len <= 0) return 0; + if (forward_len <= 0) + { + return 0; + } + + if(response.Upgrade()) + { + conn_ctx->passthrough = 1; + goto __forward; + } + if (response.SectionState(response.kSectionHeader) == response.kStateComplete) { session->CallResponseHeaderCallback(); diff --git a/src/httpaction.cc b/src/httpaction.cc index bfe1570..ea69c35 100644 --- a/src/httpaction.cc +++ b/src/httpaction.cc @@ -264,7 +264,7 @@ private: /// HTTP白名单,不进行任何处理 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class HttpActionBypass : public HttpAction +class HttpActionWhiteList : public HttpAction { public: void Construct(const std::string & str_service_define) override @@ -579,9 +579,9 @@ private: std::array<std::string, HttpActionReplace::kZoneMax> HttpActionReplace::map_edit_zone_to_str = { "http_req_uri", - "http_req_headers", + "http_req_header", "http_req_body", - "http_resp_headers", + "http_resp_header", "http_resp_body" }; @@ -862,7 +862,7 @@ bool HttpActionReplace::__scan_and_replace(enum edit_zone zone, std::string & ra /* 替换表达式,替换方法 */ const auto & __edit_fmt = edit_rule_iter.fmt; /* 执行替换 */ - replaced = __edit_regex.Replace(__edit_fmt, &raw); + replaced = __edit_regex.GlobalReplace(__edit_fmt, &raw) > 0; if (replaced) break; } @@ -878,11 +878,6 @@ std::shared_ptr<HttpAction> HttpActionFactory(enum HttpActionType type, std::str switch (type) { - case kActionBypass: - { - __http_action_object = std::make_shared<HttpActionBypass>(); - break; - } case kActionMonitor: { __http_action_object = std::make_shared<HttpActionMonitor>(); @@ -893,20 +888,25 @@ std::shared_ptr<HttpAction> HttpActionFactory(enum HttpActionType type, std::str __http_action_object = std::make_shared<HttpActionReplace>(); break; } - case kActionDrop: { __http_action_object = std::make_shared<HttpActionDrop>(); break; } - /* 阻断和重定向统一实现 */ case kActionBlock: case kActionRedirect: { __http_action_object = std::make_shared<HttpActionRedirect>(); break; } + + case kActionWhiteList: + { + __http_action_object = std::make_shared<HttpActionWhiteList>(); + break; + } + default: assert(0); } diff --git a/src/httpscan.cc b/src/httpscan.cc index 016976c..b742dc7 100644 --- a/src/httpscan.cc +++ b/src/httpscan.cc @@ -377,21 +377,38 @@ HttpScanSession::scan_result_t HttpScanSession::scan_bypass_content_type(const H void HttpScanSession::hit_config_and_do_action(HttpSession * session) { /* 判断命中数量,若为多命中,选择优先级最高的动作执行 */ - enum HttpActionType action_type = HttpActionType::kActionMax; + enum HttpActionType action_type = HttpActionType::kActionBypass; unsigned int do_action_id = 0; - /* 选择最小的动作ID为实际执行的配置ID */ + /* 选择最大的动作ID为实际执行的配置ID */ for (unsigned int i = 0; i < nr_maat_scan_result_; i++) { - if (maat_scan_result_[i].action <= action_type) do_action_id = i; + unsigned char __action = static_cast<unsigned char>(maat_scan_result_[i].action); + unsigned char __last_action = static_cast<unsigned char>(maat_scan_result_[do_action_id].action); + + if (__action > __last_action) do_action_id = i; } Maat_rule_t * hit_maat_rule = &maat_scan_result_[do_action_id]; - auto __action_type = (enum HttpActionType) hit_maat_rule->action; - const char * __action_string = hit_maat_rule->service_defined; + auto __action_type = (enum HttpActionType) (unsigned char)hit_maat_rule->action; + + /* Long Service Define */ + auto __service_define_ptr = std::unique_ptr<char[]>(new char[hit_maat_rule->serv_def_len]); + + int ret = Maat_read_rule(httpscan_module_ref_.maat_feather_ref, + hit_maat_rule, MAAT_RULE_SERV_DEFINE, __service_define_ptr.get(), hit_maat_rule->serv_def_len); + + if (ret != hit_maat_rule->serv_def_len) + { + throw std::runtime_error(string_format("Error in read rule's service define: " + "config_id = ", hit_maat_rule->config_id)); + } + + const char * __str_action = __service_define_ptr.get(); /* 创建HttpAction的对象 */ - auto action_object = HttpActionFactory(__action_type, __action_string); + auto action_object = HttpActionFactory(__action_type, __str_action); + /* HttpLogger对象 */ auto logger_object = HttpLoggerFactory(hit_maat_rule->service_id, hit_maat_rule->config_id); logger_object->ConstructByConnection(session->connection()); @@ -403,40 +420,30 @@ void HttpScanSession::hit_config_and_do_action(HttpSession * session) session->SetRequestHeaderCallback([action_object](HttpSession & session) { auto __action_object = action_object; - - LOG(DEBUG) << &session << "HttpAction" << "OnRequestHeader"; __action_object->OnRequestHeader(&session); }); session->SetRequestBodyCallback([action_object](HttpSession & session) { auto __action_object = action_object; - - LOG(DEBUG) << &session << "HttpAction" << "OnRequestBody"; __action_object->OnRequestBody(&session); }); session->SetResponseHeaderCallback([action_object](HttpSession & session) { auto __action_object = action_object; - - LOG(DEBUG) << &session << "HttpAction" << "OnResponseHeader"; __action_object->OnResponseHeader(&session); }); session->SetResponseBodyCallback([action_object](HttpSession & session) { auto __action_object = action_object; - - LOG(DEBUG) << &session << "HttpAction" << "OnResponseBody"; __action_object->OnResponseBody(&session); }); session->SetDumpToStringCallback([action_object]() { auto __action_object = action_object; - - LOG(DEBUG) << "HttpAction" << "DumpToString"; return __action_object->DumpToString(); }); diff --git a/src/main.cc b/src/main.cc index 3e929b9..a37ffed 100644 --- a/src/main.cc +++ b/src/main.cc @@ -304,6 +304,7 @@ main(int argc, char *argv[]) el::Loggers::getLogger("conntrace"); el::Loggers::getLogger("HttpScanTrace"); el::Loggers::getLogger("HttpSessionTrace"); + el::Loggers::getLogger("MasterLog"); if (nat_getdefaultname()) { diff --git a/src/opts.cc b/src/opts.cc index d9535e1..3ec872c 100644 --- a/src/opts.cc +++ b/src/opts.cc @@ -283,6 +283,21 @@ static int __maatframe_load_from_file(tfe_config * cfg, TfeConfigParser & cfg_pa __maat_config->str_log_file_path = cfg_parser.GetValue<std::string>("maat", "logfile"); __maat_config->str_stat_file = cfg_parser.GetValue<std::string>("maat", "statfile"); + /* scan interval and effective interval */ + auto __result_scan_interval_ms = cfg_parser.TryGetValue<unsigned int>("maat", "scan_interval_ms"); + if (__result_scan_interval_ms.first) + { + __maat_config->is_effect_interval_ms_set = true; + __maat_config->effect_interval_ms = __result_scan_interval_ms.second; + } + + auto __result_effect_interval_ms = cfg_parser.TryGetValue<unsigned int>("maat", "effect_interval_ms"); + if (__result_effect_interval_ms.first) + { + __maat_config->is_effect_interval_ms_set = true; + __maat_config->effect_interval_ms = __result_effect_interval_ms.second; + } + log_dbg_printf("Maat pz source mode = %d", __maat_config->cfg_load_from); log_dbg_printf("Maat json file path = %s", __maat_config->str_json_file_path.c_str()); log_dbg_printf("Maat redis server = %s", __maat_config->str_redis_addr.c_str()); @@ -337,9 +352,17 @@ int __maatframe_init(tfe_config * cfg) Maat_set_feather_opt(feather, MAAT_OPT_STAT_ON, nullptr, 0); Maat_set_feather_opt(feather, MAAT_OPT_PERF_ON, nullptr, 0); - int true_value = 1; - Maat_set_feather_opt(feather, MAAT_OPT_EFFECT_INVERVAL_MS, &true_value, sizeof(true_value)); - Maat_set_feather_opt(feather, MAAT_OPT_SCANDIR_INTERVAL_MS, &true_value, sizeof(true_value)); + if (__maat_config->is_effect_interval_ms_set) + { + unsigned int __value = __maat_config->effect_interval_ms; + Maat_set_feather_opt(feather, MAAT_OPT_EFFECT_INVERVAL_MS, &__value, sizeof(__value)); + } + + if (__maat_config->is_scan_interval_ms_set) + { + unsigned int __value = __maat_config->scan_interval_ms; + Maat_set_feather_opt(feather, MAAT_OPT_SCANDIR_INTERVAL_MS, &__value, sizeof(__value)); + } Maat_initiate_feather(feather); if (feather == nullptr) @@ -45,73 +45,80 @@ class Http; struct proxyspec { - unsigned int ssl : 1; - unsigned int http : 1; - unsigned int upgrade: 1; - unsigned int dns : 1; /* set if spec needs DNS lookups */ - struct sockaddr_storage listen_addr; - socklen_t listen_addrlen; - /* connect_addr and connect_addrlen are set: static mode; - * natlookup is set: NAT mode; natsocket /may/ be set too; - * sni_port is set, in which case we use SNI lookups */ - struct sockaddr_storage connect_addr; - socklen_t connect_addrlen; - unsigned short sni_port; - char *natengine; - nat_lookup_cb_t natlookup; - nat_socket_cb_t natsocket; - struct proxyspec *next; - - /* free at end of connection */ + unsigned int ssl : 1; + unsigned int http : 1; + unsigned int upgrade: 1; + unsigned int dns : 1; /* set if spec needs DNS lookups */ + struct sockaddr_storage listen_addr; + socklen_t listen_addrlen; + /* connect_addr and connect_addrlen are set: static mode; + * natlookup is set: NAT mode; natsocket /may/ be set too; + * sni_port is set, in which case we use SNI lookups */ + struct sockaddr_storage connect_addr; + socklen_t connect_addrlen; + unsigned short sni_port; + char * natengine; + nat_lookup_cb_t natlookup; + nat_socket_cb_t natsocket; + struct proxyspec * next; + + /* free at end of connection */ bool free_after_use; }; /* TFE Runtime Instances */ struct tfe_instance { - /* Global Maat Feather */ - Maat_feather_t maat_feather; - /* Maat Logger */ + /* Global Maat Feather */ + Maat_feather_t maat_feather; + /* Maat Logger */ void * maat_logger; - /* HTTPSCAN */ - std::unique_ptr<HttpScan> http_scan_module; - /* Http */ + /* HTTPSCAN */ + std::unique_ptr<HttpScan> http_scan_module; + /* Http */ std::unique_ptr<Http> http_module; /* Struct Logger */ std::unique_ptr<StructLogger> struct_logger_module; /* stat handler */ - struct tfe_stat_ctx * stat_module; + struct tfe_stat_ctx * stat_module; }; struct tfe_maat_config { - /* Maat Params */ - std::string str_table_info_file; - std::string str_log_file_path; - std::string str_interface_symbol; - std::string str_stat_file; - - /* Maat Config Source */ - enum cfg_load_from_t - { - LOAD_FROM_JSON_FILE = 0, - LOAD_FROM_REDIS_SERVER = 1, - LOAD_FROM_LOAD_IRIS = 2 - }; - - cfg_load_from_t cfg_load_from; - - /* from JSON FILE */ - std::string str_json_file_path; - /* from REDIR Server */ - std::string str_redis_addr; - unsigned short redir_port; - unsigned int redis_db_index; - - /* from IRIS */ - std::string str_full_cfg_dir; - std::string str_inc_cfg_dir; + /* Maat Params */ + std::string str_table_info_file; + std::string str_log_file_path; + std::string str_interface_symbol; + std::string str_stat_file; + + /* Maat Config Source */ + enum cfg_load_from_t + { + LOAD_FROM_JSON_FILE = 0, + LOAD_FROM_REDIS_SERVER = 1, + LOAD_FROM_LOAD_IRIS = 2 + }; + + cfg_load_from_t cfg_load_from; + + /* from JSON FILE */ + std::string str_json_file_path; + /* from REDIR Server */ + std::string str_redis_addr; + unsigned short redir_port; + unsigned int redis_db_index; + + /* from IRIS */ + std::string str_full_cfg_dir; + std::string str_inc_cfg_dir; + + /* scan interval */ + bool is_effect_interval_ms_set{false}; + unsigned int effect_interval_ms; + + bool is_scan_interval_ms_set{false}; + unsigned int scan_interval_ms; }; struct tfe_forgesocket_config @@ -122,62 +129,62 @@ struct tfe_forgesocket_config struct tfe_config { - /* Configure Files */ - char * cfgfile; - - /* Options */ - unsigned int debug : 1; - unsigned int detach : 1; - unsigned int sslcomp : 1; - unsigned int no_ssl2 : 1; - unsigned int no_ssl3 : 1; - unsigned int no_tls10 : 1; - unsigned int no_tls11 : 1; - unsigned int no_tls12 : 1; - unsigned int passthrough : 1; - unsigned int deny_ocsp : 1; - unsigned int contentlog_isdir : 1; - unsigned int contentlog_isspec : 1; - unsigned int certgen_writeall: 1; - - char *ciphers; - char *certgendir; - char *tgcrtdir; - char *dropuser; - char *dropgroup; - char *jaildir; - char *pidfile; - char *connectlog; - char *contentlog; - char *contentlog_basedir; /* static part of logspec, for privsep srv */ - char *masterkeylog; - CONST_SSL_METHOD *(*sslmethod)(void); - int sslversion; - X509 *cacrt; - EVP_PKEY *cakey; - EVP_PKEY *key; - STACK_OF(X509) *chain; - DH *dh; - char *ecdhcurve; - - struct proxyspec * spec; - char *crlurl; - - tfe_maat_config * maat_config; - tfe_forgesocket_config * forgesocket_config; + /* Configure Files */ + char * cfgfile; + + /* Options */ + unsigned int debug : 1; + unsigned int detach : 1; + unsigned int sslcomp : 1; + unsigned int no_ssl2 : 1; + unsigned int no_ssl3 : 1; + unsigned int no_tls10 : 1; + unsigned int no_tls11 : 1; + unsigned int no_tls12 : 1; + unsigned int passthrough : 1; + unsigned int deny_ocsp : 1; + unsigned int contentlog_isdir : 1; + unsigned int contentlog_isspec : 1; + unsigned int certgen_writeall: 1; + + char * ciphers; + char * certgendir; + char * tgcrtdir; + char * dropuser; + char * dropgroup; + char * jaildir; + char * pidfile; + char * connectlog; + char * contentlog; + char * contentlog_basedir; /* static part of logspec, for privsep srv */ + char * masterkeylog; + CONST_SSL_METHOD * (* sslmethod)(void); + int sslversion; + X509 * cacrt; + EVP_PKEY * cakey; + EVP_PKEY * key; + STACK_OF(X509) * chain; + DH * dh; + char * ecdhcurve; + + struct proxyspec * spec; + char * crlurl; + + tfe_maat_config * maat_config; + tfe_forgesocket_config * forgesocket_config; }; extern tfe_instance * g_tfe_instance; extern tfe_config * g_tfe_config; -struct tfe_config *tfe_config_new(void) MALLOC; +struct tfe_config * tfe_config_new(void) MALLOC; void tfe_config_free(struct tfe_config *) NONNULL(1); int tfe_config_has_ssl_spec(struct tfe_config *) NONNULL(1) WUNRES; int tfe_config_has_dns_spec(struct tfe_config *) NONNULL(1) WUNRES; -void tfe_config_proto_force(struct tfe_config *, const char *, const char *) NONNULL(1,2,3); -void tfe_config_proto_disable(struct tfe_config *, const char *, const char *) NONNULL(1,2,3); +void tfe_config_proto_force(struct tfe_config *, const char *, const char *) NONNULL(1, 2, 3); +void tfe_config_proto_disable(struct tfe_config *, const char *, const char *) NONNULL(1, 2, 3); void tfe_config_proto_dbg_dump(struct tfe_config *) NONNULL(1); -void tfe_config_load_from_file(tfe_config *cfg, const char *c_str_file); +void tfe_config_load_from_file(tfe_config * cfg, const char * c_str_file); #define OPTS_DEBUG(opts) unlikely((opts)->debug) diff --git a/src/pxyconn.cc b/src/pxyconn.cc index b1bba5a..7e58886 100644 --- a/src/pxyconn.cc +++ b/src/pxyconn.cc @@ -841,8 +841,6 @@ static SSL * pxy_srcssl_create(pxy_conn_ctx_t * ctx, SSL * origssl) SSL_get0_session(origssl)); ctx->origcrt = SSL_get_peer_certificate(origssl); - LOG(INFO) << SSL_get_verify_result(origssl); - if (OPTS_DEBUG(ctx->opts)) { if (ctx->origcrt) @@ -1056,9 +1054,6 @@ pxy_dstssl_create(pxy_conn_ctx_t * ctx) } #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ - SSL_CTX_load_verify_locations(sslctx, "/etc/pki/tls/cert.pem", nullptr); - SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, NULL); - ssl = SSL_new(sslctx); SSL_CTX_free(sslctx); /* SSL_new() increments refcount */ if (!ssl) @@ -1665,10 +1660,8 @@ connected: SSL_get_version(this_conn->ssl), SSL_get_cipher(this_conn->ssl), this_conn); keystr = ssl_ssl_masterkey_to_str(this_conn->ssl); - if (keystr) - { - log_dbg_print_free(keystr); - } + CLOG(INFO, "MasterLog") << keystr; + free(keystr); } else { @@ -595,8 +595,7 @@ char * ssl_ssl_masterkey_to_str(SSL *ssl) "%02X%02X%02X%02X%02X%02X%02X%02X" "%02X%02X%02X%02X%02X%02X%02X%02X" "%02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X%02X" - "\n", + "%02X%02X%02X%02X%02X%02X%02X%02X", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15], r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23], |
