]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Feature] Implement HTTPS server support for workers
authorVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 9 Feb 2026 10:44:36 +0000 (10:44 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 9 Feb 2026 10:44:36 +0000 (10:44 +0000)
Wire up server-side SSL/TLS for HTTP workers, building on the recently
added rspamd_ssl_accept_fd() infrastructure. This enables HTTPS for
controller, normal, and proxy workers with per-bind-address granularity.

Configuration: `bind_socket = "*:11335 ssl"` plus `ssl_cert` and
`ssl_key` worker options.

- Add rspamd_init_ssl_ctx_server() for server SSL_CTX with cert+key
- Parse trailing " ssl" suffix in bind_socket lines
- Propagate is_ssl flag through bind conf to listen sockets
- Add rspamd_http_connection_accept_ssl() for async SSL handshake
- Fix write_message_common to handle server-side SSL responses
- Add SSL support to HTTP router (set_ssl, handle_socket_ssl)
- Wire up SSL in controller, normal worker, and proxy worker
- Add rspamd_worker_is_ssl_socket() utility for fd-to-SSL lookup

16 files changed:
src/controller.c
src/libserver/cfg_file.h
src/libserver/cfg_utils.cxx
src/libserver/http/http_connection.c
src/libserver/http/http_connection.h
src/libserver/http/http_router.c
src/libserver/http/http_router.h
src/libserver/ssl_util.c
src/libserver/ssl_util.h
src/libserver/worker_util.c
src/libserver/worker_util.h
src/rspamd.c
src/rspamd.h
src/rspamd_proxy.c
src/worker.c
src/worker_private.h

index 286dbebe5423ab7a51939775cb660727a19c5f2e..73a83d1f366e362e21479aa78a08a961a778a61b 100644 (file)
@@ -25,6 +25,7 @@
 #include "libstat/stat_api.h"
 #include "rspamd.h"
 #include "libserver/worker_util.h"
+#include "libserver/ssl_util.h"
 #include "worker_private.h"
 #include "lua/lua_common.h"
 #include "cryptobox.h"
@@ -3657,7 +3658,8 @@ rspamd_controller_accept_socket(EV_P_ ev_io *w, int revents)
        session->wrk = worker;
        worker->nconns++;
 
-       rspamd_http_router_handle_socket(ctx->http, nfd, session);
+       rspamd_http_router_handle_socket_ssl(ctx->http, nfd, session,
+                                                                                rspamd_worker_is_ssl_socket(worker, w->fd));
 }
 
 static void
@@ -3726,7 +3728,7 @@ init_controller_worker(struct rspamd_config *cfg)
                                                                          ctx,
                                                                          G_STRUCT_OFFSET(struct rspamd_controller_worker_ctx, use_ssl),
                                                                          0,
-                                                                         "Unimplemented");
+                                                                         "Enable SSL for this worker");
 
        rspamd_rcl_register_worker_option(cfg,
                                                                          type,
@@ -3735,7 +3737,7 @@ init_controller_worker(struct rspamd_config *cfg)
                                                                          ctx,
                                                                          G_STRUCT_OFFSET(struct rspamd_controller_worker_ctx, ssl_cert),
                                                                          0,
-                                                                         "Unimplemented");
+                                                                         "Path to SSL certificate chain file");
 
        rspamd_rcl_register_worker_option(cfg,
                                                                          type,
@@ -3744,7 +3746,7 @@ init_controller_worker(struct rspamd_config *cfg)
                                                                          ctx,
                                                                          G_STRUCT_OFFSET(struct rspamd_controller_worker_ctx, ssl_key),
                                                                          0,
-                                                                         "Unimplemented");
+                                                                         "Path to SSL private key file");
        rspamd_rcl_register_worker_option(cfg,
                                                                          type,
                                                                          "timeout",
@@ -4117,6 +4119,19 @@ start_controller_worker(struct rspamd_worker *worker)
                                                                           rspamd_controller_finish_handler, ctx->timeout,
                                                                           ctx->static_files_dir, ctx->http_ctx);
 
