diff --git a/roles/pmg/defaults/main.yml b/roles/pmg/defaults/main.yml index 9025ca9..0e74a03 100644 --- a/roles/pmg/defaults/main.yml +++ b/roles/pmg/defaults/main.yml @@ -5,8 +5,6 @@ pmg_api_src_ip: "{{ trusted_ip | default(['127.0.0.1']) }}" pmg_smtp_ext_ports: - 25 - - 587 - - 465 pmg_smtp_ext_src_ip: - 0.0.0.0/0 @@ -14,23 +12,6 @@ pmg_smtp_int_ports: - 26 pmg_smtp_int_src_ip: "{{ trusted_ip | default(['127.0.0.1']) }}" -pmg_ldap_auth: "{{ (ad_auth | default(False) or ldap_auth | default(False)) | ternary(True,False) }}" -pmg_ldap_servers: "{{ ad_auth | default(False) | ternary(['ldap://' + ad_realm | default(samba_realm) | default(ansible_domain) | lower],ldap_auth | default(False) | ternary([ldap_uri],['ldap://ldap.domain.tld'])) }}" -pmg_ldap_starttls: True -pmg_ldap_search_base: "{{ ad_auth | default(False) | ternary((ad_ldap_user_search_base is defined) | ternary(ad_ldap_user_search_base,'DC=' + ad_realm | default(samba_realm) | default(ansible_domain) | regex_replace('\\.',',DC=')), ldap_auth | ternary(ldap_base,'dc=domain,dc=tld')) }}" -pmg_ldap_filter: "{{ ad_auth | default(False) | ternary('(|(userPrincipalName=%u@' + ad_realm | default(samba_realm) | default(ansible_domain) | lower + ')(sAMAccountName=%u))','(uid=%u)') }}" -# pmg_ldap_bind_dn: -# pmg_ldap_bind_pass: - -pmg_check_dkim: True -pmg_check_dmarc: True -pmg_dmarc_reject: True -pmg_dmarc_report: True -pmg_dmarc_db_server: "{{ mysql_server | default('localhost') }}" -pmg_dmarc_db_name: opendmarc -pmg_dmarc_db_user: opendmarc -# pmg_dmarc_db_pass -pmg_dmarc_report_org: "{{ ansible_domain }}" pmg_dkim_sign: [] # pmg_dkim_sign: # - domain: '*' @@ -60,12 +41,3 @@ pmg_bays_imap_attachment: False # unless allowed by openphish. See https://openphish.com/feed.txt pmg_use_openphish: False -pmg_sa_rules_base: - - name: KAM_MARK - score: 1.0 - - name: DKIM_INVALID # Default is 0.1 - score: 1.0 - - name: USER_IN_DEF_SPF_WL # Default is -7.5 ! - score: -1.0 -pmg_sa_rules_extra: [] -pmg_sa_rules: "{{ pmg_sa_rules_base + pmg_sa_rules_extra }}" diff --git a/roles/pmg/meta/main.yml b/roles/pmg/meta/main.yml new file mode 100644 index 0000000..dc58dfa --- /dev/null +++ b/roles/pmg/meta/main.yml @@ -0,0 +1,4 @@ +--- + +dependencies: + - role: mkdir diff --git a/roles/pmg/tasks/cleanup.yml b/roles/pmg/tasks/cleanup.yml new file mode 100644 index 0000000..3a805a6 --- /dev/null +++ b/roles/pmg/tasks/cleanup.yml @@ -0,0 +1,24 @@ +--- + +- name: Remove tmp and obsolete files + file: path={{ item }} state=absent + loop: + - /etc/opendkim/verifier.conf + - /etc/systemd/system/opendmarc.service + - /etc/systemd/system/opendkim-verifier.service + - /etc/opendmarc.conf + - /etc/opendmarc.dbpass + - /usr/local/bin/dmarc_reports + - /etc/cron.d/opendmarc + - /etc/pmg/templates/main.cf.in + - /etc/mail/spamassassin/scores.cf + tags: pmg + +- name: Disable unused services + service: name={{ item }} state=stopped disabled=True + loop: + - opendmarc + - opendkim-verifier + - saslauthd + failed_when: False + tags: pmg diff --git a/roles/pmg/tasks/main.yml b/roles/pmg/tasks/main.yml index eb969d4..e0b8084 100644 --- a/roles/pmg/tasks/main.yml +++ b/roles/pmg/tasks/main.yml @@ -2,24 +2,12 @@ - set_fact: pmg_smtpd_milters_int={{ [] }} tags: pmg -- set_fact: pmg_smtpd_milters_ext={{ [] }} - tags: pmg - name: Enable dkim signing for outgoing messages set_fact: pmg_smtpd_milters_int={{ pmg_smtpd_milters_int + ['unix:/var/run/opendkim/signer.sock'] }} when: pmg_dkim_sign | length > 0 tags: pmg -- name: Enable dkim checks for incoming messages - set_fact: pmg_smtpd_milters_ext={{ pmg_smtpd_milters_ext + ['unix:/var/run/opendkim/verifier.sock'] }} - when: pmg_check_dkim == True - tags: pmg - -- name: Enable dmarc checks for incoming messages - set_fact: pmg_smtpd_milters_ext={{ pmg_smtpd_milters_ext + ['unix:/var/run/opendmarc/opendmarc.sock'] }} - when: pmg_check_dkim and pmg_check_dmarc - tags: pmg - - name: Add PMG repository APT key apt_key: url: http://download.proxmox.com/debian/proxmox-ve-release-6.x.gpg @@ -46,14 +34,9 @@ apt: name: - proxmox-mailgateway - - sasl2-bin - - libsasl2-modules-ldap - opendkim - opendkim-tools - - opendmarc - - python-mysqldb # Needed to manage the db for dmarc reports - - mariadb-client # Needed to inject the schema - - patch # Needed to remove the subscription nag screen + - patch # Needed to remove the subscription nag screen - libmail-imapclient-perl # For the sa-learn script update_cache: True tags: pmg @@ -68,34 +51,14 @@ service: name=rsyslog state=started enabled=True tags: pmg -- name: Add postfix to the sasl group +- name: Add postfix to the opendkim group user: name: postfix - groups: sasl,opendkim,opendmarc + groups: opendkim append: True notify: restart postfix tags: pmg -- name: Deploy saslauth configuration - template: src={{ item.src }}.j2 dest={{ item.dest }} mode={{ item.mode | default(omit) }} - with_items: - - src: saslauthd - dest: /etc/default/saslauthd - - src: smtpd.conf - dest: /etc/postfix/sasl/smtpd.conf - - src: saslauthd.conf - dest: /etc/saslauthd.conf - mode: 600 - when: pmg_ldap_auth == True - notify: - - restart saslauthd - - restart postfix - tags: pmg - -- name: Handle saslauthd daemon - service: name=saslauthd state={{ pmg_ldap_auth | ternary('started','stopped') }} enabled={{ pmg_ldap_auth | ternary(True,False) }} - tags: pmg - - name: Create custom templates directory file: path=/etc/pmg/templates state=directory tags: pmg @@ -104,7 +67,6 @@ template: src={{ item }}.j2 dest=/etc/pmg/templates/{{ item }} with_items: - master.cf.in - - main.cf.in notify: pmgconfig sync tags: pmg @@ -122,26 +84,13 @@ file: src=/home/lbkp/pmg dest=/var/lib/pmg/backup state=link tags: pmg -- name: Create pre/post backup scripts dir - file: path=/etc/backup/{{ item }}.d state=directory +- name: Deploy pre/post backup scripts + template: src=pmg_{{ item }}_backup.sh.j2 dest=/etc/backup/{{ item }}.d/pmg.sh mode=755 with_items: - pre - post tags: pmg -- name: Deploy pre/post backup scripts - template: src={{ item.src }}.j2 dest=/etc/backup/{{ item.type }}.d/pmg.sh mode=755 - with_items: - - src: pmg_pre_backup.sh - type: pre - - src: pmg_post_backup.sh - type: post - tags: pmg - -- name: Create dehydrated hook dir - file: path=/etc/dehydrated/hooks_deploy_cert.d/ state=directory - tags: pmg - - name: Deploy dehydrated hook template: src=dehydrated_deploy_hook.j2 dest=/etc/dehydrated/hooks_deploy_cert.d/pmg mode=755 tags: pmg @@ -167,10 +116,8 @@ template: src=opendkim.conf.j2 dest=/etc/opendkim/{{ item }}.conf with_items: - signer - - verifier notify: - restart opendkim-signer - - restart opendkim-verifier tags: pmg - name: Create DKIM dir @@ -190,18 +137,12 @@ template: src=opendkim.service.j2 dest=/etc/systemd/system/opendkim-{{ item }}.service with_items: - signer - - verifier register: pmg_opendkim_unit tags: pmg -- name: Deploy opendmarc service unit - template: src=opendmarc.service.j2 dest=/etc/systemd/system/opendmarc.service - register: pmg_opendmarc_unit - tags: pmg - - name: Reload systemd systemd: daemon_reload=True - when: pmg_opendkim_unit.results | selectattr('changed','equalto',True) | list | length > 0 or pmg_opendmarc_unit.changed + when: pmg_opendkim_unit.results | selectattr('changed','equalto',True) | list | length > 0 tags: pmg - name: Check if /etc/pmg/mynetworks exists @@ -209,65 +150,13 @@ register: pmg_mynetworks tags: pmg -- name: Deploy opendmarc config - template: src=opendmarc.conf.j2 dest=/etc/opendmarc.conf - tags: pmg - -- name: Handle opendkim and opendmarc services +- name: Handle opendkim services service: name={{ item.service }} state={{ item.enabled | ternary('started','stopped') }} enabled={{ item.enabled }} with_items: - service: opendkim enabled: False - service: opendkim-signer enabled: "{{ pmg_dkim_sign | length > 0 }}" - - service: opendkim-verifier - enabled: "{{ pmg_check_dkim }}" - - service: opendmarc - enabled: "{{ pmg_check_dkim and pmg_check_dmarc }}" - tags: pmg - -- import_tasks: ../includes/get_rand_pass.yml - vars: - - pass_file: "/etc/opendmarc.dbpass" - when: pmg_dmarc_db_pass is not defined - tags: pmg -- set_fact: pmg_dmarc_db_pass={{ rand_pass }} - when: pmg_dmarc_db_pass is not defined - tags: pmg - -- import_tasks: ../includes/webapps_create_mysql_db.yml - vars: - - db_name: "{{ pmg_dmarc_db_name }}" - - db_user: "{{ pmg_dmarc_db_user }}" - - db_server: "{{ pmg_dmarc_db_server }}" - - db_pass: "{{ pmg_dmarc_db_pass }}" - when: pmg_dmarc_report == True - tags: pmg - -- name: Inject DMARC report SQL structure - mysql_db: - name: "{{ pmg_dmarc_db_name }}" - state: import - target: /usr/share/dbconfig-common/data/opendmarc/install/mysql - login_host: "{{ pmg_dmarc_db_server }}" - login_user: sqladmin - login_password: "{{ mysql_admin_pass }}" - when: pmg_dmarc_report and db_created.changed - tags: pmg - -- name: Deploy dmarc_reports script - template: src=dmarc_reports.j2 dest=/usr/local/bin/dmarc_reports mode=700 - when: pmg_dmarc_report == True - tags: pmg - -- name: Handle dmarc report cron job - cron: - name: dmarc_reports - cron_file: opendmarc - user: root - job: systemd-cat /usr/local/bin/dmarc_reports - special_time: daily - state: "{{ pmg_dmarc_report | ternary('present','absent') }}" tags: pmg - name: Install imap-sa-learn script @@ -320,7 +209,6 @@ - fromnamespoof.cf - phishing.pre - phishing.cf - - scores.cf notify: reload pmg-smtp-filter tags: pmg @@ -391,3 +279,4 @@ tags: pmg,firewall - include: filebeat.yml +- include: cleanup.yml diff --git a/roles/pmg/templates/master.cf.in.j2 b/roles/pmg/templates/master.cf.in.j2 index 7a46854..155a3c3 100644 --- a/roles/pmg/templates/master.cf.in.j2 +++ b/roles/pmg/templates/master.cf.in.j2 @@ -1,15 +1,92 @@ +# +# Postfix master process configuration file. Each logical line +# describes how a Postfix daemon program should be run. +# +# A logical line starts with non-whitespace, non-comment text. +# Empty lines and whitespace-only lines are ignored, as are comment +# lines whose first non-whitespace character is a `#'. +# A line that starts with whitespace continues a logical line. +# +# The fields that make up each line are described below. A "-" field +# value requests that a default value be used for that field. +# +# Service: any name that is valid for the specified transport type +# (the next field). With INET transports, a service is specified as +# host:port. The host part (and colon) may be omitted. Either host +# or port may be given in symbolic form or in numeric form. Examples +# for the SMTP server: localhost:smtp receives mail via the loopback +# interface only; 10025 receives mail on port 10025. +# +# Transport type: "inet" for Internet sockets, "unix" for UNIX-domain +# sockets, "fifo" for named pipes. +# +# Private: whether or not access is restricted to the mail system. +# Default is private service. Internet (inet) sockets can't be private. +# +# Unprivileged: whether the service runs with root privileges or as +# the owner of the Postfix system (the owner name is controlled by the +# mail_owner configuration variable in the main.cf file). Only the +# pipe, virtual and local delivery daemons require privileges. +# +# Chroot: whether or not the service runs chrooted to the mail queue +# directory (pathname is controlled by the queue_directory configuration +# variable in the main.cf file). Presently, all Postfix daemons can run +# chrooted, except for the pipe, virtual and local delivery daemons. +# The proxymap server can run chrooted, but doing so defeats most of +# the purpose of having that service in the first place. +# The files in the examples/chroot-setup subdirectory describe how +# to set up a Postfix chroot environment for your type of machine. +# +# Wakeup time: automatically wake up the named service after the +# specified number of seconds. A ? at the end of the wakeup time +# field requests that wake up events be sent only to services that +# are actually being used. Specify 0 for no wakeup. Presently, only +# the pickup, queue manager and flush daemons need a wakeup timer. +# +# Max procs: the maximum number of processes that may execute this +# service simultaneously. Default is to use a globally configurable +# limit (the default_process_limit configuration parameter in main.cf). +# Specify 0 for no process count limit. +# +# Command + args: the command to be executed. The command name is +# relative to the Postfix program directory (pathname is controlled by +# the daemon_directory configuration variable). Adding one or more +# -v options turns on verbose logging for that service; adding a -D +# option enables symbolic debugging (see the debugger_command variable +# in the main.cf configuration file). See individual command man pages +# for specific command-line options, if any. +# +# In order to use the "uucp" message tranport below, set up entries +# in the transport table. +# +# In order to use the "cyrus" message transport below, configure it +# in main.cf as the mailbox_transport. +# +# SPECIFY ONLY PROGRAMS THAT ARE WRITTEN TO RUN AS POSTFIX DAEMONS. +# ALL DAEMONS SPECIFIED HERE MUST SPEAK A POSTFIX-INTERNAL PROTOCOL. +# +# DO NOT SHARE THE POSTFIX QUEUE BETWEEN MULTIPLE POSTFIX INSTANCES. +# # ========================================================================== # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ========================================================================== +[% IF ! pmg.mail.before_queue_filtering -%] scan unix - - n - [% pmg.mail.max_filters %] lmtp -o lmtp_send_xforward_command=yes -o lmtp_connection_cache_on_demand=no -o disable_dns_lookups=yes +[% END -%] [% pmg.mail.int_port %] inet n - - - [% pmg.mail.max_smtpd_out %] smtpd +[% IF pmg.mail.before_queue_filtering -%] + -o smtpd_proxy_filter=127.0.0.1:10023 + -o smtpd_proxy_options=speed_adjust + -o smtpd_client_connection_count_limit=[% pmg.mail.conn_count_limit div 5 %] +[%- ELSE -%] -o content_filter=scan:127.0.0.1:10023 +[%- END %] -o smtpd_recipient_restrictions=permit_mynetworks,reject_unauth_destination -o smtpd_helo_restrictions= -o smtpd_client_restrictions= @@ -19,31 +96,16 @@ scan unix - - n - [% pmg.mail.max_filters %] [% pmg.mail.ext_port %] inet n - - - 1 postscreen smtpd pass - - - - [% pmg.mail.max_smtpd_in %] smtpd +[% IF pmg.mail.before_queue_filtering -%] + -o smtpd_proxy_filter=127.0.0.1:10024 + -o smtpd_proxy_options=speed_adjust + -o smtpd_client_connection_count_limit=[% pmg.mail.conn_count_limit div 5 %] +[%- ELSE -%] -o content_filter=scan:127.0.0.1:10024 +[%- END %] -o receive_override_options=no_address_mappings -o smtpd_discard_ehlo_keywords=silent-discard,dsn -o mynetworks=127.0.0.0/8,[% postfix.int_ip %] - -o smtpd_milters={{ pmg_smtpd_milters_ext | join(',') }} - -submission inet n - - - 100 smtpd - -o content_filter=scan:127.0.0.1:10023 - -o smtpd_enforce_tls=yes - -o smtpd_sasl_auth_enable=yes - -o smtpd_client_restrictions=permit_sasl_authenticated,reject - -o smtpd_recipient_restrictions=reject_unknown_recipient_domain - -o smtpd_sender_restrictions= - -o smtpd_helo_restrictions= - -o smtpd_milters={{ pmg_smtpd_milters_int | join(',') }} - -smtps inet n - - - 100 smtpd - -o content_filter=scan:127.0.0.1:10023 - -o smtpd_tls_wrappermode=yes - -o smtpd_sasl_auth_enable=yes - -o smtpd_client_restrictions=permit_sasl_authenticated,reject - -o smtpd_recipient_restrictions=reject_unknown_recipient_domain - -o smtpd_sender_restrictions= - -o smtpd_helo_restrictions= - -o smtpd_milters={{ pmg_smtpd_milters_int | join(',') }} 127.0.0.1:10025 inet n - n - - smtpd -o content_filter=