diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2018-04-16 16:46:22 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2018-04-16 16:46:22 +0200 |
commit | b2e15909533fccca8d344f4f2678564f5398ad8a (patch) | |
tree | 3ef3640564b059334d0bdf0e8cf8419bfd16cad0 /acmeman | |
parent | 3a9ca11ba6a8cede2beb7c28036137f9f4efc0ba (diff) | |
download | acmeman-b2e15909533fccca8d344f4f2678564f5398ad8a.tar.gz acmeman-b2e15909533fccca8d344f4f2678564f5398ad8a.tar.bz2 |
Ignore hostnames that don't resolve to the server IP address
* Makefile.PL: Require Sys::Hostname and Net::DNS
* acmeman (collect): If core.check-dns is set, test A records of
each hostname collected. Ignore hostnames that don't point back
to our server.
(%syntax): New keywords: core.check-dns and core.my-ip
Diffstat (limited to 'acmeman')
-rwxr-xr-x | acmeman | 89 |
1 files changed, 89 insertions, 0 deletions
@@ -26,6 +26,8 @@ use File::Path qw(make_path); use DateTime::Format::Strptime; use LWP::UserAgent; use LWP::Protocol::https; +use Net::DNS; +use Sys::Hostname; use Pod::Usage; use Pod::Man; use Getopt::Long qw(:config gnu_getopt no_ignore_case); @@ -234,9 +236,24 @@ Valid values for I<BOOL> are: B<1>, B<on>, B<true>, or B<yes>, for true, and B<0>, B<off>, B<false>, or B<no> for false (all values case-insensitive). +=item B<check-dns=>I<BOOL> + +When set to B<true> (the default), the program will check whether each +host name has an A DNS record pointing back to one of the IP addresses +of the server. Hostnames which don't satisfy this condition will be ignored. +The IP of the server is determined by looking up the A record for its +hostname. This can be overridden using the B<my-ip> configuration statement. + =item B<key-size=>I<N> Size of the RSA key to use, in bits. Default is 4096. + +=item B<my-ip>=I<IP> [I<IP>...] + +Declares IP address (or addresses) of this server. Use this keyword if +the server IP cannot be reliably determined by resolving its hostname. +Special I<IP> B<$hostip> stands for the IP retreived by resolving the +hostname. =back @@ -846,6 +863,64 @@ sub coalesce { @{$ref} = map { $_->{domain} } sort { $a->{ord} <=> $b->{ord} } @domlist; } +sub resolve { + my $host = shift; + state $res; + unless ($res) { + $res = new Net::DNS::Resolver(); + } + my $q = $res->query($host, 'A'); + unless ($q) { + if ($res->errorstring eq 'NXDOMAIN') { + debug(1, "$host: no such host"); + } elsif ($res->errorstring eq 'NOERROR') { + debug(1, "$host: no A record"); + } else { + error("$host: " . $res->errorstring); + # FIXME: bail out? + } + return (); + } + return map { $_->rdatastr } grep { $_->type eq 'A' } $q->answer; +} + +sub myip { + my $host = shift; + state $ips; + unless ($ips) { + $ips = {}; + my $addhost; + + if ($config->isset(qw(core my-ip))) { + $addhost = 0; + foreach my $ip ($config->get(qw(core my-ip))) { + if ($ip eq '$hostip') { + $addhost = 1; + } else { + $ips->{$ip} = 1; + } + } + } else { + $addhost = 1; + } + + if ($addhost) { + foreach my $ip (resolve(hostname())) { + $ips->{$ip} = 1; + } + } + } + return $ips->{$host}; +} + +sub host_ns_ok { + my $host = shift; + foreach my $ip (resolve($host)) { + return 1 if myip($ip); + } + return 0 +} + sub collect { my $aref = shift; return unless $config->isset('domain'); @@ -854,6 +929,18 @@ sub collect { my $dom; my $ft; + if ($config->get(qw(core check-dns))) { + my @res = grep { host_ns_ok($_) } + ($k, ($v->{alt} ? @{$v->{alt}} : ())); + if (@res) { + $k = shift @res; + $v->{alt} = @res ? \@res : undef; + } else { + error("ignoring $k: none of its names resolves to our IP"); + next; + } + } + if (exists($v->{files})) { if (my $fref = $config->get('files', $v->{files})) { $dom = new App::Acmeman::Domain( @@ -931,6 +1018,8 @@ my %syntax = ( 'time-delta' => { default => 86400 }, source => { default => 'apache' }, 'check-alt-names' => { default => 0, parser => \&cb_parse_bool }, + 'check-dns' => { default => 1, parser => \&cb_parse_bool }, + 'my-ip' => { array => 1 }, 'key-size' => { re => '^\d+$', default => 4096 } } }, |