#!/usr/bin/env perl use strict; use warnings; no warnings qw{experimental}; use feature qw{signatures}; use List::Util qw{uniq}; use Config::Simple; use File::Copy; use File::Touch; use DNS::Unbound; use Net::DNS::Packet; my @domains2add = @ARGV; my $dkim_config_file = "/etc/opendkim.conf"; my $trusted_hosts_file = '/etc/opendkim/TrustedHosts'; my $keytable_file = '/etc/opendkim/KeyTable'; my $signing_table_file = '/etc/opendkim/SigningTable'; DKIM_CONFIG: { my $cfg = Config::Simple->new($dkim_config_file); die "Can't open opendkim config file" unless $cfg; $cfg->param('KeyTable', $keytable_file ); $cfg->param('SigningTable', $signing_table_file); $cfg->param('ExternalIgnoreList', $trusted_hosts_file); $cfg->param('InternalHosts', $trusted_hosts_file); # This way we support signing more than one domain $cfg->delete('Domain'); $cfg->delete('KeyFile'); $cfg->delete('Selector'); File::Copy::copy($dkim_config_file, "$dkim_config_file.bak") or die "Could not back up old dkim config"; $cfg->save(); print "OpenDKIM config file ($dkim_config_file) changed.\n"; } TRUSTED_HOSTS: { my @hosts = read_lines( $trusted_hosts_file ); my @ips2add = grep { defined $_ } map { ( domain2ips( $_, "A" ), domain2ips( $_, "AAAA" ) ) } @domains2add; push(@hosts, "127.0.0.1", "localhost", "::1", @domains2add, @ips2add); @hosts = uniq @hosts; backup_and_emit( $trusted_hosts_file, @hosts); } KEY_TABLE: { my @lines = read_lines( $keytable_file ); push(@lines, (map { "mail._domainkey.$_ $_:mail:/etc/opendkim/keys/$_/mail.private" } @domains2add ) ); @lines = uniq @lines; backup_and_emit($keytable_file, @lines); } SIGNING_TABLE: { my @lines = read_lines( $signing_table_file ); push(@lines, (map { "$_ mail._domainkey.$_" } @domains2add ) ); @lines = uniq @lines; backup_and_emit($signing_table_file, @lines); } sub read_lines( $file ) { File::Touch::touch($file); open(my $fh, '<', $file); my @lines = map { chomp $_; $_ } readline $fh; close $fh; return @lines; } sub backup_and_emit($file, @lines) { File::Copy::copy($file, "$file.bak") or die "Could not back up $file"; open(my $wh, '>', $file); foreach my $line (@lines) { print $wh "$line\n"; } close $wh; print "$file changed.\n"; } sub domain2ips( $domain, $type ) { my $resolver = DNS::Unbound->new(); my $p = $resolver->resolve( $domain, $type )->answer_packet(); my @rrs = Net::DNS::Packet->new( \$p )->answer; return map { $_->address } @rrs; }