Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jkullick/bbb36828a1f413abd6b9d6431bafa54b to your computer and use it in GitHub Desktop.
Save jkullick/bbb36828a1f413abd6b9d6431bafa54b to your computer and use it in GitHub Desktop.

Revisions

  1. jkullick revised this gist Jan 17, 2017. 1 changed file with 2 additions and 1 deletion.
    Original file line number Diff line number Diff line change
    @@ -38,7 +38,8 @@
    _dmarc.$DOMAIN. 1800 IN TXT v=DMARC1; p=none
    ```

    3. Set Mailname:
    ### Misc

    ```bash
    cat > /etc/mailname << EOF
    ${FQDN}
  2. jkullick revised this gist Jan 17, 2017. 1 changed file with 31 additions and 14 deletions.
    45 changes: 31 additions & 14 deletions secure-mailserver-postfix-dovecot-letsencrypt-debian-jessie.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,7 @@
    1. Set parameters:
    ## Prerequirements

    ### Config Options

    ```bash
    export FQDN="mail.example.org"
    export DOMAIN="example.org"
    @@ -7,7 +10,7 @@
    export A_RECORD=$(curl -sSL https://icanhazip.com)
    ```

    2. Set DNS records:
    ### DNS

    With *Digital Ocean* API:

    @@ -42,26 +45,30 @@
    EOF
    ```
    4. Install packages:
    ### Install packages
    ```bash
    echo "deb http://ftp.debian.org/debian jessie-backports main" >> /etc/apt/sources.list
    apt-get update
    apt-get install -y postfix dovecot-core dovecot-imapd amavisd-new postgrey opendkim opendkim-tools
    apt-get install -y certbot -t jessie-backports
    ```
    5. Generate SSL certificate with the *Let's Encrypt* client:
    ### SSL / Let's Encrypt
    Generate SSL certificate with the *Let's Encrypt* client:
    ```bash
    certbot certonly --register-unsafely-without-email --agree-tos --standalone -d "${FQDN}"
    ```
    6. Generate *Diffie Hellman* Keys:
    Generate *Diffie Hellman* Keys:
    ```bash
    openssl gendh -out /etc/postfix/dh_512.pem -2 512
    openssl gendh -out /etc/postfix/dh_2048.pem -2 2048
    ```
    7. Postfix config:
    ## Postfix
    ```bash
    cat > /etc/postfix/main.cf << EOF
    alias_maps = hash:/etc/aliases
    @@ -118,7 +125,8 @@
    EOF
    ```
    8. Dovecot config:
    ## Dovecot
    ```bash
    cat > /etc/dovecot/dovecot.conf << EOF
    listen = *
    @@ -177,19 +185,24 @@
    EOF
    ```
    9. Amavis config:
    ## Anti-Spam Measures
    ### Amavis
    ```bash
    cat >> /etc/amavis/conf.d/20-debian_defaults << EOF
    \$inet_socket_bind = '127.0.0.1';
    EOF
    ```
    10. Postgrey config:
    ### Postgrey
    ```bash
    sed -i 's/inet=10023/inet=10023 --delay=30/' /etc/default/postgrey
    ```
    11. OpenDKIM config:
    ### OpenDKIM
    ```bash
    cat >> /etc/opendkim.conf << EOF
    AutoRestart Yes
    @@ -239,7 +252,7 @@
    EOF
    ```
    12. Set DKIM DNS record:
    ### DNS Records
    With *Digital Ocean* API:
    ```bash
    @@ -254,13 +267,17 @@
    cat /etc/opendkim/keys/${DOMAIN}/mail.txt
    ```
    13. Add User:
    ## Mailbox Configs
    ### New User
    ```bash
    adduser --disabled-password --gecos "" ${MAILBOX}
    passwd ${MAILBOX}
    ```
    14. Add alias:
    ### New Alias
    ```bash
    cat >> /etc/aliases << EOF
    root: ${MAILBOX}
    @@ -269,7 +286,7 @@
    newaliases
    ```
    15. Reboot
    ### Reboot
    ---
    - [Source](https://thomas-leister.de/postfix-amavis-spamfilter-spamassassin-sieve/)
  3. jkullick revised this gist Dec 29, 2016. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions secure-mailserver-postfix-dovecot-letsencrypt-debian-jessie.md
    Original file line number Diff line number Diff line change
    @@ -271,5 +271,11 @@
    15. Reboot
    [Source](https://thomas-leister.de/postfix-amavis-spamfilter-spamassassin-sieve/), [Source](https://arnowelzel.de/wp/greylisting-zur-spamvermeidung]), [Source](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy), [Source](https://www.heinlein-support.de/blog/security/perfect-forward-secrecy-pfs-fur-postfix-und-dovecot/), [Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-postfix-e-mail-server-with-dovecot)
    [Source](https://blog.stefan-oltmann.de/postfix-und-dovecot-unter-debian/), [Source](http://www.cyberciti.biz/faq/postfix-mail-for-domaincom-loops-back-to-myself-error-and-solution/)
    ---
    - [Source](https://thomas-leister.de/postfix-amavis-spamfilter-spamassassin-sieve/)
    - [Source](https://arnowelzel.de/wp/greylisting-zur-spamvermeidung])
    - [Source](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy)
    - [Source](https://www.heinlein-support.de/blog/security/perfect-forward-secrecy-pfs-fur-postfix-und-dovecot/)
    - [Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-postfix-e-mail-server-with-dovecot)
    - [Source](https://blog.stefan-oltmann.de/postfix-und-dovecot-unter-debian/)
    - [Source](http://www.cyberciti.biz/faq/postfix-mail-for-domaincom-loops-back-to-myself-error-and-solution/)
  4. jkullick renamed this gist Aug 30, 2016. 1 changed file with 0 additions and 0 deletions.
  5. jkullick revised this gist Aug 30, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions secure-mailserver-postfix-dovecot-letsencrypt.md
    Original file line number Diff line number Diff line change
    @@ -84,6 +84,7 @@
    smtp_tls_key_file = /etc/letsencrypt/live/${FQDN}/privkey.pem
    smtp_tls_security_level = may
    smtp_use_tls = yes
    smtpd_banner = $myhostname ESMTP
    smtpd_milters = inet:localhost:12301
    smtpd_recipient_restrictions = permit_mynetworks, reject_invalid_hostname, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, permit_sasl_authenticated, reject_unauth_destination, check_policy_service inet:[127.0.0.1]:10023
    smtpd_sasl_auth_enable = yes
  6. jkullick revised this gist Aug 30, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion secure-mailserver-postfix-dovecot-letsencrypt.md
    Original file line number Diff line number Diff line change
    @@ -270,5 +270,5 @@
    15. Reboot
    [Source](https://thomas-leister.de/postfix-amavis-spamfilter-spamassassin-sieve/), [https://arnowelzel.de/wp/greylisting-zur-spamvermeidung](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy), [Source](https://www.heinlein-support.de/blog/security/perfect-forward-secrecy-pfs-fur-postfix-und-dovecot/), [Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-postfix-e-mail-server-with-dovecot)
    [Source](https://thomas-leister.de/postfix-amavis-spamfilter-spamassassin-sieve/), [Source](https://arnowelzel.de/wp/greylisting-zur-spamvermeidung]), [Source](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy), [Source](https://www.heinlein-support.de/blog/security/perfect-forward-secrecy-pfs-fur-postfix-und-dovecot/), [Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-postfix-e-mail-server-with-dovecot)
    [Source](https://blog.stefan-oltmann.de/postfix-und-dovecot-unter-debian/), [Source](http://www.cyberciti.biz/faq/postfix-mail-for-domaincom-loops-back-to-myself-error-and-solution/)
  7. jkullick revised this gist Aug 30, 2016. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions secure-mailserver-postfix-dovecot-letsencrypt.md
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,7 @@
    ```

    2. Set DNS records:

    With *Digital Ocean* API:

    ```bash
    @@ -238,6 +239,7 @@
    ```
    12. Set DKIM DNS record:
    With *Digital Ocean* API:
    ```bash
    export DKIM_RECORD=$(cat /etc/opendkim/keys/${DOMAIN}/mail.txt | awk -F'"' '{print $2}' | tr -d '\n')
  8. jkullick revised this gist Aug 30, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion secure-mailserver-postfix-dovecot-letsencrypt.md
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@
    _dmarc.$DOMAIN. 1800 IN TXT v=DMARC1; p=none
    ```

    3. Set */etc/mailname*:
    3. Set Mailname:
    ```bash
    cat > /etc/mailname << EOF
    ${FQDN}
  9. jkullick revised this gist Aug 30, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion secure-mailserver-postfix-dovecot-letsencrypt.md
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@
    ```bash
    export DO_API_KEY="abc1234567890..."

    # A racord
    # A record
    curl -X POST -H "Content-Type: application/json" -d "{\"type\":\"A\",\"name\":\"mail\",\"data\":\"${A_RECORD}\",\"priority\":null,\"port\":null,\"weight\":null}" -H "Authorization: Bearer ${DO_API_KEY}" "https://api.digitalocean.com/v2/domains/${DOMAIN}/records"

    # MX record
  10. jkullick created this gist Aug 30, 2016.
    272 changes: 272 additions & 0 deletions secure-mailserver-postfix-dovecot-letsencrypt.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,272 @@
    1. Set parameters:
    ```bash
    export FQDN="mail.example.org"
    export DOMAIN="example.org"
    export MAILBOX="user"
    export DEBIAN_FRONTEND="noninteractive"
    export A_RECORD=$(curl -sSL https://icanhazip.com)
    ```

    2. Set DNS records:
    With *Digital Ocean* API:

    ```bash
    export DO_API_KEY="abc1234567890..."

    # A racord
    curl -X POST -H "Content-Type: application/json" -d "{\"type\":\"A\",\"name\":\"mail\",\"data\":\"${A_RECORD}\",\"priority\":null,\"port\":null,\"weight\":null}" -H "Authorization: Bearer ${DO_API_KEY}" "https://api.digitalocean.com/v2/domains/${DOMAIN}/records"

    # MX record
    curl -X POST -H "Content-Type: application/json" -d "{\"type\":\"MX\",\"name\":\"mail\",\"data\":\"${FQDN}.\",\"priority\":10,\"port\":null,\"weight\":null}" -H "Authorization: Bearer ${DO_API_KEY}" "https://api.digitalocean.com/v2/domains/${DOMAIN}/records"

    # SPF record
    curl -X POST -H "Content-Type: application/json" -d "{\"type\":\"TXT\",\"name\":\"@\",\"data\":\"v=spf1 mx ~all\",\"priority\":null,\"port\":null,\"weight\":null}" -H "Authorization: Bearer ${DO_API_KEY}" "https://api.digitalocean.com/v2/domains/${DOMAIN}/records"

    # DMARC record
    curl -X POST -H "Content-Type: application/json" -d "{\"type\":\"TXT\",\"name\":\"_dmarc\",\"data\":\"v=DMARC1; p=none\",\"priority\":null,\"port\":null,\"weight\":null}" -H "Authorization: Bearer ${DO_API_KEY}" "https://api.digitalocean.com/v2/domains/${DOMAIN}/records"
    ```

    Without *DO* API:
    ```
    $FQDN. 1800 IN A $A_RECORD
    $DOMAIN. 1800 IN MX 10 $FQDN
    $DOMAIN. 1800 IN TXT v=spf1 mx ~all
    _dmarc.$DOMAIN. 1800 IN TXT v=DMARC1; p=none
    ```

    3. Set */etc/mailname*:
    ```bash
    cat > /etc/mailname << EOF
    ${FQDN}
    EOF
    ```
    4. Install packages:
    ```bash
    echo "deb http://ftp.debian.org/debian jessie-backports main" >> /etc/apt/sources.list
    apt-get update
    apt-get install -y postfix dovecot-core dovecot-imapd amavisd-new postgrey opendkim opendkim-tools
    apt-get install -y certbot -t jessie-backports
    ```
    5. Generate SSL certificate with the *Let's Encrypt* client:
    ```bash
    certbot certonly --register-unsafely-without-email --agree-tos --standalone -d "${FQDN}"
    ```
    6. Generate *Diffie Hellman* Keys:
    ```bash
    openssl gendh -out /etc/postfix/dh_512.pem -2 512
    openssl gendh -out /etc/postfix/dh_2048.pem -2 2048
    ```
    7. Postfix config:
    ```bash
    cat > /etc/postfix/main.cf << EOF
    alias_maps = hash:/etc/aliases
    config_directory = /etc/postfix
    content_filter = amavis:[127.0.0.1]:10024
    home_mailbox = Maildir/
    inet_interfaces = all
    inet_protocols = ipv4
    mailbox_size_limit = 0
    milter_default_action = accept
    milter_protocol = 2
    mydestination = ${FQDN}, ${FQDN}, localhost, localhost.localdomain
    myhostname = ${FQDN}
    mynetworks = 127.0.0.0/8
    myorigin = /etc/mailname
    non_smtpd_milters = inet:localhost:12301
    recipient_delimiter = +
    smtp_tls_CApath = /etc/ssl/certs
    smtp_tls_cert_file = /etc/letsencrypt/live/${FQDN}/fullchain.pem
    smtp_tls_key_file = /etc/letsencrypt/live/${FQDN}/privkey.pem
    smtp_tls_security_level = may
    smtp_use_tls = yes
    smtpd_milters = inet:localhost:12301
    smtpd_recipient_restrictions = permit_mynetworks, reject_invalid_hostname, reject_non_fqdn_hostname, reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, permit_sasl_authenticated, reject_unauth_destination, check_policy_service inet:[127.0.0.1]:10023
    smtpd_sasl_auth_enable = yes
    smtpd_sasl_path = private/auth
    smtpd_sasl_security_options = noanonymous
    smtpd_sasl_type = dovecot
    smtpd_tls_CApath = /etc/ssl/certs
    smtpd_tls_cert_file = /etc/letsencrypt/live/${FQDN}/fullchain.pem
    smtpd_tls_dh1024_param_file = /etc/postfix/dh_2048.pem
    smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
    smtpd_tls_eecdh_grade = strong
    smtpd_tls_key_file = /etc/letsencrypt/live/${FQDN}/privkey.pem
    smtpd_tls_mandatory_ciphers = medium
    smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
    smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
    smtpd_tls_security_level = may
    tls_medium_cipherlist = AES128+EECDH:AES128+EDH
    tls_preempt_cipherlist = yes
    EOF
    ```
    ```bash
    cat >> /etc/postfix/master.cf << EOF
    submission inet n - n - - smtpd
    -o smtpd_tls_security_level=encrypt
    amavis unix - - - - 2 smtp
    -o smtp_send_xforward_command=yes
    -o smtp_tls_security_level=none
    127.0.0.1:10025 inet n - - - - smtpd
    -o content_filter=
    EOF
    ```
    8. Dovecot config:
    ```bash
    cat > /etc/dovecot/dovecot.conf << EOF
    listen = *
    mail_location = maildir:~/Maildir
    namespace inbox {
    inbox = yes
    location =
    mailbox Drafts {
    auto = no
    special_use = \Drafts
    }
    mailbox Sent {
    auto = subscribe
    special_use = \Sent
    }
    mailbox Spam {
    auto = create
    special_use = \Junk
    }
    mailbox Trash {
    auto = no
    special_use = \Trash
    }
    prefix =
    }
    passdb {
    args = %s
    driver = pam
    }
    protocols = imap
    service auth {
    unix_listener /var/spool/postfix/private/auth {
    group = postfix
    mode = 0660
    user = postfix
    }
    }
    service imap-login {
    inet_listener imap {
    port = 0
    }
    inet_listener imaps {
    port = 993
    }
    }
    ssl = required
    ssl_cert = </etc/letsencrypt/live/${FQDN}/fullchain.pem
    ssl_cipher_list = AES128+EECDH:AES128+EDH
    ssl_dh_parameters_length = 4096
    ssl_key = </etc/letsencrypt/live/${FQDN}/privkey.pem
    ssl_prefer_server_ciphers = yes
    ssl_protocols = !SSLv2 !SSLv3
    userdb {
    driver = passwd
    }
    EOF
    ```
    9. Amavis config:
    ```bash
    cat >> /etc/amavis/conf.d/20-debian_defaults << EOF
    \$inet_socket_bind = '127.0.0.1';
    EOF
    ```
    10. Postgrey config:
    ```bash
    sed -i 's/inet=10023/inet=10023 --delay=30/' /etc/default/postgrey
    ```
    11. OpenDKIM config:
    ```bash
    cat >> /etc/opendkim.conf << EOF
    AutoRestart Yes
    AutoRestartRate 10/1h
    UMask 002
    Syslog yes
    SyslogSuccess Yes
    LogWhy Yes
    Canonicalization relaxed/simple
    ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
    InternalHosts refile:/etc/opendkim/TrustedHosts
    KeyTable refile:/etc/opendkim/KeyTable
    SigningTable refile:/etc/opendkim/SigningTable
    Mode sv
    PidFile /var/run/opendkim/opendkim.pid
    SignatureAlgorithm rsa-sha256
    UserID opendkim:opendkim
    Socket inet:12301@localhost
    EOF
    ```
    ```bash
    (mkdir -p /etc/opendkim/keys/${DOMAIN} && cd /etc/opendkim/keys/${DOMAIN} && opendkim-genkey -s mail -d ${DOMAIN} && chown opendkim:opendkim /etc/opendkim/keys/${DOMAIN}/mail.private )
    ```
    ```bash
    cat > /etc/opendkim/TrustedHosts << EOF
    127.0.0.1
    localhost
    EOF
    ```
    ```bash
    cat > /etc/opendkim/KeyTable << EOF
    mail._domainkey.${DOMAIN} ${DOMAIN}:mail:/etc/opendkim/keys/${DOMAIN}/mail.private
    EOF
    ```
    ```bash
    cat > /etc/opendkim/SigningTable << EOF
    *@${DOMAIN} mail._domainkey.${DOMAIN}
    EOF
    ```
    12. Set DKIM DNS record:
    With *Digital Ocean* API:
    ```bash
    export DKIM_RECORD=$(cat /etc/opendkim/keys/${DOMAIN}/mail.txt | awk -F'"' '{print $2}' | tr -d '\n')
    # DKIM records
    curl -X POST -H "Content-Type: application/json" -d "{\"type\":\"TXT\",\"name\":\"mail._domainkey\",\"data\":\"${DKIM_RECORD}\",\"priority\":null,\"port\":null,\"weight\":null}" -H "Authorization: Bearer ${DO_API_KEY}" "https://api.digitalocean.com/v2/domains/${DOMAIN}/records"
    ```
    Without *DO* API:
    ```bash
    cat /etc/opendkim/keys/${DOMAIN}/mail.txt
    ```
    13. Add User:
    ```bash
    adduser --disabled-password --gecos "" ${MAILBOX}
    passwd ${MAILBOX}
    ```
    14. Add alias:
    ```bash
    cat >> /etc/aliases << EOF
    root: ${MAILBOX}
    EOF
    newaliases
    ```
    15. Reboot
    [Source](https://thomas-leister.de/postfix-amavis-spamfilter-spamassassin-sieve/), [https://arnowelzel.de/wp/greylisting-zur-spamvermeidung](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy), [Source](https://www.heinlein-support.de/blog/security/perfect-forward-secrecy-pfs-fur-postfix-und-dovecot/), [Source](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-postfix-e-mail-server-with-dovecot)
    [Source](https://blog.stefan-oltmann.de/postfix-und-dovecot-unter-debian/), [Source](http://www.cyberciti.biz/faq/postfix-mail-for-domaincom-loops-back-to-myself-error-and-solution/)