From b0ba5834ceb783fc99b05ad1281343a92bd61f19 Mon Sep 17 00:00:00 2001 From: Denis Knauf Date: Thu, 1 Dec 2022 14:05:00 +0100 Subject: [PATCH] postscreen spf generator. dependencies: python3 instead of python2. cdb -> lmdb for aliases --- files/postscreen_access_spf_generator.rb | 62 ++++++++++++++++++++++++ meta/main.yml | 8 ++- tasks/main.yml | 19 ++++++-- tasks/postfix.yml | 5 +- vars/main.yml | 3 +- 5 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 files/postscreen_access_spf_generator.rb diff --git a/files/postscreen_access_spf_generator.rb b/files/postscreen_access_spf_generator.rb new file mode 100644 index 0000000..7be558d --- /dev/null +++ b/files/postscreen_access_spf_generator.rb @@ -0,0 +1,62 @@ +#!/usr/bin/env ruby +require 'shellwords' +require 'ipaddress' +require 'resolv' + +class R + def initialize opts=nil + @resolv = Resolv::DNS.new opts + end + IN = Resolv::DNS::Resource::IN + + def a( q) @resolv.getresources( q, IN::A) end + def aaaa( q) @resolv.getresources( q, IN::AAAA) end + def txt( q) @resolv.getresources( q, IN::TXT) end + def mx( q) @resolv.getresources( q, IN::MX) end + + def ip q + a(q) + aaaa(q) + end +end + +$resolv = R.new + +def bb d + $resolv.txt( d).map do |l| + v, *as = l.data.split( ' ') + if "v=spf1" == v + as.map do |a| + case a + when /\Aa:(.*)\z/ + $resolv.ip( $1).map( &:address) + when "mx" + $resolv.mx( d).map do |l| + $resolv.ip( l.exchange.to_s).map( &:address) + end + when /\Aip[46]:(.*)\z/ then $1 + when /\A(?:redirect=|include:)(.*)\z/ then bb $1 + when /\A[-~+]all/ then nil + else nil + end + end + end + end +end + +ARGV. + flat_map do |d| + bb( d). + flatten. + compact. + uniq. + map {|x| IPAddress.parse( x).first.to_string rescue ArgumentError }. + select {|x| String === x }. + uniq. + map {|x| [x, d]} + end. + group_by {|(x,d)| x }. + each {|x,xs| xs.map! &:last }. + sort_by {|x,ds| x = IPAddress.parse x; [x.class.name, x] }. + each do |(x,ds)| + puts "#{x} permit # #{ds.uniq.sort.join ' '}" + end diff --git a/meta/main.yml b/meta/main.yml index 55686cb..fc0a634 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,7 +1,6 @@ galaxy_info: - author: your name - description: your role description - company: your company (optional) + author: Denis Knauf + description: Mailserver providing SMTP, Submission, IMAP including postfix, dovecot and LDAP # If the issue tracker for your role is not on github, uncomment the # next line and provide a value @@ -14,7 +13,7 @@ galaxy_info: # - GPL-3.0-only # - Apache-2.0 # - CC-BY-4.0 - license: AGPL-3.0 + license: AGPL-3.0-or-later min_ansible_version: 2.9 @@ -50,4 +49,3 @@ galaxy_info: dependencies: [] # List your role dependencies here, one per line. Be sure to remove the '[]' above, # if you add dependencies to this list. - diff --git a/tasks/main.yml b/tasks/main.yml index a23d4d5..38dc16a 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -4,12 +4,13 @@ - name: install gnutls, postfix & dovecot apt: name: - # TLS + # X509 - gnutls-bin # ansible - - python-pip - - python-openssl + - python3-pip + - python3-openssl + - python3-psycopg2 #- libpam-ldapd @@ -35,6 +36,10 @@ - dovecot-gssapi - dovecot-lmtpd + # ruby - scripts + - ruby + - ruby-gem + - name: 'directory-structures (/etc/postfix-&/etc/dovecot&...)' file: dest: "{{item}}" @@ -144,6 +149,14 @@ with_dict: Socket: local:/var/spool/postfix/milter/opendmarc +- name: 'postscreen access via SPF entries generator' + copy: + src: postscreen_access_spf_generator.rb + dest: /usr/local/bin + owner: root + group: root + mode: 0755 + - name: copy systemd-services copy: src: "{{item}}" diff --git a/tasks/postfix.yml b/tasks/postfix.yml index 6615082..c5b1f2e 100644 --- a/tasks/postfix.yml +++ b/tasks/postfix.yml @@ -21,6 +21,8 @@ compatibility_level: "2" html_directory: /usr/share/doc/postfix/html default_database_type: lmdb + enable_long_queue_ids: yes + recipient_delimiter: '+' # Verbindungssicherheit / Verschluesselung: smtpd_tls_cert_file: "/etc/postfix/tls/{{mail_server_fqdn}}.crt" @@ -54,7 +56,6 @@ mydestination: '' relayhost: '' mynetworks: '{{postfix_mynetworks}}' - recipient_delimiter: '+' inet_interfaces: 'all' #inet_protocols: 'ipv4' @@ -79,7 +80,7 @@ # welche domains sind moeglich? virtual_mailbox_domains: "cdb:/etc/postfix/virtual_endpoint_map" # aliases fuer virtuelle adressen. - virtual_alias_maps: "cdb:/etc/postfix/virtual_aliases, cdb:/etc/postfix/mailinglists" + virtual_alias_maps: "lmdb:/etc/postfix/virtual_aliases, lmdb:/etc/postfix/mailinglists" sender_canonical_maps: "cdb:/etc/postfix/sender_canonical" # virtual_mailbox_maps wird nicht gesezt, da virtual_transport die ueberpruefung vornimmt. smtpd_relay_restrictions: 'permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination' diff --git a/vars/main.yml b/vars/main.yml index b741c50..82d917f 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -2,7 +2,7 @@ # vim: set et sw=2 ts=2 sts=2: postfix_default_file_content: - "/etc/aliases": '' + "/etc/aliases": '# DO NOT USE THIS FILE. INSTEAD USE /etc/postfix/virual_aliases.' "/etc/postfix/virtual_aliases": '' "/etc/postfix/recipient_access": 'public@ REJECT' "/etc/postfix/relaydomains": '' @@ -14,6 +14,7 @@ postfix_default_file_content: "/etc/postfix/virtual_domain_map": "nfotex.com OK" "/etc/postfix/virtual_endpoint_map": '' "/etc/postfix/transport_map": '' + "/etc/postfix/postscreen_access.cidr": '' postfix_postmap: - cdb:access - cdb:generic_map