#!/usr/bin/perl # Auto-generating IPv6 Reverse DNS server with DNSSEC online signing # Version 1.1 # $Id: v6rev.pl,v 1.5 2011/12/12 02:17:32 fujiwara Exp $ # # Author: Kazunori Fujiwara , my $debug = 0; my $loaded_privdrop = 0; use Net::DNS::SEC::Private; use Net::DNS::Nameserver; use Socket; use Socket6; use strict; use warnings; my $configfile = $ARGV[0]; STDOUT->autoflush(1); ############################################################################### # Supported queries: # any.$rev_dom PTR ----> ANY.$fwd_dom # $rev_dom NS/SOA/NSEC/DNSKEY # ANY.$fwd_dom AAAA ----> AAAA # ANY.$fwd_dom NSEC # $fwd_dom NS/SOA/NSEC/DNSKEY # Remaining work: # new configuration # multiple zone support # name error handling on reverse mapping ############################################################################### my @serveraddr = ('203.178.129.34', '2001:200:132:7::2'); my $serverport = 53; my $pid_file ="/var/run/v6rev.pid"; ############################################################################### # We need periodic re-signing of DNSKEY and other static RRSets. ############################################################################### my $enable_dnssec = 0; my $querylog = 0; my $keyfile_dir = "."; my $reconfig_interval = 3600; my $ttl = 900; my $serial = time; my @nsname = ('ns.example.jp'); my %static_ptr; my @zone = (); my $use_privdrop = ''; # my @zone = ( { 'dom' => '8.b.d.0.1.0.0.2.ip6.arpa' } ); # $zone[0] = forward zone # $zone[1...] = reverse zone # $zone[]->{dom} = domain name '8.b.d.0.1.0.0.2.ip6.arpa' # $zone[]->{hostdigits} = number of host part digits # $zone[]->{keys} = [ @public_keys ] # $zone[]->{ksk_private} = [ @ksk_private ] # $zone[]->{zsk_private} = [ @zsk_private ] # $zone[]->{key_sigs} = [ @dnskey_rrsigs ] # $zone[]->{soa} = SOA RR of the zone # $zone[]->{soa_sigs} = [ @soa_rrsigs ] # $zone[]->{ns} = [ @ns ] # $zone[]->{ns_sigs} = [ @ns_rrsigs ]; # $zone[]->{apex_nsec} = APEX's NSEC RR # $zone[]->{apex_nsec_sigs} = [ @APEX_NSEC_rrsigs ] my $initialized_time = -1; my $reload_interval = 86400; ############################################################################### &initialize($configfile); if ($serverport eq 53 && $< != 0) { # for debug @serveraddr = ('127.0.0.1', '::1'); $serverport = 10053; $pid_file ="v6rev.pid"; } ############################################################################### sub initialize() { @zone = (); $zone[0] = { dom => "example.com" }; if (defined($configfile)) { open(F, "$configfile") || die "cannot open $configfile"; while () { chomp; next if (/^[#; \t]/); if (/^(\S+):\s+(.*)$/) { my ($key, $value) = ($1, $2); my @value = split(/,/, $value); for (my $i = 0; $i <= $#value; $i++) { if ($value[$i] =~ /^\s*(\S+.*\S*)\s*$/) { $value[$i] = $1; } } if ($key eq "server_address" && $#value >= 0) { @serveraddr = @value; } elsif ($key eq "server_port" && $#value == 0 && $value[0] > 0) { $serverport = $value[0]; } elsif ($key eq "pid_file" && $#value == 0) { $pid_file = $value[0]; } elsif ($key eq "debug" && $#value == 0) { $debug = $value[0]; } elsif ($key eq "reconfig_interval" && $#value == 0 && $value[0] > 0) { $reconfig_interval = $value[0]; } elsif ($key eq "keyfile_dir" && $#value == 0) { $keyfile_dir = $value[0]; } elsif ($key eq "ttl" && $#value == 0 && $value[0] > 0) { $ttl = $value[0]; } elsif ($key eq "nsname" && $#value >= 0) { @nsname = @value; } elsif ($key eq "forward_domainname" && $#value == 0) { $zone[0] = { dom => $value[0] }; } elsif ($key eq "reverse_domainname" && $#value >= 0) { foreach my $dom (@value) { $dom =~ tr / A-Z / a-z /; if ($dom =~ /^([0-9a-f.]+\.ip6\.arpa)\.?/i) { push @zone, { 'dom' => $1 }; } else { print STDERR "Illegal reverse domain name: $dom\n"; } } } elsif ($key eq "enable_dnssec" && $#value == 0) { if ($value[0] > 0 || $value[0] =~ /^(yes|on)$/i) { $enable_dnssec = 1; } else { $enable_dnssec = 0; } } elsif ($key eq "querylog" && $#value == 0) { if ($value[0] > 0 || $value[0] =~ /^(yes|on)$/i) { $querylog = 1; } else { $querylog = 0; } } elsif ($key eq "static_ptr" && $#value == 0) { my @rr = split(/ /, $value[0]); if ($#rr != 1 || &rev2host($rr[0]) eq '') { print STDERR "Invalid parameter: $_\n"; } else { $static_ptr{$rr[0]} = $rr[1]; } } elsif ($key eq "use_privdrop" && $#value == 0) { if ($value[0] =~ /^\d+$/ || defined(getpwnam($value[0]))) { $use_privdrop = $value[0]; } else { print STDERR "Invalid parameter: $_\n"; } } else { print STDERR "Unknown parameter: $_\n"; } } } close (F); } if ($#zone <= 0) { # For example $zone[1] = ( { 'dom' => '8.b.d.0.1.0.0.2.ip6.arpa' } ); } for (my $i = 0; $i <= $#zone; $i++) { my $dom = $zone[$i]->{dom}; if ($i != 0) { # calculate hostdigits my @dom = split(/\./, $dom); $zone[$i]->{hostdigits} = 33 - $#dom; } else { $zone[$i]->{hostdigits} = 0; } $zone[$i]->{soa} = Net::DNS::RR->new( "$dom $ttl IN SOA ".$nsname[0]." postmaster.".$nsname[0]." $serial 3600 900 86400 900"); $zone[$i]->{ns} = []; for my $k (@nsname) { push @{$zone[$i]->{ns}}, Net::DNS::RR->new("$dom $ttl IN NS $k"); } $zone[$i]->{keys} = [ ] ; $zone[$i]->{ksk_private} = [ ]; $zone[$i]->{zsk_private} = [ ]; } if ($enable_dnssec) { opendir(my $dh, $keyfile_dir) || die "cannot opendir $keyfile_dir"; foreach my $file (readdir($dh)) { for (my $i = 0; $i <= $#zone; $i++) { my $dom = $zone[$i]->{dom}; if ($file =~ /^K$dom\.\+\d+\+\d+\.key$/) { my $public = Net::DNS::RR->new_from_string(&load_file($keyfile_dir."/".$file)); $public->ttl($ttl); push @{$zone[$i]->{keys}}, $public; my $privatefile = $file; $privatefile =~ s/key$/private/; $privatefile = $keyfile_dir."/".$privatefile; if ($public->flags == 257) { if (-f $privatefile) { my $private = Net::DNS::SEC::Private->new($privatefile); push @{$zone[$i]->{ksk_private}}, $private; } } else { if (-f $privatefile) { my $private = Net::DNS::SEC::Private->new($privatefile); push @{$zone[$i]->{zsk_private}}, $private; } } } } } close($dh); } ############################################################################### for (my $i = 0; $i <= $#zone; $i++) { $zone[$i]->{key_sigs} = (); $zone[$i]->{soa_sigs} = (); $zone[$i]->{ns_sigs} = (); $zone[$i]->{apex_nsec_sigs} = (); for my $private (@{$zone[$i]->{ksk_private}}) { push @{$zone[$i]->{key_sigs}}, create Net::DNS::RR::RRSIG([@{$zone[$i]->{keys}}],$private); } if ($i == 0) { $zone[0]->{apex_nsec} = Net::DNS::RR->new($zone[0]->{dom}." $ttl IN NSEC 00000000000000000000000000000000.".$zone[0]->{dom}." ( SOA NS DNSKEY NSEC RRSIG )"); } else { $zone[$i]->{apex_nsec} = Net::DNS::RR->new(&generate_rev_nsec("",$zone[$i]->{dom}, $zone[$i]->{hostdigits})); } for my $private (@{$zone[$i]->{zsk_private}}) { push @{$zone[$i]->{soa_sigs}}, create Net::DNS::RR::RRSIG([$zone[$i]->{soa}],$private); push @{$zone[$i]->{ns_sigs}}, create Net::DNS::RR::RRSIG([@{$zone[$i]->{ns}}],$private); push @{$zone[$i]->{apex_nsec_sigs}}, create Net::DNS::RR::RRSIG([$zone[$i]->{apex_nsec}],$private); } } ############################################################################### $initialized_time = time; if ($debug) { &dump_variables; } } sub dump_variables { print "server_address=".join("/", @serveraddr)."\n"; print "nsname=".join("/", @nsname)."\n"; print "serverport=$serverport\n"; print "pid_file=$pid_file\n"; print "serial=$serial\n"; print "ttl=$ttl\n"; print "enable_dnssec=$enable_dnssec\n"; print "querylog=$querylog\n"; print "use_privdrop=$use_privdrop\n"; print "keyfile_dir=$keyfile_dir\n"; print "reconfig_interval=$reconfig_interval\n"; foreach my $n (keys(%static_ptr)) { print "static_ptr $n=".$static_ptr{$n}."\n"; } for (my $i = 0; $i <= $#zone; $i++) { print "zone $i: ".$zone[$i]->{dom}." hostdigits=".$zone[$i]->{hostdigits}."\n"; print "zone $i: soa: "; $zone[$i]->{soa}->print; print "zone $i: apex_nsec: "; $zone[$i]->{apex_nsec}->print; &displayrrset("zone $i: NS", @{$zone[$i]->{ns}}); &displayrrset("zone $i: keys", @{$zone[$i]->{keys}}); &displayrrset("zone $i: key_sigs", @{$zone[$i]->{key_sigs}}); &displayrrset("zone $i: soa_sigs", @{ $zone[$i]->{soa_sigs}}); &displayrrset("zone $i: ns_sigs", @{ $zone[$i]->{ns_sigs}}); &displayrrset("zone $i: apex_nsec_sigs", @{$zone[$i]->{apex_nsec_sigs}}); } } sub displayrrset { print "DISPLAYRRSET:".shift.":"; foreach (@_) { $_->print; } } ################################################################### # Initialize and start main loop ################################################################### my $ns = Net::DNS::Nameserver->new( LocalAddr => [ @serveraddr ], LocalPort => $serverport, ReplyHandler => \&reply_handler, Verbose => 0, ); if ($use_privdrop ne '' && $loaded_privdrop == 0) { require Privileges::Drop; Privileges::Drop::drop_privileges($use_privdrop); $loaded_privdrop = 1; } if ($ns) { open(F, "> $pid_file") || die "couldn't write $pid_file"; print F $$, "\n"; close(F); $ns->main_loop; } else { die "couldn't create nameserver object\n"; } ################################################################### # Load DNSKEY file ################################################################### sub load_file { my ($file) = @_; my ($line); open(F, "$file") || die "cannot open $file: $!"; while() { next if (/^;/); $line .= $_; } chomp($line); close(F); return $line; } ################################################################### # Reverse domainname -> hostname label ################################################################### sub rev2host { my $dom = shift; if ($dom =~ /^(([0-9a-fA-F]\.){32})ip6\.arpa\.?$/i) { return join("", reverse(split(/\./, $1))).'.'.$zone[0]->{dom}; } return ''; } ################################################################### # Forward hostname to IPv6 address ################################################################### sub host2addr { my $dom = shift; my $addr = ''; my $fwd_dom = $zone[0]->{dom}; if ($dom =~ /^([0-9a-fA-F]{32})\.$fwd_dom\.?$/i) { my $t = $1; $addr = join(':', ($t =~ m/.{4}/g)); } return $addr; } ################################################################### # forward lookup NSEC support ################################################################### sub nexthostlabel { my $label = shift; return '00000000000000000000000000000000' if ($label eq ''); $label =~ tr/A-Z/a-z/; return '' unless ($label =~ /^[0-9a-f]{32}$/); my $L = substr($label, 16, 16); my $H = substr($label, 0, 16); if ($L eq 'ffffffffffffffff') { if ($H eq 'ffffffffffffffff') { return ''; } $label = sprintf("%016x0000000000000000", hex($H)+1); } else { $label = $H.sprintf("%016x", hex($L)+1); } return $label; } sub previoushostlabel { my $label = shift; $label =~ tr/A-Z/a-z/; return '' unless ($label =~ /^[0-9a-f]{32}$/); my $L = substr($label, 16, 16); my $H = substr($label, 0, 16); if ($L eq '0000000000000000') { if ($H eq '0000000000000000') { return ''; } $label = sprintf("%016xffffffffffffffff", hex($H)-1); } else { $label = $H.sprintf("%016x", hex($L)-1); } return $label; } sub nearesthostlabel { my $label = shift; $label =~ tr/A-Z/a-z/; return $label if ($label =~ /^[0-9a-f]{32}$/); return '' if ($label eq ''); my $first = substr($label, 0, 1); return '' if (ord($first) < ord('0')); return '9fffffffffffffffffffffffffffffff' if (ord($first) > ord('9') && ord($first) < ord('a')); return 'ffffffffffffffffffffffffffffffff' if (ord($first) > ord('f')); if ($label =~ /^([0-9a-f]+)([^0-9a-f]?.*)$/) { my ($H, $L) = ($1, $2); if (length($H) >= 32) { return substr($H, 0, 32); } my $stub = ''; for (my $i = 32-length($H); $i > 0; $i--) { $stub .= '0'; } if ($L ne '') { return $H . $stub; } return &previoushostlabel($H.$stub); } else { $label = ''; } } sub generate_fwd_nsec { my $labels = shift; my $base = shift; my @labels = split(/\./, $labels); my $label = $labels[$#labels]; my $nearest = &nearesthostlabel($label); my $nextlabel = &nexthostlabel($nearest); if ($nextlabel eq '') { $nextlabel = $base; } else { $nextlabel = $nextlabel.'.'.$base; } if ($nearest ne '') { return "$nearest.$base $ttl IN NSEC $nextlabel ( AAAA NSEC RRSIG )"; } return ''; } ################################################################### # reverse lookup NSEC support ################################################################### sub rev_decrement { my @a = @_; my $carry = 1; my $i = $#a; while ($i >= 0 && $carry > 0) { my $k = hex($a[$i]); if ($k == 0) { $carry = 1; $a[$i] = 'f'; } else { $carry = 0; $a[$i] = sprintf("%1x", $k-1); } $i--; } return ($carry > 0) ? () : @a; } sub rev_increment { my @a = @_; my $carry = 1; my $i = $#a; while ($i >= 0 && $carry > 0) { my $k = hex($a[$i]); if ($k >= 15) { $carry = 1; $a[$i] = '0'; } else { $carry = 0; $a[$i] = sprintf("%1x", $k+1); } $i--; } return ($carry > 0) ? () : @a; } sub generate_rev_nsec { my $labels = shift; my $base = shift; my $hostdigits = shift; my $apex = shift; my @labels = reverse split(/\./, $labels); my @result; my $i = $#labels; if ($labels eq '') { $labels = ""; for ($i = 0; $i < $hostdigits; $i++) { $labels .= "0."; } return "$base $ttl IN NSEC $labels$base ( SOA NS DNSKEY NSEC RRSIG )"; } for ($i = 0; $i < $hostdigits; $i++) { if ($i > $#labels) { for (; $i < $hostdigits; $i++) { push @result, '0'; } @result = &rev_decrement(@result); } else { my $label = $labels[$i]; my $f = substr($label, 0, 1); if (ord($f) < ord('0')) { for (; $i < $hostdigits; $i++) { push @result, '0'; } @result = &rev_decrement(@result); } elsif (ord($f) > ord('9') && (ord($f) < ord('a'))) { push @result, '9'; $i++; for (; $i < $hostdigits; $i++) { push @result, 'f'; } } elsif (ord($f) > ord('f')) { push @result, 'f'; $i++; for (; $i < $hostdigits; $i++) { push @result, 'f'; } } elsif (length($label) > 1) { push @result, $f; $i++; for (; $i < $hostdigits; $i++) { push @result, 'f'; } } else { push @result, $label; } } } if ($#result < 0) { return ''; } my $newlabel = join(".", reverse @result).".".$base; my $newnext = ""; my @next = &rev_increment(@result); if ($#next < 0) { $newnext = $base; } else { $newnext = join(".", reverse @next).".".$base; } return "$newlabel $ttl IN NSEC $newnext ( PTR NSEC RRSIG )"; } ################################################################### # Main reply handler ################################################################### sub reply_handler { my ($qname, $qclass, $qtype, $peerhost,$query,$conn) = @_; my ($rcode, @ans, @auth, @add); my (@qadd, $rr, $nsec, $addr, $host, $qnames, $short); my ($opt, $opt_do) = ('', 0); my $do_dnssec; my $fwd_dom = $zone[0]->{dom}; my $now = time; if ($initialized_time + $reload_interval < $now) { print "$now initialize\n"; &initialize; } $qname = '.' if ($qname eq ''); ($qnames = $qname) =~ y/A-Z/a-z/; $rcode = 'REFUSED'; @qadd = $query->additional; if ($#qadd > 0) { return ("SERVFAIL", \@ans, \@auth, \@add, { aa => 1 }); } elsif ($#qadd == 0) { $opt = $qadd[0]; if ($opt->type ne "OPT") { return ("SERVFAIL", \@ans, \@auth, \@add, { aa => 1 }); } $opt_do = $opt->do ? 1 : 0; push @add, $opt; } print "$now $peerhost $qname $qclass $qtype $opt_do\n" if ($querylog); $do_dnssec = $enable_dnssec && $opt_do; if ($qnames =~ /\.ip6\.arpa$/) { my $no; my $dom; $rcode = 'REFUSED'; for ($no = 1; $no <= $#zone; $no++) { $dom = $zone[$no]->{'dom'}; if ($qnames eq $dom) { if ($qtype eq "NS") { push @ans, @{$zone[$no]->{ns}}; push @ans, @{$zone[$no]->{ns_sigs}} if ($do_dnssec); } elsif ($qtype eq "SOA") { push @ans, $zone[$no]->{soa}; push @ans, @{$zone[$no]->{soa_sigs}} if ($do_dnssec); } elsif ($qtype eq "DNSKEY" && $do_dnssec) { push @ans, @{$zone[$no]->{keys}}, @{$zone[$no]->{key_sigs}}; } elsif ($qtype eq "NSEC" && $do_dnssec) { push @ans, $zone[$no]->{apex_nsec}, @{$zone[$no]->{apex_nsec_sigs}}; } else { push @auth, $zone[$no]->{soa}; push @auth, @{$zone[$no]->{soa_sigs}}, $zone[$no]->{apex_nsec}, @{$zone[$no]->{apex_nsec_sigs}} if ($do_dnssec); } $rcode = "NOERROR"; last; } elsif ($qnames =~ /^(.*)\.$dom.?$/) { $short = $1; $host = &rev2host($qname); if ($host ne '') { if (defined($static_ptr{$qnames})) { $host = $static_ptr{$qnames}; } if ($qtype eq "PTR") { $rr = Net::DNS::RR->new("$qname $ttl $qclass $qtype $host"); push @ans, $rr; if ($do_dnssec) { foreach my $private (@{$zone[$no]->{zsk_private}}) { push @ans, create Net::DNS::RR::RRSIG([$rr],$private); } } push @auth, @{$zone[$no]->{ns}}; push @auth, @{$zone[$no]->{ns_sigs}} if ($do_dnssec); $rcode = "NOERROR"; } else { push @auth, $zone[$no]->{soa}; if ($do_dnssec) { push @auth, @{$zone[$no]->{soa_sigs}}; $nsec = &generate_rev_nsec($short, $dom, $zone[$no]->{hostdigits}); if ($nsec ne "") { $nsec = Net::DNS::RR->new($nsec); foreach my $private (@{$zone[$no]->{zsk_private}}) { push @auth, $nsec, create Net::DNS::RR::RRSIG([$nsec], $private); } } push @auth, $zone[$no]->{apex_nsec}, @{$zone[$no]->{apex_nsec_sigs}};; } $rcode = "NOERROR"; } } else { $rcode = "NXDOMAIN"; push @auth, $zone[$no]->{soa}; if ($do_dnssec) { push @auth, @{$zone[$no]->{soa_sigs}}, $zone[$no]->{apex_nsec}, @{$zone[$no]->{apex_nsec_sigs}}; $nsec = &generate_rev_nsec($short, $dom, $zone[$no]->{hostdigits}); if ($nsec ne "") { $nsec = Net::DNS::RR->new($nsec); foreach my $private (@{$zone[$no]->{zsk_private}}) { push @auth, $nsec, create Net::DNS::RR::RRSIG([$nsec],$private); } } } } last; } } } elsif ($qnames =~ /^(.*)\.$fwd_dom\.?$/i) { $short = $1; $addr = &host2addr($qname); if ($addr ne '') { if ($qtype eq 'AAAA') { $rr = Net::DNS::RR->new("$qname $ttl $qclass $qtype $addr"); push @ans, $rr; if ($do_dnssec) { foreach my $private (@{$zone[0]->{zsk_private}}) { push @ans, create Net::DNS::RR::RRSIG([$rr],$private); } } push @auth, @{$zone[0]->{ns}}; push @auth, @{$zone[0]->{ns_sigs}} if ($do_dnssec); $rcode = "NOERROR"; } elsif ($qtype eq 'NSEC' && $do_dnssec) { $nsec = &generate_fwd_nsec($short,$fwd_dom); if ($nsec ne '') { my $nsecRR = Net::DNS::RR->new($nsec); push @auth, $nsecRR; foreach my $private (@{$zone[0]->{zsk_pr ivate}}) { push @auth, create Net::DNS::RR::RRSIG([$nsecRR],$private); } } } else { # Generate existing NSEC RR push @auth, $zone[0]->{soa}; if ($do_dnssec) { push @auth, @{$zone[0]->{soa_sigs}}; $nsec = &generate_fwd_nsec($short,$fwd_dom); if ($nsec ne '') { my $nsecRR = Net::DNS::RR->new($nsec); push @auth, $nsecRR; foreach my $private (@{$zone[0]->{zsk_private}}) { push @auth, create Net::DNS::RR::RRSIG([$nsecRR],$private); } } } $rcode = "NOERROR"; } } else { push @auth, $zone[0]->{soa}; if ($do_dnssec) { push @auth, $zone[0]->{apex_nsec}, @{$zone[0]->{apex_nsec_sigs}}, @{$zone[0]->{soa_sigs}}; $nsec = &generate_fwd_nsec($short, $fwd_dom); if ($nsec ne '') { my $nsecRR = Net::DNS::RR->new($nsec); foreach my $private (@{$zone[0]->{zsk_private}}) { push @auth, $nsecRR, create Net::DNS::RR::RRSIG([$nsecRR],$private); } } } $rcode = "NXDOMAIN"; } } elsif ($qnames eq $fwd_dom) { if ($qtype eq "NS") { push @ans, @{$zone[0]->{ns}}; push @ans, @{$zone[0]->{ns_sigs}} if ($do_dnssec); } elsif ($qtype eq "SOA") { push @ans, $zone[0]->{soa}; push @ans, @{$zone[0]->{soa_sigs}} if ($do_dnssec); } elsif ($qtype eq "DNSKEY" && $do_dnssec) { push @ans, @{$zone[0]->{keys}}, @{$zone[0]->{key_sigs}}; } elsif ($qtype eq "NSEC" && $do_dnssec) { push @ans, $zone[0]->{apex_nsec}, @{$zone[0]->{apex_nsec_sigs}}; } else { push @auth, $zone[0]->{soa}; push @auth, @{$zone[0]->{soa_sigs}}, $zone[0]->{apex_nsec}, @{$zone[0]->{apex_nsec_sigs}} if ($do_dnssec); } $rcode = "NOERROR"; } else { $rcode = "REFUSED"; } if ($debug) { print "Return RCODE=$rcode\n"; print "Answer:\n"; for my $a (@ans) { $a->print; }; print "Authority:\n"; for my $a (@auth) { $a->print; }; print "Additional:\n"; for my $a (@add) { $a->print; }; } return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); } =head1 NAME Auto-generating IPv6 Reverse DNS server with DNSSEC online signing =head1 DESCRIPTION v6rev.pl is a DNS server which acts a master of specified IPv6 reverse zone and its forward zone. It support DNSSEC online signing. =head1 USAGE v6rev.pl requires one argument, a configuration file path. =head2 configuration file It contains colon sparated field name and field value. The value field may contain multiple value separated by comma. A line starts with '#', ';', ' ' and TAB character is treated as a comment. server_address: 127.0.0.1, ::1 # DNS server IP address server_port: 53 # DNS server port number pid_file: /var/run/v6rev.pid # process ID file reconfig_interval: 3600 # The DNS server reloads the config file periodically. reverse_domainname: 6.0.0.0.2.3.1.0.0.0.2.0.1.0.0.2.ip6.arpa # Reverse zone name, multiple domainnames are allowed forward_domainname: user.dnslab.jp # Forward zone name keyfile_dir: . # The directory which the DNSSEC key files are put. # Generate DNSSEC keypair file using BIND 9's dnssec-keygen or ldns-keygen. # BIND 9.7's dnssec-keygen requires -C option. # This program support private key format v1.2 # because Net::DNS::SEC::Private does not support v1.3. ttl: 3600 # TTL nsname: v6rev.dnslab.jp, v6rev2.dnslab.jp # DNS server names. They must be out-bailiwick. enable_dnssec: 1 # Enable DNSSEC or not querylog: 1 # Enable querylog to stdout static_ptr: REVERSE_DOMAIN_FQDN HOSTNAME_FQDN # Define fixed reverse hostname. # For example, "static_ptr: 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa rev.example.jp" # Multiple definitions are allowed. # Forward mapping is not generated. Reverse only. use_privdrop: uid or username (Default: empty) # Drop root privilege after opening port 53. # Requires "Privileges::Drop" # (If you don't use this function, you don't need the module.) # (If you use this function and DNSSEC, DNSSEC key files must be readable # by the new privilege.) =head1 Limitations This program runs in the foreground and outputs messages to STDOUT and STDERR. Some wrapper script may be required. =head1 Author Kazunori Fujiwara =head1 Copyright and License Copyright(c) 2009,2010 Japan Registry Services Co., Ltd. All rights reserved. By using this file, you agree to the terms and conditions set forth bellow. LICENSE TERMS AND CONDITIONS The following License Terms and Conditions apply, unless a different license is obtained from Japan Registry Services Co., Ltd. ("JPRS"), a Japanese corporation, Chiyoda First Bldg. East 13F, 3-8-1 Nishi-Kanda, Chiyoda-ku, Tokyo 101-0065, Japan. 1. Use, Modification and Redistribution (including distribution of any modified or derived work) in source and/or binary forms is permitted under this License Terms and Conditions. 2. Redistribution of source code must retain the copyright notices as they appear in each source code file, this License Terms and Conditions. 3. Redistribution in binary form must reproduce the Copyright Notice, this License Terms and Conditions, in the documentation and/or other materials provided with the distribution. For the purposes of binary distribution the "Copyright Notice" refers to the following language: "Copyright(c) 2007,2008 Japan Registry Services Co., Ltd. All rights reserved." 4. The name of JPRS may not be used to endorse or promote products derived from this Software without specific prior written approval of JPRS. 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPRS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPRS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. =cut