From d9ed3cd179a434fa928d6516ec9df0fd3b84efab Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Sat, 25 Mar 2023 16:23:05 +0100 Subject: [PATCH] nginx: Allow http and/or mail servers to accept the PROXY protocol See #2300 for the initial proposal --- core/nginx/conf/nginx.conf | 46 ++++++++++++++++------------ docs/configuration.rst | 8 +++++ towncrier/newsfragments/2717.feature | 1 + 3 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 towncrier/newsfragments/2717.feature diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index e0d4fd49..4b560f9c 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -23,6 +23,8 @@ http { {% if REAL_IP_HEADER %} real_ip_header {{ REAL_IP_HEADER }}; + {% elif PROXY_PROTOCOL in ['all', 'http'] %} + real_ip_header proxy_protocol; {% endif %} {% if REAL_IP_FROM %}{% for from_ip in REAL_IP_FROM.split(',') %} @@ -58,9 +60,9 @@ http { # server { # Listen over HTTP - listen 80; + listen 80{% if PROXY_PROTOCOL in ['all', 'http'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:80; + listen [::]:80{% if PROXY_PROTOCOL in ['all', 'http'] %} proxy_protocol{% endif %}; {% endif %} {% if TLS_FLAVOR == 'letsencrypt' %} location ^~ /.well-known/acme-challenge/ { @@ -92,17 +94,17 @@ http { # Listen on HTTP only in kubernetes or behind reverse proxy {% if KUBERNETES_INGRESS or TLS_FLAVOR in [ 'mail-letsencrypt', 'notls', 'mail' ] %} - listen 80; + listen 80{% if PROXY_PROTOCOL in ['all', 'http'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:80; + listen [::]:80{% if PROXY_PROTOCOL in ['all', 'http'] %} proxy_protocol{% endif %}; {% endif %} {% endif %} # Only enable HTTPS if TLS is enabled with no error and not on kubernetes {% if not KUBERNETES_INGRESS and TLS and not TLS_ERROR %} - listen 443 ssl http2; + listen 443 ssl http2{% if PROXY_PROTOCOL in ['all', 'http'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:443 ssl http2; + listen [::]:443 ssl http2{% if PROXY_PROTOCOL in ['all', 'http'] %} proxy_protocol{% endif %}; {% endif %} include /etc/nginx/tls.conf; @@ -323,6 +325,10 @@ mail { ssl_session_cache shared:SSLMAIL:3m; {% endif %} + {% if PROXY_PROTOCOL and REAL_IP_FROM %}{% for from_ip in REAL_IP_FROM.split(',') %} + set_real_ip_from {{ from_ip }}; + {% endfor %}{% endif %} + # Advertise real capabilities of backends (postfix/dovecot) smtp_capabilities PIPELINING "SIZE {{ MESSAGE_SIZE_LIMIT }}" ETRN ENHANCEDSTATUSCODES 8BITMIME DSN; pop3_capabilities TOP UIDL RESP-CODES PIPELINING AUTH-RESP-CODE USER; @@ -348,9 +354,9 @@ mail { # SMTP is always enabled, to avoid losing emails when TLS is failing server { - listen 25; + listen 25{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:25; + listen [::]:25{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} {% if TLS and not TLS_ERROR %} {% if TLS_FLAVOR in ['letsencrypt','mail-letsencrypt'] %} @@ -372,9 +378,9 @@ mail { # All other protocols are disabled if TLS is failing {% if not TLS_ERROR %} server { - listen 143; + listen 143{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:143; + listen [::]:143{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} {% if TLS %} starttls only; @@ -387,9 +393,9 @@ mail { } server { - listen 110; + listen 110{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:110; + listen [::]:110{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} {% if TLS %} starttls only; @@ -402,9 +408,9 @@ mail { } server { - listen 587; + listen 587{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:587; + listen [::]:587{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} {% if TLS %} starttls only; @@ -416,9 +422,9 @@ mail { {% if TLS %} server { - listen 465 ssl; + listen 465 ssl{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:465 ssl; + listen [::]:465 ssl{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} protocol smtp; smtp_auth plain login; @@ -426,9 +432,9 @@ mail { } server { - listen 993 ssl; + listen 993 ssl{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:993 ssl; + listen [::]:993 ssl{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} protocol imap; imap_auth plain; @@ -438,9 +444,9 @@ mail { } server { - listen 995 ssl; + listen 995 ssl{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% if SUBNET6 %} - listen [::]:995 ssl; + listen [::]:995 ssl{% if PROXY_PROTOCOL in ['all', 'mail'] %} proxy_protocol{% endif %}; {% endif %} protocol pop3; pop3_auth plain; diff --git a/docs/configuration.rst b/docs/configuration.rst index efe67326..4d60a64a 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -253,6 +253,14 @@ The ``TZ`` sets the timezone Mailu will use. The timezone naming convention usua .. _`TZ database name`: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +The ``PROXY_PROTOCOL`` (default: unset) allows the the front container to receive TCP and HTTP connections with +the PROXY protocol. It can be set to: +* ``http`` to accept the ``PROXY`` protocol on nginx's HTTP proxy ports +* ``mail`` to accept the ``PROXY`` protocol on nginx's mail proxy ports +* ``all`` to accept the ``PROXY`` protocol on all nginx's HTTP and mail proxy ports + +This requires to have a valid ``REAL_IP_FROM``. + Antivirus settings ------------------ diff --git a/towncrier/newsfragments/2717.feature b/towncrier/newsfragments/2717.feature new file mode 100644 index 00000000..82086fc1 --- /dev/null +++ b/towncrier/newsfragments/2717.feature @@ -0,0 +1 @@ +Allow inbound to http and mail ports to accept the PROXY protocol