+       if (ctx->use_ssl && ctx->ssl_cert && ctx->ssl_key) {
+               gpointer server_ssl_ctx = rspamd_init_ssl_ctx_server(ctx->ssl_cert, ctx->ssl_key);
+
+               if (server_ssl_ctx) {
+                       rspamd_ssl_ctx_config(ctx->cfg, server_ssl_ctx);
+                       rspamd_http_router_set_ssl(ctx->http, server_ssl_ctx);
+                       msg_info_ctx("enabled SSL for controller worker");
+               }
+               else {
+                       msg_err_ctx("failed to create SSL context for controller worker");
+               }
+       }
+
        /* Add callbacks for different methods */
        rspamd_http_router_add_path(ctx->http,
                                                                PATH_AUTH,
index ed0c1f1670c79fffd6eb5eec740bbc2cd53f4813..5b9022e2dbbaff4c7b682c4534018ebb6fb8c696 100644 (file)
@@ -196,6 +196,7 @@ struct rspamd_worker_bind_conf {
        char *name;
        char *bind_line;
        gboolean is_systemd;
+       gboolean is_ssl;
        struct rspamd_worker_bind_conf *next;
 };
 
index a70473adc489613212d1c9277d8cf02a279f826f..edee9cb8985dbd740c9ab2b120a92a38809688f8 100644 (file)
@@ -189,6 +189,18 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
 
        auto bind_line = std::string_view{cnf->bind_line};
 
+       /* Check for trailing " ssl" suffix (case-insensitive) */
+       if (bind_line.size() > 4 &&
+               bind_line[bind_line.size() - 4] == ' ' &&
+               g_ascii_tolower(bind_line[bind_line.size() - 3]) == 's' &&
+               g_ascii_tolower(bind_line[bind_line.size() - 2]) == 's' &&
+               g_ascii_tolower(bind_line[bind_line.size() - 1]) == 'l') {
+               cnf->is_ssl = TRUE;
+               /* Strip the suffix for address parsing */
+               cnf->bind_line[bind_line.size() - 4] = '\0';
+               bind_line = std::string_view{cnf->bind_line};
+       }
+
        if (bind_line.starts_with("systemd:")) {
                /* The actual socket will be passed by systemd environment */
                fdname = str + sizeof("systemd:") - 1;
index 18350716585b3c078fb030340d250bc5beedd978..117d2e4334a05be90a81cd5b716e55d3b8605163 100644 (file)
@@ -2573,6 +2573,14 @@ if (conn->opts & RSPAMD_HTTP_CLIENT_SSL) {
                }
        }
 }
