commit f0dc58b: [Project] More rework for HTTP proxy support

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Mar 18 16:21:06 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-03-18 15:32:54 +0000
URL: https://github.com/rspamd/rspamd/commit/f0dc58b678766902780598c9cdffed8188e070f5

[Project] More rework for HTTP proxy support

---
 src/libutil/http_connection.c | 157 +++++++++++++++++++++++++++---------------
 src/libutil/http_connection.h |   1 -
 src/plugins/surbl.c           |   6 +-
 3 files changed, 104 insertions(+), 60 deletions(-)

diff --git a/src/libutil/http_connection.c b/src/libutil/http_connection.c
index d782c2d13..e75e26a45 100644
--- a/src/libutil/http_connection.c
+++ b/src/libutil/http_connection.c
@@ -51,6 +51,7 @@ enum rspamd_http_priv_flags {
 	RSPAMD_HTTP_CONN_FLAG_ENCRYPTION_NEEDED = 1 << 4,
 	RSPAMD_HTTP_CONN_FLAG_PROXY = 1 << 5,
 	RSPAMD_HTTP_CONN_FLAG_PROXY_REQUEST = 1 << 6,
+	RSPAMD_HTTP_CONN_OWN_SOCKET = 1 << 7,
 };
 
 #define IS_CONN_ENCRYPTED(c) ((c)->flags & RSPAMD_HTTP_CONN_FLAG_ENCRYPTED)
@@ -1078,24 +1079,25 @@ rspamd_http_parser_reset (struct rspamd_http_connection *conn)
 	priv->parser_cb.on_message_complete = rspamd_http_on_message_complete;
 }
 
