From f920564ad191a111df16a2d03b9b4b921172f4de Mon Sep 17 00:00:00 2001 From: biathlon3 Date: Thu, 6 Jun 2024 09:04:39 +0400 Subject: [PATCH] jsch action is implemented. --- fw/http.c | 64 ++++++++++++++++++++++++++++--------------------- fw/http.h | 2 ++ fw/http_match.h | 1 + fw/http_sess.c | 56 ++++++++++++++++++++++++------------------- fw/http_tbl.c | 8 +++++++ fw/http_tbl.h | 1 + 6 files changed, 80 insertions(+), 52 deletions(-) diff --git a/fw/http.c b/fw/http.c index 3875067037..65725227fd 100644 --- a/fw/http.c +++ b/fw/http.c @@ -150,6 +150,7 @@ static struct { * here, because it refers to HTTP layer. */ unsigned int max_header_list_size = 0; +bool is_jsch_global = true; #define S_CRLFCRLF "\r\n\r\n" #define S_HTTP "http://" @@ -6029,6 +6030,13 @@ tfw_http_req_process(TfwConn *conn, TfwStream *stream, struct sk_buff *skb, "request has been filtered out via http table", HTTP2_ECODE_PROTO); } + if (res.type == TFW_HTTP_RES_JSCH) { + req->need_jsch = true; + req->vhost = res.vhost; + } + else { + req->need_jsch = is_jsch_global; + } if (res.type == TFW_HTTP_RES_VHOST) { req->vhost = res.vhost; } @@ -6134,37 +6142,39 @@ tfw_http_req_process(TfwConn *conn, TfwStream *stream, struct sk_buff *skb, * to GET. We should send js challenge to the client because the real * method, expected by the client is GET. */ - switch (tfw_http_sess_obtain(req)) { - case TFW_HTTP_SESS_SUCCESS: - break; + if (req->need_jsch) { + switch (tfw_http_sess_obtain(req)) { + case TFW_HTTP_SESS_SUCCESS: + break; - case TFW_HTTP_SESS_REDIRECT_NEED: - /* Response is built and stored in @req->resp. */ - break; + case TFW_HTTP_SESS_REDIRECT_NEED: + /* Response is built and stored in @req->resp. */ + break; - case TFW_HTTP_SESS_VIOLATE: - TFW_INC_STAT_BH(clnt.msgs_filtout); - return tfw_http_req_parse_block(req, 403, NULL, - HTTP2_ECODE_PROTO); + case TFW_HTTP_SESS_VIOLATE: + TFW_INC_STAT_BH(clnt.msgs_filtout); + return tfw_http_req_parse_block(req, 403, NULL, + HTTP2_ECODE_PROTO); - case TFW_HTTP_SESS_JS_NOT_SUPPORTED: - /* - * Requested resource can't be challenged, try service it - * from cache. - */ - T_DBG("Can't send JS challenge for request since a " - "non-challengeable resource (e.g. image) was requested"); - __set_bit(TFW_HTTP_B_JS_NOT_SUPPORTED, req->flags); - break; + case TFW_HTTP_SESS_JS_NOT_SUPPORTED: + /* + * Requested resource can't be challenged, try service it + * from cache. + */ + T_DBG("Can't send JS challenge for request since a " + "non-challengeable resource (e.g. image) was requested"); + __set_bit(TFW_HTTP_B_JS_NOT_SUPPORTED, req->flags); + break; - case TFW_HTTP_SESS_FAILURE: - TFW_INC_STAT_BH(clnt.msgs_otherr); - return tfw_http_req_parse_drop_with_fin(req, 500, - "request dropped: internal error" - " in Sticky module", - HTTP2_ECODE_PROTO); - default: - BUG(); + case TFW_HTTP_SESS_FAILURE: + TFW_INC_STAT_BH(clnt.msgs_otherr); + return tfw_http_req_parse_drop_with_fin(req, 500, + "request dropped: internal error" + " in Sticky module", + HTTP2_ECODE_PROTO); + default: + BUG(); + } } if (TFW_MSG_H2(req)) diff --git a/fw/http.h b/fw/http.h index 53b4402e71..650eeb0d47 100644 --- a/fw/http.h +++ b/fw/http.h @@ -400,6 +400,7 @@ struct tfw_http_req_t { unsigned char method_override; unsigned int header_list_sz; unsigned int headers_cnt; + bool need_jsch; }; #define TFW_IDX_BITS 24 @@ -722,6 +723,7 @@ typedef void (*tfw_http_cache_cb_t)(TfwHttpMsg *); (TFW_MSG_H2(hmmsg) ? HTTP2_EXTRA_HDR_OVERHEAD : 0) extern unsigned int max_header_list_size; +extern bool is_jsch_global; /* External HTTP functions. */ int tfw_http_msg_process(TfwConn *conn, struct sk_buff *skb, diff --git a/fw/http_match.h b/fw/http_match.h index 3da5b3df0b..59ef5b97f2 100644 --- a/fw/http_match.h +++ b/fw/http_match.h @@ -76,6 +76,7 @@ typedef enum { TFW_HTTP_MATCH_ACT_BLOCK, TFW_HTTP_MATCH_ACT_FLAG, TFW_HTTP_MATCH_ACT_CACHE_TTL, + TFW_HTTP_MATCH_ACT_JSCH, _TFW_HTTP_MATCH_ACT_COUNT } tfw_http_rule_act_t; diff --git a/fw/http_sess.c b/fw/http_sess.c index d68d3b502a..618f19aebb 100644 --- a/fw/http_sess.c +++ b/fw/http_sess.c @@ -588,17 +588,19 @@ tfw_http_sess_resp_process(TfwHttpResp *resp, bool cache) { return 0; } - BUG_ON(!req->sess); - - /* - * RFC 6265 4.1.1 and 4.1.2 says that we should not set session cookie - * if it's not necessary. Since client didn't send up the cookie and - * it seems that we don't enforce them, we can just set the cookie in - * each response forwarded to the client. - */ - if (test_bit(TFW_HTTP_B_HAS_STICKY, req->flags)) - return 0; - return tfw_http_sticky_add(resp, cache); + if (req->need_jsch) { + BUG_ON(!req->sess); + /* + * RFC 6265 4.1.1 and 4.1.2 says that we should not set session cookie + * if it's not necessary. Since client didn't send up the cookie and + * it seems that we don't enforce them, we can just set the cookie in + * each response forwarded to the client. + */ + if (test_bit(TFW_HTTP_B_HAS_STICKY, req->flags)) + return 0; + return tfw_http_sticky_add(resp, cache); + } + return 0; } /** @@ -666,6 +668,8 @@ tfw_http_sess_check_jsch(StickyVal *sv, TfwHttpReq* req) { unsigned long min_time; TfwCfgJsCh *js_ch = req->vhost->cookie->js_challenge; + if (!req->need_jsch) + return 0; if (!js_ch) return 0; @@ -843,20 +847,22 @@ tfw_http_sess_obtain(TfwHttpReq *req) * We leave this for administrator decision or more progressive DDoS * mitigation techniques. */ - r = tfw_http_sticky_req_process(req, sv, c_val); - switch (r) { - case TFW_HTTP_SESS_SUCCESS: - break; - case TFW_HTTP_SESS_FAILURE: - return r; - default: - /* - * Any js challenge processing error: cookie not found - * or invalid or request comes not in time. We increment - * max_misses and restart js challenge. - */ - BUG_ON(r < __TFW_HTTP_SESS_PUB_CODE_MAX); - return tfw_http_sticky_challenge_start(req); + if (req->need_jsch) { + r = tfw_http_sticky_req_process(req, sv, c_val); + switch (r) { + case TFW_HTTP_SESS_SUCCESS: + break; + case TFW_HTTP_SESS_FAILURE: + return r; + default: + /* + * Any js challenge processing error: cookie not found + * or invalid or request comes not in time. We increment + * max_misses and restart js challenge. + */ + BUG_ON(r < __TFW_HTTP_SESS_PUB_CODE_MAX); + return tfw_http_sticky_challenge_start(req); + } } if (req->vhost->cookie->learn) { diff --git a/fw/http_tbl.c b/fw/http_tbl.c index cf9a9ef8bd..ae2cea26cb 100644 --- a/fw/http_tbl.c +++ b/fw/http_tbl.c @@ -156,6 +156,10 @@ tfw_http_tbl_scan(TfwMsg *msg, TfwHttpTable *table, TfwHttpActionResult *action) return 0; case TFW_HTTP_MATCH_ACT_BLOCK: return -1; + case TFW_HTTP_MATCH_ACT_JSCH: + action->type = TFW_HTTP_RES_JSCH; + action->vhost = tfw_vhost_lookup_default(); + return 0; default: action->type = TFW_HTTP_RES_VHOST; @@ -499,6 +503,10 @@ tfw_cfgop_http_rule(TfwCfgSpec *cs, TfwCfgEntry *e) rule->act.type = TFW_HTTP_MATCH_ACT_CACHE_TTL; rule->act.cache_ttl = act_val_parsed; } + else if (!strcasecmp(action, "jsch")) { + is_jsch_global = false; + rule->act.type = TFW_HTTP_MATCH_ACT_JSCH; + } else if (action && action_val && !tfw_cfg_parse_uint(action, &rule->act.redir.resp_code)) { diff --git a/fw/http_tbl.h b/fw/http_tbl.h index 2f6f4bbe60..542546bffd 100644 --- a/fw/http_tbl.h +++ b/fw/http_tbl.h @@ -30,6 +30,7 @@ #define TFW_HTTP_RES_VHOST 0 #define TFW_HTTP_RES_REDIR 1 +#define TFW_HTTP_RES_JSCH 2 typedef struct { TfwStr url;