+else if (priv->ssl) {
+       /* Server-side SSL: connection already established, restore handlers */
+       rspamd_ssl_connection_restore_handlers(priv->ssl,
+                                                                                  rspamd_http_event_handler,
+                                                                                  rspamd_http_ssl_err_handler,
+                                                                                  conn,
+                                                                                  EV_WRITE);
+}
 else {
        /* Watch for READ too on client to detect early server responses */
        short ev_flags = (conn->type == RSPAMD_HTTP_CLIENT) ? (EV_WRITE | EV_READ) : EV_WRITE;
@@ -2897,3 +2905,90 @@ double rspamd_http_connection_keepalive_idle_timeout(struct rspamd_http_connecti
        struct rspamd_http_connection_private *priv = conn->priv;
        return (priv->ka_idle_override > 0 ? priv->ka_idle_override : default_idle);
 }
+
+static void
+rspamd_http_ssl_accept_handler(int fd, short what, gpointer ud)
+{
+       struct rspamd_http_connection *conn = (struct rspamd_http_connection *) ud;
+       struct rspamd_http_connection_private *priv = conn->priv;
+
+       /* SSL handshake complete, start reading HTTP message */
+       rspamd_http_connection_read_message_common(conn, conn->ud, priv->timeout, 0);
+}
+
+static void
+rspamd_http_ssl_accept_shared_handler(int fd, short what, gpointer ud)
+{
+       struct rspamd_http_connection *conn = (struct rspamd_http_connection *) ud;
+       struct rspamd_http_connection_private *priv = conn->priv;
+
+       /* SSL handshake complete, start reading HTTP message with shared body */
+       rspamd_http_connection_read_message_common(conn, conn->ud, priv->timeout,
+                                                                                          RSPAMD_HTTP_FLAG_SHMEM);
+}
+
+static gboolean
+rspamd_http_connection_accept_ssl_common(struct rspamd_http_connection *conn,
+                                                                                gpointer ssl_ctx,
+                                                                                gpointer ud,
+                                                                                ev_tstamp timeout,
+                                                                                rspamd_ssl_handler_t accept_handler)
+{
+       struct rspamd_http_connection_private *priv = conn->priv;
+       GError *err;
+
+       g_assert(conn != NULL);
+       g_assert(ssl_ctx != NULL);
+
+       conn->ud = ud;
+       priv->timeout = timeout;
+
+       priv->ssl = rspamd_ssl_connection_new(ssl_ctx, priv->ctx->event_loop,
+                                                                                 FALSE, conn->log_tag);
+
+       if (priv->ssl == NULL) {
+               err = g_error_new(HTTP_ERROR, 400, "cannot create SSL connection");
+               rspamd_http_connection_ref(conn);
+               conn->error_handler(conn, err);
+               rspamd_http_connection_unref(conn);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       if (!rspamd_ssl_accept_fd(priv->ssl, conn->fd, &priv->ev,
+                                                         timeout, accept_handler,
+                                                         rspamd_http_ssl_err_handler, conn)) {
+
+               err = g_error_new(HTTP_ERROR, 400,
+                                                 "ssl accept error: ssl error=%s, errno=%s",
+                                                 ERR_error_string(ERR_get_error(), NULL),
+                                                 strerror(errno));
+               rspamd_http_connection_ref(conn);
+               conn->error_handler(conn, err);
+               rspamd_http_connection_unref(conn);
+               g_error_free(err);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean
+rspamd_http_connection_accept_ssl(struct rspamd_http_connection *conn,
+                                                                 gpointer ssl_ctx,
+                                                                 gpointer ud,
+                                                                 ev_tstamp timeout)
+{
+       return rspamd_http_connection_accept_ssl_common(conn, ssl_ctx, ud, timeout,
+                                                                                                       rspamd_http_ssl_accept_handler);
+}
+
+gboolean
+rspamd_http_connection_accept_ssl_shared(struct rspamd_http_connection *conn,
+                                                                                gpointer ssl_ctx,
+                                                                                gpointer ud,
+                                                                                ev_tstamp timeout)
+{
+       return rspamd_http_connection_accept_ssl_common(conn, ssl_ctx, ud, timeout,
+                                                                                                       rspamd_http_ssl_accept_shared_handler);
+}
index 879417b9f841982a1c14656c4ffdbe31c6295671..32a902d5bf7727059b64d457dba65c1d4cfba539 100644 (file)
@@ -345,6 +345,29 @@ void rspamd_http_connection_set_max_size(struct rspamd_http_connection *conn,
 
 void rspamd_http_connection_disable_encryption(struct rspamd_http_connection *conn);
 
+/**
+ * Accept SSL on an existing server connection. Performs the SSL handshake
+ * asynchronously and then starts HTTP message reading.
+ * @param conn server connection (already created via rspamd_http_connection_new_server)
+ * @param ssl_ctx server SSL context (from rspamd_init_ssl_ctx_server)
+ * @param ud opaque user data
+ * @param timeout handshake/IO timeout
+ * @return TRUE if handshake was initiated
+ */
+gboolean rspamd_http_connection_accept_ssl(struct rspamd_http_connection *conn,
+                                                                                  gpointer ssl_ctx,
+                                                                                  gpointer ud,
+                                                                                  ev_tstamp timeout);
+
+/**
+ * Accept SSL on an existing server connection with shared memory body.
+ * Same as rspamd_http_connection_accept_ssl but starts reading in shared mode.
+ */
+gboolean rspamd_http_connection_accept_ssl_shared(struct rspamd_http_connection *conn,
+                                                                                                 gpointer ssl_ctx,
+                                                                                                 gpointer ud,
+                                                                                                 ev_tstamp timeout);
+
 #ifdef __cplusplus
 }
 #endif
index fd472460508a5697fb8edfd2dbc8fb2b8dc70ee2..b5255e0e46a66287553c94a91a6105a675a0b38c 100644 (file)
@@ -18,6 +18,7 @@
 #include "http_connection.h"
 #include "http_private.h"
 #include "libserver/http_content_negotiation.h"
+#include "libserver/ssl_util.h"
 #include "libutil/regexp.h"
 #include "libutil/printf.h"
 #include "libserver/logger.h"
@@ -515,8 +516,15 @@ void rspamd_http_router_add_regexp(struct rspamd_http_connection_router *router,
        }
 }
 
-void rspamd_http_router_handle_socket(struct rspamd_http_connection_router *router,
-                                                                         int fd, gpointer ud)
+void rspamd_http_router_set_ssl(struct rspamd_http_connection_router *router,
+                                                               gpointer ssl_ctx)
+{
+       g_assert(router != NULL);
+       router->server_ssl_ctx = ssl_ctx;
+}
+
+void rspamd_http_router_handle_socket_ssl(struct rspamd_http_connection_router *router,
+                                                                                 int fd, gpointer ud, gboolean ssl)
 {
        struct rspamd_http_connection_entry *conn;
 
@@ -536,10 +544,23 @@ void rspamd_http_router_handle_socket(struct rspamd_http_connection_router *rout
                rspamd_http_connection_set_key(conn->conn, router->key);
        }
 
-       rspamd_http_connection_read_message(conn->conn, conn, router->timeout);
+       if (ssl && router->server_ssl_ctx) {
+               rspamd_http_connection_accept_ssl(conn->conn, router->server_ssl_ctx,
+                                                                                 conn, router->timeout);
+       }
+       else {
+               rspamd_http_connection_read_message(conn->conn, conn, router->timeout);
+       }
+
        DL_PREPEND(router->conns, conn);
 }
 
+void rspamd_http_router_handle_socket(struct rspamd_http_connection_router *router,
+                                                                         int fd, gpointer ud)
+{
+       rspamd_http_router_handle_socket_ssl(router, fd, ud, FALSE);
+}
+
 void rspamd_http_router_free(struct rspamd_http_connection_router *router)
 {
        struct rspamd_http_connection_entry *conn, *tmp;
@@ -556,6 +577,10 @@ void rspamd_http_router_free(struct rspamd_http_connection_router *router)
                        rspamd_keypair_unref(router->key);
                }
 
+               if (router->server_ssl_ctx) {
+                       rspamd_ssl_ctx_free(router->server_ssl_ctx);
+               }
+
                if (router->default_fs_path != NULL) {
                        g_free(router->default_fs_path);
                }
index 6977d6e736a2125a72c69357a658973ed9d39c86..f3ce54effc79ce6b8bb9ac5daebc9a1febd34c27 100644 (file)
@@ -59,6 +59,7 @@ struct rspamd_http_connection_router {
        struct rspamd_cryptobox_keypair *key;
        rspamd_http_router_error_handler_t error_handler;
        rspamd_http_router_finish_handler_t finish_handler;
+       gpointer server_ssl_ctx;
 };
 
 /**
@@ -126,6 +127,14 @@ struct rspamd_regexp_s;
 void rspamd_http_router_add_regexp(struct rspamd_http_connection_router *router,
                                                                   struct rspamd_regexp_s *re, rspamd_http_router_handler_t handler);
 
+/**
+ * Set server SSL context for the router
+ * @param router router object
+ * @param ssl_ctx server SSL context (from rspamd_init_ssl_ctx_server)
+ */
+void rspamd_http_router_set_ssl(struct rspamd_http_connection_router *router,
+                                                               gpointer ssl_ctx);
+
 /**
  * Handle new accepted socket
  * @param router router object
@@ -137,6 +146,19 @@ void rspamd_http_router_handle_socket(
        int fd,
        gpointer ud);
 
+/**
+ * Handle new accepted socket with optional SSL
+ * @param router router object
+ * @param fd server socket
+ * @param ud opaque userdata
+ * @param ssl whether to use SSL on this socket
+ */
+void rspamd_http_router_handle_socket_ssl(
+       struct rspamd_http_connection_router *router,
+       int fd,
+       gpointer ud,
+       gboolean ssl);
+
 /**
  * Free router and all connections associated
  * @param router
index f41d310579c257a84ab99660000123a0941f942e..af2b360ac49f5cabd28d5d0edac9fd039aca380f 100644 (file)
@@ -1170,6 +1170,51 @@ gpointer rspamd_init_ssl_ctx_noverify(void)
 
        return ssl_ctx_noverify;
 }
+
+gpointer
+rspamd_init_ssl_ctx_server(const char *cert_path, const char *key_path)
+{
+       struct rspamd_ssl_ctx *ctx;
+
+       g_assert(cert_path != NULL);
+       g_assert(key_path != NULL);
+
+       ctx = rspamd_init_ssl_ctx_common();
+
+       /* Server-side session cache */
+       SSL_CTX_set_session_cache_mode(ctx->s, SSL_SESS_CACHE_SERVER);
+       /* Remove client session callback set by common init */
+       SSL_CTX_sess_set_new_cb(ctx->s, NULL);
+
+       /* Load certificate chain */
+       if (SSL_CTX_use_certificate_chain_file(ctx->s, cert_path) != 1) {
+               msg_err("cannot load certificate chain from %s: %s",
+                               cert_path, ERR_error_string(ERR_get_error(), NULL));
+               rspamd_ssl_ctx_free(ctx);
+               return NULL;
+       }
+
+       /* Load private key */
+       if (SSL_CTX_use_PrivateKey_file(ctx->s, key_path, SSL_FILETYPE_PEM) != 1) {
+               msg_err("cannot load private key from %s: %s",
+                               key_path, ERR_error_string(ERR_get_error(), NULL));
+               rspamd_ssl_ctx_free(ctx);
+               return NULL;
+       }
+
+       /* Verify that the key matches the certificate */
+       if (SSL_CTX_check_private_key(ctx->s) != 1) {
+               msg_err("ssl private key does not match certificate: %s",
+                               ERR_error_string(ERR_get_error(), NULL));
+               rspamd_ssl_ctx_free(ctx);
+               return NULL;
+       }
+
+       /* No client certificate verification */
+       SSL_CTX_set_verify(ctx->s, SSL_VERIFY_NONE, NULL);
+
+       return ctx;
+}
 #if defined(RSPAMD_LEGACY_SSL_PROVIDER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
 #include <openssl/provider.h>
 #endif
index 802ba968656eff12ce05467c6ccc64b51c47a81a..0a042dbff61a0339ed26c7f1eb02faedeee8091b 100644 (file)
@@ -125,6 +125,7 @@ void rspamd_ssl_connection_free(struct rspamd_ssl_connection *conn);
 
 gpointer rspamd_init_ssl_ctx(void);
 gpointer rspamd_init_ssl_ctx_noverify(void);
+gpointer rspamd_init_ssl_ctx_server(const char *cert_path, const char *key_path);
 void rspamd_ssl_ctx_config(struct rspamd_config *cfg, gpointer ssl_ctx);
 void rspamd_ssl_ctx_free(gpointer ssl_ctx);
 void rspamd_openssl_maybe_init(struct rspamd_external_libs_ctx *ctx);
index 7c426a6cb75964ce2996fb9240321d38c8dc430a..c28ce366611d479886ac89cc761ebacfa9003efe 100644 (file)
@@ -2889,3 +2889,28 @@ rspamd_metrics_to_prometheus_string(const ucl_object_t *top)
        /* Must be finalized and freed by caller */
        return output;
 }
+
+gboolean
+rspamd_worker_is_ssl_socket(struct rspamd_worker *worker, int fd)
+{
+       GList *cur;
+       struct rspamd_worker_listen_socket *ls;
+
+       if (worker == NULL || worker->cf == NULL) {
+               return FALSE;
+       }
+
+       cur = worker->cf->listen_socks;
+
+       while (cur) {
+               ls = (struct rspamd_worker_listen_socket *) cur->data;
+
+               if (ls->fd == fd) {
+                       return ls->is_ssl;
+               }
+
+               cur = g_list_next(cur);
+       }
+
+       return FALSE;
+}
index de80b6a37bf3ada7d3da7f46811a0bba160558c9..1089c0a9cf1032ed1e41f7fa71659e2abdec21a0 100644 (file)
@@ -383,6 +383,14 @@ rspamd_metrics_add_double(rspamd_fstring_t **output,
  */
 rspamd_fstring_t *rspamd_metrics_to_prometheus_string(const ucl_object_t *top);
 
+/**
+ * Check if the given listen fd is an SSL socket for this worker
+ * @param worker
+ * @param fd listen fd from accept event
+ * @return TRUE if the socket is SSL
+ */
+gboolean rspamd_worker_is_ssl_socket(struct rspamd_worker *worker, int fd);
+
 #ifdef WITH_HYPERSCAN
 struct rspamd_control_command;
 
index fbadc59d8576c1477a3f32fa46afe60cfb499d45..7568b43f2a74e0d77d6c7c900751c055b2ce4c02 100644 (file)
@@ -708,6 +708,16 @@ spawn_workers(struct rspamd_main *rspamd_main, struct ev_loop *ev_base)
                                                                                 strerror(errno));
                                                }
                                                else {
+                                                       /* Propagate SSL flag to listen sockets */
+                                                       if (bcf->is_ssl) {
+                                                               GList *cur;
+
+                                                               for (cur = ls; cur != NULL; cur = g_list_next(cur)) {
+                                                                       struct rspamd_worker_listen_socket *cur_ls =
+                                                                               (struct rspamd_worker_listen_socket *) cur->data;
+                                                                       cur_ls->is_ssl = true;
+                                                               }
+                                                       }
                                                        g_hash_table_insert(listen_sockets, (gpointer) key, ls);
                                                        listen_ok = TRUE;
                                                }
