]> source.dussan.org Git - rspamd.git/commitdiff
[Project] More rework for HTTP proxy support
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 18 Mar 2019 15:32:54 +0000 (15:32 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 18 Mar 2019 15:32:54 +0000 (15:32 +0000)
src/libutil/http_connection.c
src/libutil/http_connection.h
src/plugins/surbl.c

index d782c2d13ac2ad1474ffea9e372edcb4a29eae97..e75e26a45e52877cfcaf52c9b3035755d4ca43bd 100644 (file)
@@ -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,
index da354ac41305ccd7579400c3a50d2fadafe16f98..6240772da688fe773665e0e74499d5bd8d278c69 100644 (file)
@@ -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,
index 3f1990b7b6e40c55d0e1ab8baa6fd6e74d2385f9..11d3e35d934930a7ef3eb56e347e7261a5004a9a 100644 (file)
@@ -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;