-struct rspamd_http_connection *
-rspamd_http_connection_new_server (struct rspamd_http_context *ctx,
+static struct rspamd_http_connection *
+rspamd_http_connection_new_common (struct rspamd_http_context *ctx,
 								   gint fd,
 								   rspamd_http_body_handler_t body_handler,
 								   rspamd_http_error_handler_t error_handler,
 								   rspamd_http_finish_handler_t finish_handler,
-								   unsigned opts)
+								   unsigned opts,
+								   enum rspamd_http_connection_type type,
+								   enum rspamd_http_priv_flags priv_flags,
+								   struct upstream *proxy_upstream)
 {
 	struct rspamd_http_connection *conn;
 	struct rspamd_http_connection_private *priv;
 
-	if (error_handler == NULL || finish_handler == NULL) {
-		return NULL;
-	}
+	g_assert (error_handler != NULL && finish_handler == NULL);
 
 	conn = g_malloc0 (sizeof (struct rspamd_http_connection));
 	conn->opts = opts;
-	conn->type = RSPAMD_HTTP_SERVER;
+	conn->type = type;
 	conn->body_handler = body_handler;
 	conn->error_handler = error_handler;
 	conn->finish_handler = finish_handler;
@@ -1111,8 +1113,17 @@ rspamd_http_connection_new_server (struct rspamd_http_context *ctx,
 	priv = g_malloc0 (sizeof (struct rspamd_http_connection_private));
 	conn->priv = priv;
 	priv->ctx = ctx;
+	priv->flags = priv_flags;
 
-	priv->cache = ctx->server_kp_cache;
+	if (type == RSPAMD_HTTP_SERVER) {
+		priv->cache = ctx->server_kp_cache;
+	}
+	else {
+		priv->cache = ctx->client_kp_cache;
+		if (ctx->client_kp) {
+			priv->local_key = rspamd_keypair_ref (ctx->client_kp);
+		}
+	}
 
 	rspamd_http_parser_reset (conn);
 	priv->parser.data = conn;
@@ -1120,6 +1131,18 @@ rspamd_http_connection_new_server (struct rspamd_http_context *ctx,
 	return conn;
 }
 
+struct rspamd_http_connection *
+rspamd_http_connection_new_server (struct rspamd_http_context *ctx,
+								   gint fd,
+								   rspamd_http_body_handler_t body_handler,
+								   rspamd_http_error_handler_t error_handler,
+								   rspamd_http_finish_handler_t finish_handler,
+								   unsigned opts)
+{
+	return rspamd_http_connection_new_common (ctx, fd, body_handler,
+			error_handler, finish_handler, opts, RSPAMD_HTTP_SERVER, 0, NULL);
+}
+
 struct rspamd_http_connection *
 rspamd_http_connection_new_client_socket (struct rspamd_http_context *ctx,
 								   rspamd_http_body_handler_t body_handler,
@@ -1128,39 +1151,8 @@ rspamd_http_connection_new_client_socket (struct rspamd_http_context *ctx,
 								   unsigned opts,
 								   gint fd)
 {
-	struct rspamd_http_connection *conn;
-	struct rspamd_http_connection_private *priv;
-
-	g_assert (error_handler != NULL && finish_handler == NULL);
-
-	conn = g_malloc0 (sizeof (struct rspamd_http_connection));
-	conn->opts = opts;
-	conn->type = RSPAMD_HTTP_CLIENT;
-	conn->body_handler = body_handler;
-	conn->error_handler = error_handler;
-	conn->finish_handler = finish_handler;
-	conn->fd = fd;
-	conn->ref = 1;
-	conn->finished = FALSE;
-
-	/* Init priv */
-	if (ctx == NULL) {
-		ctx = rspamd_http_context_default ();
-	}
-
-	priv = g_malloc0 (sizeof (struct rspamd_http_connection_private));
-	conn->priv = priv;
-	priv->ctx = ctx;
-
-	priv->cache = ctx->client_kp_cache;
-	if (ctx->client_kp) {
-		priv->local_key = rspamd_keypair_ref (ctx->client_kp);
-	}
-
-	rspamd_http_parser_reset (conn);
-	priv->parser.data = conn;
-
-	return conn;
+	return rspamd_http_connection_new_common (ctx, fd, body_handler,
+			error_handler, finish_handler, opts, RSPAMD_HTTP_CLIENT, 0, NULL);
 }
 
 struct rspamd_http_connection *
@@ -1173,21 +1165,77 @@ rspamd_http_connection_new_client (struct rspamd_http_context *ctx,
 {
 	gint fd;
 
-	if (error_handler == NULL || finish_handler == NULL) {
-		return NULL;
+	if (opts & RSPAMD_HTTP_CLIENT_ENCRYPTED) {
+		if (ctx->https_proxies) {
+			struct upstream *up = rspamd_upstream_get (ctx->https_proxies,
+					RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0);
+
+			if (up) {
+				rspamd_inet_addr_t *proxy_addr = rspamd_upstream_addr_next (up);
+
+				fd = rspamd_inet_address_connect (proxy_addr, SOCK_STREAM, TRUE);
+
+				if (fd == -1) {
+					msg_info ("cannot connect to https proxy %s: %s",
+							rspamd_inet_address_to_string (proxy_addr),
+							strerror (errno));
+					rspamd_upstream_fail (up, TRUE);
+
+					return NULL;
+				}
+
+				return rspamd_http_connection_new_common (ctx, fd, body_handler,
+						error_handler, finish_handler, opts,
+						RSPAMD_HTTP_CLIENT,
+						RSPAMD_HTTP_CONN_OWN_SOCKET|RSPAMD_HTTP_CONN_FLAG_PROXY,
+						up);
+			}
+		}
+	}
+	else {
+		if (ctx->http_proxies) {
+			struct upstream *up = rspamd_upstream_get (ctx->http_proxies,
+					RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0);
+
+			if (up) {
+				rspamd_inet_addr_t *proxy_addr = rspamd_upstream_addr_next (up);
+
+				fd = rspamd_inet_address_connect (proxy_addr, SOCK_STREAM, TRUE);
+
+				if (fd == -1) {
+					msg_info ("cannot connect to http proxy %s: %s",
+							rspamd_inet_address_to_string (proxy_addr),
+							strerror (errno));
+					rspamd_upstream_fail (up, TRUE);
+
+					return NULL;
+				}
+
+				return rspamd_http_connection_new_common (ctx, fd, body_handler,
+						error_handler, finish_handler, opts,
+						RSPAMD_HTTP_CLIENT,
+						RSPAMD_HTTP_CONN_OWN_SOCKET|RSPAMD_HTTP_CONN_FLAG_PROXY,
+						up);
+			}
+		}
 	}
 
+	/* Unproxied version */
 	fd = rspamd_inet_address_connect (addr, SOCK_STREAM, TRUE);
 
 	if (fd == -1) {
-		msg_info ("cannot connect to %s: %s", rspamd_inet_address_to_string (addr),
+		msg_info ("cannot connect to proxy %s: %s",
+				rspamd_inet_address_to_string (addr),
 				strerror (errno));
+
 		return NULL;
 	}
 
-	return rspamd_http_connection_new_client_socket (ctx,
-			body_handler, error_handler, finish_handler,
-			opts | RSPAMD_HTTP_OWN_SOCKET, fd);
+	return rspamd_http_connection_new_common (ctx, fd, body_handler,
+			error_handler, finish_handler, opts,
+			RSPAMD_HTTP_CLIENT,
+			RSPAMD_HTTP_CONN_OWN_SOCKET,
+			NULL);
 }
 
 struct rspamd_http_connection *
@@ -1200,10 +1248,6 @@ rspamd_http_connection_new_keepalive (struct rspamd_http_context *ctx,
 {
 	struct rspamd_http_connection *conn;
 
-	if (error_handler == NULL || finish_handler == NULL) {
-		return NULL;
-	}
-
 	if (ctx == NULL) {
 		ctx = rspamd_http_context_default ();
 	}
@@ -1437,12 +1481,12 @@ rspamd_http_connection_free (struct rspamd_http_connection *conn)
 			rspamd_pubkey_unref (priv->peer_key);
 		}
 
-		g_free (priv);
-	}
+		if (priv->flags & RSPAMD_HTTP_CONN_OWN_SOCKET) {
+			/* Fd is owned by a connection */
+			close (conn->fd);
+		}
 
-	if (conn->opts & RSPAMD_HTTP_OWN_SOCKET) {
-		/* Fd is owned by a connection */
-		close (conn->fd);
+		g_free (priv);
 	}
 
 	g_free (conn);
@@ -1810,6 +1854,7 @@ rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted,
 			}
 		}
 		else {
+			/* Normal HTTP/1.1 with Host */
 			if (encrypted) {
 				if (host != NULL) {
 					rspamd_printf_fstring (buf,
diff --git a/src/libutil/http_connection.h b/src/libutil/http_connection.h
index da354ac41..6240772da 100644
--- a/src/libutil/http_connection.h
+++ b/src/libutil/http_connection.h
@@ -85,7 +85,6 @@ enum rspamd_http_options {
 	RSPAMD_HTTP_CLIENT_SHARED = 1u << 3, /**< Store reply in shared memory */
 	RSPAMD_HTTP_REQUIRE_ENCRYPTION = 1u << 4,
 	RSPAMD_HTTP_CLIENT_KEEP_ALIVE = 1u << 5,
-	RSPAMD_HTTP_OWN_SOCKET = 1u << 6,
 };
 
 typedef int (*rspamd_http_body_handler_t) (struct rspamd_http_connection *conn,
diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c
index 3f1990b7b..11d3e35d9 100644
--- a/src/plugins/surbl.c
+++ b/src/plugins/surbl.c
@@ -1788,6 +1788,8 @@ register_redirector_call (struct rspamd_url *url, struct rspamd_task *task,
 
 		selected = rspamd_upstream_get (surbl_module_ctx->redirectors,
 				RSPAMD_UPSTREAM_ROUND_ROBIN, url->host, url->hostlen);
+		param = rspamd_mempool_alloc0 (task->task_pool,
+						sizeof (struct redirector_param));
 
 		if (selected) {
 			param->conn = rspamd_http_connection_new_client (NULL,
@@ -1806,9 +1808,7 @@ register_redirector_call (struct rspamd_url *url, struct rspamd_task *task,
 			return;
 		}
 
-		param =
-				rspamd_mempool_alloc (task->task_pool,
-						sizeof (struct redirector_param));
+
 		param->url = url;
 		param->task = task;
 		param->ctx = surbl_module_ctx;


More information about the Commits mailing list