index 4c266cb50bc92c692d97ead9a1ffc1dfd089fa59..02901a7eafaac2ed69d17709e1609b8219439d89 100644 (file)
@@ -241,6 +241,7 @@ struct rspamd_worker_listen_socket {
        int fd;
        enum rspamd_worker_socket_type type;
        bool is_systemd;
+       bool is_ssl;
 };
 
 typedef struct worker_s {
index 66529707569b8aa46564bd30f3962c613e5107dd..0f61124334dd26884dc29708884f830323977725 100644 (file)
@@ -27,6 +27,7 @@
 #include "libmime/message.h"
 #include "rspamd.h"
 #include "libserver/worker_util.h"
+#include "libserver/ssl_util.h"
 #include "worker_private.h"
 #include "lua/lua_common.h"
 #include "keypairs_cache.h"
@@ -180,6 +181,14 @@ struct rspamd_proxy_ctx {
        /* Default log tag type for worker */
        enum rspamd_proxy_log_tag_type log_tag_type;
        struct rspamd_main *srv;
+       /* Whether we use ssl for this server */
+       gboolean use_ssl;
+       /* SSL cert */
+       char *ssl_cert;
+       /* SSL private key */
+       char *ssl_key;
+       /* Server SSL context */
+       gpointer server_ssl_ctx;
 };
 
 enum rspamd_backend_flags {
@@ -1056,6 +1065,30 @@ init_rspamd_proxy(struct rspamd_config *cfg)
                                                                          G_STRUCT_OFFSET(struct rspamd_proxy_ctx, encrypted_only),
                                                                          0,
                                                                          "Allow only encrypted connections");
+       rspamd_rcl_register_worker_option(cfg,
+                                                                         type,
+                                                                         "ssl",
+                                                                         rspamd_rcl_parse_struct_boolean,
+                                                                         ctx,
+                                                                         G_STRUCT_OFFSET(struct rspamd_proxy_ctx, use_ssl),
+                                                                         0,
+                                                                         "Enable SSL for this worker");
+       rspamd_rcl_register_worker_option(cfg,
+                                                                         type,
+                                                                         "ssl_cert",
+                                                                         rspamd_rcl_parse_struct_string,
+                                                                         ctx,
+                                                                         G_STRUCT_OFFSET(struct rspamd_proxy_ctx, ssl_cert),
+                                                                         0,
+                                                                         "Path to SSL certificate chain file");
+       rspamd_rcl_register_worker_option(cfg,
+                                                                         type,
+                                                                         "ssl_key",
+                                                                         rspamd_rcl_parse_struct_string,
+                                                                         ctx,
+                                                                         G_STRUCT_OFFSET(struct rspamd_proxy_ctx, ssl_key),
+                                                                         0,
+                                                                         "Path to SSL private key file");
        rspamd_rcl_register_worker_option(cfg,
                                                                          type,
                                                                          "upstream",
@@ -3286,9 +3319,17 @@ proxy_accept_socket(EV_P_ ev_io *w, int revents)
                                                 rspamd_inet_address_to_string(addr),
                                                 rspamd_inet_address_get_port(addr));
 
-               rspamd_http_connection_read_message_shared(session->client_conn,
-                                                                                                  session,
-                                                                                                  session->ctx->timeout);
+               if (ctx->server_ssl_ctx && rspamd_worker_is_ssl_socket(worker, w->fd)) {
+                       rspamd_http_connection_accept_ssl_shared(session->client_conn,
+                                                                                                        ctx->server_ssl_ctx,
+                                                                                                        session,
+                                                                                                        session->ctx->timeout);
+               }
+               else {
+                       rspamd_http_connection_read_message_shared(session->client_conn,
+                                                                                                          session,
+                                                                                                          session->ctx->timeout);
+               }
        }
        else {
                msg_info_session("accepted milter connection from %s port %d",
@@ -3375,6 +3416,18 @@ start_rspamd_proxy(struct rspamd_worker *worker)
                                                                  (rspamd_mempool_destruct_t) rspamd_http_context_free,
                                                                  ctx->http_ctx);
 
+       if (ctx->use_ssl && ctx->ssl_cert && ctx->ssl_key) {
+               ctx->server_ssl_ctx = rspamd_init_ssl_ctx_server(ctx->ssl_cert, ctx->ssl_key);
+
+               if (ctx->server_ssl_ctx) {
+                       rspamd_ssl_ctx_config(ctx->cfg, ctx->server_ssl_ctx);
+                       msg_info("enabled SSL for proxy worker");
+               }
+               else {
+                       msg_err("failed to create SSL context for proxy worker");
+               }
+       }
+
        if (ctx->has_self_scan) {
                /* Additional initialisation needed */
                rspamd_worker_init_scanner(worker, ctx->event_loop, ctx->resolver,
index 2d46754d87cb7cc66783ec2e7ea3c57386dccd53..6dc9dd9741394eeae245d0ab1fa675259eaa1133 100644 (file)
@@ -30,6 +30,7 @@
 #include "libstat/stat_api.h"
 #include "libserver/worker_util.h"
 #include "libserver/rspamd_control.h"
+#include "libserver/ssl_util.h"
 #include "worker_private.h"
 #include "libserver/http/http_private.h"
 #include "libserver/cfg_file_private.h"
@@ -398,9 +399,17 @@ accept_socket(EV_P_ ev_io *w, int revents)
                rspamd_http_connection_set_key(session->http_conn, ctx->key);
        }
 
-       rspamd_http_connection_read_message(session->http_conn,
-                                                                               session,
-                                                                               ctx->timeout);
+       if (ctx->server_ssl_ctx && rspamd_worker_is_ssl_socket(worker, w->fd)) {
+               rspamd_http_connection_accept_ssl(session->http_conn,
+                                                                                 ctx->server_ssl_ctx,
+                                                                                 session,
+                                                                                 ctx->timeout);
+       }
+       else {
+               rspamd_http_connection_read_message(session->http_conn,
+                                                                                       session,
+                                                                                       ctx->timeout);
+       }
 }
 
 gpointer
@@ -478,6 +487,33 @@ init_worker(struct rspamd_config *cfg)
                                                                          0,
                                                                          "Encryption keypair");
 
