Skip to content

Commit

Permalink
nginx: Allow http and/or mail servers to accept the PROXY protocol
Browse files Browse the repository at this point in the history
See Mailu#2300 for the initial proposal
  • Loading branch information
OdyX committed Mar 26, 2023
1 parent 6f3a01e commit d05b7e6
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 20 deletions.
46 changes: 26 additions & 20 deletions core/nginx/conf/nginx.conf
Expand Up @@ -23,6 +23,8 @@ http {

{% if REAL_IP_HEADER %}
real_ip_header {{ REAL_IP_HEADER }};
{% elif PROXY_PROTOCOL %}
real_ip_header proxy_protocol;
{% endif %}

{% if REAL_IP_FROM %}{% for from_ip in REAL_IP_FROM.split(',') %}
Expand Down Expand Up @@ -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/ {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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'] %}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -416,19 +422,19 @@ 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;
auth_http_header Auth-Port 465;
}

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;
Expand All @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions docs/configuration.rst
Expand Up @@ -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
------------------

Expand Down
1 change: 1 addition & 0 deletions towncrier/newsfragments/2717.feature
@@ -0,0 +1 @@
Allow inbound to http and mail ports to accept the PROXY protocol

0 comments on commit d05b7e6

Please sign in to comment.