Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

I'm using, but recently they got more obnoxious with their (free!) service, and being a cheapskate who doesn't want to be annoyed, I set up my own dynamic DNS update with my vhost at Hosteurope. I have set up as the DNS server for the zone with the Hosteurope DNS and run my own DNS server on my vhost to serve entries for * The key setup is done according to the many dynamic DNS articles.

The below program reads the external IP address from my UPnP enabled gateway, a FritzBox. It then sends the signed DNS update packet to my DNS server.

The setup is not particularly secure, as the key can be used to update any dynamic IP address in the zone. But for my purpose of having one name map to a dynamic IP address, that's just enough.

#!/usr/bin/perl -w use strict; use vars qw($VERSION); use Net::UPnP::ControlPoint; use Net::UPnP::GW::Gateway; use Net::DNS '0.74'; # Earlier versions had bugs in the TSIG handling use Getopt::Long; use Pod::Usage; $VERSION= '0.01'; GetOptions( 'v|verbose' => \my $verbose, 'k|key:s' => \my $key, 'n|key-name:s' => \my $key_name, 'f|key-file:s' => \my $keyfile, 's|server:s' => \my $server, 'h|hostname:s' => \my $hostname, 'z|zone:s' => \my $zone, 't|ttl:s' => \my $ttl, 'force' => \my $force, 'help' => \my $help, 'man' => \my $man, ) or pod2usage(2); pod2usage(1) if $help; pod2usage(-verbose => 2) if $man; pod2usage("$0: No hostname to update." unless $hostname; sub status { print "@_\n" if $verbose; }; $ttl||= 600; if( ! $zone) { ($zone=$hostname)=~ s!^\w+\.!!; status("Assuming DNS zone is $zone"); }; my $upnp= Net::UPnP::ControlPoint->new(); my $current_address= ''; my $resolver= Net::DNS::Resolver->new(); # Find the relevant nameserver for the zone if( ! $server ) { my $query= $resolver->search($zone,'NS'); if( $query ) { for my $rr (grep { 'NS' eq $_->type } ($query->answer)) { $server= $rr->nsdname; status "Nameserver for zone '$zone' is '$server'."; }; } else { die "Couldn't find a nameserver for zone '$zone'.\n"; }; }; $resolver->nameservers($server); status "Looking up IP for '$hostname'"; my $query= $resolver->search($hostname); if(! $query) { my $err= $resolver->errorstring(); if( 'NXDOMAIN' ne $err ) { die "Lookup of '$hostname' failed: $err\n"; } else { status "Hostname '$hostname' was not found."; }; } else { for my $rr (grep { 'A' eq $_->type } ($query->answer)) { $current_address= $rr->address; status "Hostname '$hostname' resolves to IP address '$current_ +address'"; }; }; status "Searching local network for UPnP-enabled gateways"; my @devices= $upnp->search( st => 'urn:schemas-upnp-org:device:Interne +tGatewayDevice:1', mx => 3 ); foreach my $dev (@devices) { my $type= $dev->getdevicetype; my $gw= Net::UPnP::GW::Gateway->new; $gw->setdevice( $dev ); my $ip_address= $gw->getexternalipaddress; status sprintf "Gateway '%s' has IP address %s", $dev->getfriendly +name, $ip_address; # XXX Do a name lookup and do an early exit if we don't need to up +date if( $current_address eq $ip_address ) { if( $force ) { status "Current IP address and address in DNS are identica +l, but --force is in effect"; } else { status "Current IP address and address in DNS are identica +l, skipping update"; exit 0; }; }; my $update = Net::DNS::Update->new($zone); $update->push( update => rr_del("$hostname. A") ); $update->push( update => rr_add("$hostname. 600 A $ip_address") ); if( $keyfile ) { status "Signing from key file $keyfile"; $update->sign_tsig( $keyfile ); } else { status "Signing from command line with key named $key_name"; $update->sign_tsig( $key_name, $key ); }; status "Updating IP for $hostname on $server to $ip_address"; status $update->string if $verbose; my $reply= $resolver->send( $update ); if( $reply ) { if( 'NOERROR' eq $reply->header->rcode) { status "Success"; } else { die "Update failed: " . $reply->header->rcode . "\n"; }; } else { die "Update failed: " . $resolver->errorstring . "\n"; }; }; __END__ =head1 NAME update-wan-ip - dynamic DNS update from an UPnP enabled gateway =head1 SYNOPSIS update-wan-ip [options] update-wan-ip -h HOSTNAME -k KEYFILE update-wan-ip -h -k /root/Kdyn-example-com+157+ +12345.key Options: --hostname, -h --key-file, -f --key, -k --key-name, -n --force --verbose --help --man =head1 OPTIONS =over 4 =item B<--hostname>, B<-h> --hostname Set the hostname you want to update. =item B<--key-file>, B<-k> --key-file /root/Kdyn-example-com+157+12345.key Name of the keyfile that contains the key for the DNS updates. Note that the filename also carries the name of the DNS key. This is i +mportant and must match the name of the DNS key in your DNS server. =item B<--key-name>, B<-n> --key-name dyn-example-com Name of the key that is used for the DNS update. If you don't use a keyfile, for example while testing the setup, you can specify the name of the key through this switch. This does not override a name given through a keyfile. =item B<--key>, B<-k> --key AAANN3...== The key that is used for the DNS update. If you don't use a keyfile, for example while testing the setup, you can specify the key through this switch. =back =head1 TROUBLESHOOTING Test with the C<nsupdate> command whether DNS updates work at all: nsupdate -y key-name:key server zone update add 600 A show send Check that both machines have the same time. If not, install C<ntp> on both machines. =cut

In reply to My own dynamic DNS setup by Corion

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others examining the Monastery: (4)
    As of 2017-06-26 22:54 GMT
    Find Nodes?
      Voting Booth?
      How many monitors do you use while coding?

      Results (595 votes). Check out past polls.