+       rspamd_rcl_register_worker_option(cfg,
+                                                                         type,
+                                                                         "ssl",
+                                                                         rspamd_rcl_parse_struct_boolean,
+                                                                         ctx,
+                                                                         G_STRUCT_OFFSET(struct rspamd_worker_ctx, use_ssl),
+                                                                         0,
+                                                                         "Enable SSL for this worker");
+
+       rspamd_rcl_register_worker_option(cfg,
+                                                                         type,
+                                                                         "ssl_cert",
+                                                                         rspamd_rcl_parse_struct_string,
+                                                                         ctx,
+                                                                         G_STRUCT_OFFSET(struct rspamd_worker_ctx, ssl_cert),
+                                                                         0,
+                                                                         "Path to SSL certificate chain file");
+
+       rspamd_rcl_register_worker_option(cfg,
+                                                                         type,
+                                                                         "ssl_key",
+                                                                         rspamd_rcl_parse_struct_string,
+                                                                         ctx,
+                                                                         G_STRUCT_OFFSET(struct rspamd_worker_ctx, ssl_key),
+                                                                         0,
+                                                                         "Path to SSL private key file");
+
        return ctx;
 }
 
@@ -510,6 +546,19 @@ start_worker(struct rspamd_worker *worker)
        rspamd_mempool_add_destructor(ctx->cfg->cfg_pool,
                                                                  (rspamd_mempool_destruct_t) rspamd_http_context_free,
                                                                  ctx->http_ctx);
