Skip to content

Instantly share code, notes, and snippets.

@h0tw1r3
Created September 4, 2025 20:00
Show Gist options
  • Select an option

  • Save h0tw1r3/55ef442e469443a9c45c63e86a1a5ec0 to your computer and use it in GitHub Desktop.

Select an option

Save h0tw1r3/55ef442e469443a9c45c63e86a1a5ec0 to your computer and use it in GitHub Desktop.

Revisions

  1. h0tw1r3 revised this gist Sep 4, 2025. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion perl-lib-auth.pm
    Original file line number Diff line number Diff line change
    @@ -34,4 +34,9 @@ sub handler {
    $r->header_out("Auth-Port", $ENV{RELAY_PORT});

    return OK;
    }
    }

    return DECLINED;
    }

    1;
  2. h0tw1r3 created this gist Sep 4, 2025.
    65 changes: 65 additions & 0 deletions nginx.conf
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    user nginx;
    worker_processes auto;
    error_log /var/log/nginx/error.log info;
    pid /run/nginx.pid;

    include /usr/share/nginx/modules/*.conf;

    env RELAY_HOST;
    env RELAY_PORT;

    events {
    worker_connections 1024;
    }

    http {
    access_log /var/log/nginx/access.log;
    log_not_found off;

    perl_modules /etc/nginx/perl/lib;
    perl_require auth.pm;

    server {
    listen 80 default_server;
    listen [::]:80 ipv6only=on default_server;

    server_name _;

    root /dev/null; # No static content served

    location /auth {
    perl auth::handler;
    }
    }
    }

    mail {
    server_name mail.example.com;
    auth_http 127.0.0.1:80/auth;

    smtp_capabilities PIPELINING 8BITMIME ENHANCEDSTATUSCODES "SIZE 10240000" SMTPUTF8 CHUNKING ETRN VRFY;
    xclient on;

    proxy_pass_error_message on;

    ssl_trusted_certificate /etc/nginx/ssl/ca.crt;
    ssl_certificate /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.nopass.key;

    server {
    listen 25;
    listen 465 ssl;

    protocol smtp;
    smtp_auth none;
    starttls on;
    }

    server {
    listen 587;

    protocol smtp;
    smtp_auth none;
    starttls only;
    }
    }
    37 changes: 37 additions & 0 deletions perl-lib-auth.pm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    package auth;

    use strict;
    use warnings;

    use Socket;
    use nginx;

    sub handler {
    my $r = shift;

    # Require STARTTLS if Auth-Method is "none"
    # nginx handles ensuring TLS for other methods (e.g. "plain", "login", "cram-md5")
    if ($r->header_in("Auth-Method") eq "none" && $r->header_in("Auth-SSL") || "" ne "on") {
    my $max_attempts = 3;
    my $attempt = ($r->header_in("Auth-Login-Attempt") || 0) + 0;

    if ($attempt > $max_attempts) {
    $r->header_out("Auth-Status", "Too many errors");
    $r->header_out("Auth-Error-Code", "503");
    } else {
    $r->header_out("Auth-Status", "Must issue a STARTTLS command first");
    $r->header_out("Auth-Error-Code", "530 5.7.0");
    $r->header_out("Auth-Wait", "1");
    }

    return DECLINED;
    }

    if (exists $ENV{RELAY_HOST} && $ENV{RELAY_PORT}) {
    my $address = inet_ntoa(inet_aton($ENV{RELAY_HOST}));
    $r->header_out("Auth-Status", "OK");
    $r->header_out("Auth-Server", $address);
    $r->header_out("Auth-Port", $ENV{RELAY_PORT});

    return OK;
    }