diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-12-09 14:02:18 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-12-09 14:02:18 +0000 |
commit | 05d6d354ec99e800007828137315b42be332c719 (patch) | |
tree | 4f357f0795a28202e0e5703506dc1d9069deafa9 /src | |
parent | 4fe64bdcb51eb13b732bfcab0ffb321b16e91395 (diff) | |
download | rspamd-05d6d354ec99e800007828137315b42be332c719.tar.gz rspamd-05d6d354ec99e800007828137315b42be332c719.zip |
[Feature] Allow to skip DNS resolution for keep-alive connections
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/http/http_context.c | 56 | ||||
-rw-r--r-- | src/libserver/http/http_context.h | 20 | ||||
-rw-r--r-- | src/libserver/http/http_private.h | 1 | ||||
-rw-r--r-- | src/lua/lua_http.c | 42 |
4 files changed, 91 insertions, 28 deletions
diff --git a/src/libserver/http/http_context.c b/src/libserver/http/http_context.c index b56f1c4c0..2dbaff0a4 100644 --- a/src/libserver/http/http_context.c +++ b/src/libserver/http/http_context.c @@ -365,19 +365,18 @@ rspamd_http_context_default (void) gint32 rspamd_keep_alive_key_hash (struct rspamd_keepalive_hash_key *k) { - guint32 h; + rspamd_cryptobox_fast_hash_state_t hst; - h = rspamd_inet_address_port_hash (k->addr); + rspamd_cryptobox_fast_hash_init (&hst, 0); if (k->host) { - h ^= rspamd_cryptobox_fast_hash (k->host, strlen (k->host), h); + rspamd_cryptobox_fast_hash_update (&hst, k->host, strlen (k->host)); } - if (k->is_ssl) { - h = ~h; - } + rspamd_cryptobox_fast_hash_update (&hst, &k->port, sizeof(k->port)); + rspamd_cryptobox_fast_hash_update (&hst, &k->is_ssl, sizeof(k->is_ssl)); - return (gint32)h; + return rspamd_cryptobox_fast_hash_final (&hst); } bool @@ -389,12 +388,12 @@ rspamd_keep_alive_key_equal (struct rspamd_keepalive_hash_key *k1, } if (k1->host && k2->host) { - if (rspamd_inet_address_port_equal (k1->addr, k2->addr)) { + if (k1->port == k2->port) { return strcmp (k1->host, k2->host) == 0; } } else if (!k1->host && !k2->host) { - return rspamd_inet_address_port_equal (k1->addr, k2->addr); + return (k1->port == k2->port); } /* One has host and another has no host */ @@ -410,8 +409,13 @@ rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx, struct rspamd_keepalive_hash_key hk, *phk; khiter_t k; + if (ctx == NULL) { + ctx = rspamd_http_context_default (); + } + hk.addr = (rspamd_inet_addr_t *)addr; hk.host = (gchar *)host; + hk.port = rspamd_inet_address_get_port (addr); hk.is_ssl = is_ssl; k = kh_get (rspamd_keep_alive_hash, ctx->keep_alive_hash, &hk); @@ -471,6 +475,37 @@ rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx, return NULL; } +const rspamd_inet_addr_t * +rspamd_http_context_has_keepalive(struct rspamd_http_context *ctx, + const gchar *host, + unsigned port, + bool is_ssl) +{ + struct rspamd_keepalive_hash_key hk, *phk; + khiter_t k; + + if (ctx == NULL) { + ctx = rspamd_http_context_default (); + } + + hk.host = (gchar *)host; + hk.port = port; + hk.is_ssl = is_ssl; + + k = kh_get (rspamd_keep_alive_hash, ctx->keep_alive_hash, &hk); + + if (k != kh_end (ctx->keep_alive_hash)) { + phk = kh_key (ctx->keep_alive_hash, k); + GQueue *conns = &phk->conns; + + if (g_queue_get_length(conns) > 0) { + return phk->addr; + } + } + + return NULL; +} + void rspamd_http_context_prepare_keepalive(struct rspamd_http_context *ctx, struct rspamd_http_connection *conn, @@ -484,6 +519,7 @@ rspamd_http_context_prepare_keepalive(struct rspamd_http_context *ctx, hk.addr = (rspamd_inet_addr_t *)addr; hk.host = (gchar *)host; hk.is_ssl = is_ssl; + hk.port = rspamd_inet_address_get_port (addr); k = kh_get (rspamd_keep_alive_hash, ctx->keep_alive_hash, &hk); @@ -504,6 +540,8 @@ rspamd_http_context_prepare_keepalive(struct rspamd_http_context *ctx, phk->host = g_strdup (host); phk->is_ssl = is_ssl; phk->addr = rspamd_inet_address_copy (addr); + phk->port = hk.port; + kh_put (rspamd_keep_alive_hash, ctx->keep_alive_hash, phk, &r); conn->keepalive_hash_key = phk; diff --git a/src/libserver/http/http_context.h b/src/libserver/http/http_context.h index f42164dba..635da7ba5 100644 --- a/src/libserver/http/http_context.h +++ b/src/libserver/http/http_context.h @@ -74,9 +74,23 @@ struct rspamd_http_context *rspamd_http_context_default (void); * @param host * @return */ -struct rspamd_http_connection * -rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx, const rspamd_inet_addr_t *addr, const gchar *host, - bool is_ssl); +struct rspamd_http_connection * rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx, + const rspamd_inet_addr_t *addr, + const gchar *host, + bool is_ssl); + +/** + * Checks if there is a valid keepalive connection + * @param ctx + * @param addr + * @param host + * @param is_ssl + * @return + */ +const rspamd_inet_addr_t *rspamd_http_context_has_keepalive(struct rspamd_http_context *ctx, + const gchar *host, + unsigned port, + bool is_ssl); /** * Prepares keepalive key for a connection by creating a new entry or by reusing existent diff --git a/src/libserver/http/http_private.h b/src/libserver/http/http_private.h index c6a5b497b..0e48d9f3c 100644 --- a/src/libserver/http/http_private.h +++ b/src/libserver/http/http_private.h @@ -87,6 +87,7 @@ struct rspamd_keepalive_hash_key { rspamd_inet_addr_t *addr; gchar *host; gboolean is_ssl; + unsigned port; GQueue conns; }; diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c index 1fee9e313..85aa04e1f 100644 --- a/src/lua/lua_http.c +++ b/src/lua/lua_http.c @@ -389,6 +389,7 @@ lua_http_make_connection (struct lua_http_cbdata *cbd) { rspamd_inet_address_set_port (cbd->addr, cbd->msg->port); unsigned http_opts = RSPAMD_HTTP_CLIENT_SIMPLE; + struct rspamd_http_message *msg = cbd->msg; if (cbd->msg->flags & RSPAMD_HTTP_FLAG_WANT_SSL) { http_opts |= RSPAMD_HTTP_CLIENT_SSL; @@ -1036,20 +1037,6 @@ lua_http_request (lua_State *L) } - const rspamd_ftok_t *host_header_tok = rspamd_http_message_find_header (msg, "Host"); - if (host_header_tok != NULL) { - if (msg->host) { - g_string_free (msg->host, true); - } - msg->host = g_string_new_len (host_header_tok->begin, host_header_tok->len); - cbd->host = msg->host->str; - } - else { - if (msg->host) { - cbd->host = msg->host->str; - } - } - if (body) { if (gzip) { if (rspamd_fstring_gzip (&body)) { @@ -1064,8 +1051,31 @@ lua_http_request (lua_State *L) cbd->session = session; } - if (msg->host && rspamd_parse_inet_address (&cbd->addr, - msg->host->str, msg->host->len, RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) { + bool numeric_ip = false; + + /* Check if we can skip resolving */ + if (msg->host) { + cbd->host = msg->host->str; + + if (cbd->flags & RSPAMD_LUA_HTTP_FLAG_KEEP_ALIVE) { + const rspamd_inet_addr_t *ka_addr = rspamd_http_context_has_keepalive(NULL, + msg->host->str, msg->port, msg->flags & RSPAMD_HTTP_FLAG_WANT_SSL); + + if (ka_addr) { + cbd->addr = rspamd_inet_address_copy(ka_addr); + numeric_ip = true; + } + } + + if (!cbd->addr) { + if (rspamd_parse_inet_address (&cbd->addr, + msg->host->str, msg->host->len, RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) { + numeric_ip = true; + } + } + } + + if (numeric_ip) { /* Host is numeric IP, no need to resolve */ gboolean ret; |