+
+       if (ctx->use_ssl && ctx->ssl_cert && ctx->ssl_key) {
+               ctx->server_ssl_ctx = rspamd_init_ssl_ctx_server(ctx->ssl_cert, ctx->ssl_key);
+
+               if (ctx->server_ssl_ctx) {
+                       rspamd_ssl_ctx_config(ctx->cfg, ctx->server_ssl_ctx);
+                       msg_info_ctx("enabled SSL for normal worker");
+               }
+               else {
+                       msg_err_ctx("failed to create SSL context for normal worker");
+               }
+       }
+
        rspamd_worker_init_scanner(worker, ctx->event_loop, ctx->resolver,
                                                           &ctx->lang_det);
 
index 6fb40e9704069ab6d38cc3043b9e133ee6dd8b9e..19f6cd7b319a7551d7bae90a17ce2fec1b7f5d9f 100644 (file)
@@ -45,6 +45,8 @@ struct rspamd_worker_ctx {
        gboolean is_mime;
        /* Allow encrypted requests only using network */
        gboolean encrypted_only;
+       /* Whether we use ssl for this server */
+       gboolean use_ssl;
        /* Limit of tasks */
        uint32_t max_tasks;
        /* Maximum time for task processing */
@@ -55,6 +57,12 @@ struct rspamd_worker_ctx {
        struct rspamd_http_context *http_ctx;
        /* Language detector */
        struct rspamd_lang_detector *lang_det;
+       /* SSL cert */
+       char *ssl_cert;
+       /* SSL private key */
+       char *ssl_key;
+       /* Server SSL context */
+       gpointer server_ssl_ctx;
 };
 
 /*