Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: My own dynamic DNS setup

by Theodore (Monk)
on Apr 11, 2014 at 13:01 UTC ( #1081958=note: print w/replies, xml ) Need Help??


in reply to My own dynamic DNS setup

And here is my own perverted pair of scripts, with IPv6/AAAA support :-)

Client script:

#!/usr/bin/perl use strict; if (($ARGV[0] ne "v4") and ($ARGV[0] ne "v6")) { print "Usage: $0 v4|v6\n"; exit 1; }; # Check for IPV6 requ. my $ipver = "v4"; if ($ARGV[0] eq "v6") { require Net::INET6Glue::INET_is_INET6; $ipver = "v6"; }; my $previp = ''; # DNS record types: my %drts = ( 'v4' => 'A', 'v6' => 'AAAA', ); # Checkip url my $checkurl = 'http://www.example.com.gr/myip'; # Updateip url my $updateurl = 'http://www.example.com/ddnsset.pl?'; # FQDN to set: my $fqdn = 'myhost'; # History filenames: my %iphist = ( 'v4' => '/tmp/dynipsethistv4.txt', 'v6' => '/tmp/dynipsethistv6.txt', ); # Load history: if (-e $iphist{$ipver}) { open (HI, "<", $iphist{$ipver}) or die "Failed to open " . $iphist +{$ipver} . " for reading: $!.\n"; $previp = <HI>; close HI; }; # Create a user agent object use LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->agent("dynipset/0.1 "); # Create a request my $req = HTTP::Request->new(GET => $checkurl); # Pass request to the user agent and get a response back my $res = $ua->request($req); # Check the outcome of the response if ($res->is_success) { my $newip = $res->content; #print "DEBUG: My new IP is $newip ($ipver) \n"; if ($previp eq $newip) { # Do nothing. #print "DEBUG: IP not changed.\n"; exit 0; } else { # Set ip: my $dbrec = "$fqdn|" . $drts{$ipver} . "|$newip"; my $rc = &setDNS($dbrec); if ($rc) { print "SET: $fqdn " . $drts{$ipver} . " $newip\n"; } else { print "ERROR: setDNS failed ($fqdn|$newip)!\n"; exit 1; }; # Save new ip to history: open (HI, ">", $iphist{$ipver}) or die "Failed to open " . $ip +hist{$ipver} . " for writing: $!.\n"; print HI $newip; close HI; exit 0; }; } else { print "ERROR: checkip request failed: " . $res->status_line, "\n"; exit 1; }; exit 0; sub setDNS { my ($dbrec, $rest) = @_; use Crypt::CBC; use MIME::Base64 qw(encode_base64url decode_base64url); my $cipher = Crypt::CBC->new( -key => 'a pass phrase', -cipher => 'Blowfish', -keysize => 56 ); my $ciphertext = $cipher->encrypt($dbrec); my $encoded = encode_base64url($ciphertext); #print "DEBUG: $encoded\n"; my $url = "$updateurl$encoded"; my $ua = LWP::UserAgent->new; $ua->agent("dynipset/0.1 "); # Create a request my $req = HTTP::Request->new(GET => $url); # Pass request to the user agent and get a response back my $res = $ua->request($req); if ($res->is_success) { return 1; } else { print "ERROR: updateip request failed: " . $res->status_line, +"\n"; return 0; }; };

Server script:

#!/usr/bin/perl use strict; use Net::DNS; use Paranoid::Network::IPv4 qw(:all); use Paranoid::Network::IPv6 qw(:all); use Data::Dumper; use CGI; my $zone = 'dyn.example.com'; # A zone reserved for this script +. my $dnsserver = '127.0.0.1'; # Assuming 'allow-updates {127.0.0 +.1;}' in localhost BIND. my @validnames = ('myhost', 'myhost2'); # Only these are allowed. my @validtypes = ('A', 'AAAA'); # Only these are allowed. my $query = CGI->new; my @params = $query->url_param('keywords'); my $qref = &qdecode($params[0]); my ($name, $type, $ip, $rest) = @{ $qref }; if (not grep($name, @validnames)) { print STDERR "ERROR: Invalid name: $name\n"; print $query->header('text/html','500 Internal Server Error'); print $query->start_html(-title=>''); print $query->end_html(); exit 1; }; if (not grep($type, @validtypes)) { print STDERR "ERROR: Invalid type: $type\n"; print $query->header('text/html','500 Internal Server Error'); print $query->start_html(-title=>''); print $query->end_html(); exit 1; }; if ( (($type eq 'A') and (not (($ip =~ /^@{[ IPV4REGEX ]}$/)))) or (($type eq 'AAAA') and (not (($ip =~ /^@{[ IPV6REGEX ]}$/)))) ) { print STDERR "ERROR: Invalid IP: $ip\n"; print $query->header('text/html','500 Internal Server Error'); print $query->start_html(-title=>''); print $query->end_html(); exit 1; }; my $fqn = $name . "." . $zone; my $fqdn = $name . "." . $zone . "."; my $resolver = new Net::DNS::Resolver; $resolver->nameservers($dnsserver); # Delete old record. my $update = new Net::DNS::Update($zone); $update->push( prereq => yxrrset("$fqn $type") ); $update->push( update => rr_del("$fqn $type") ); my $reply = $resolver->send($update); if ($reply) { if ( $reply->header->rcode eq 'NOERROR' ) { print STDERR "Delete old records succeeded\n"; } else { print STDERR 'Delete old records failed: ', $reply->he +ader->rcode, "\n"; } } else { print STDERR 'Delete old records failed: ', $resolver->errorst +ring, "\n"; print $query->header('text/html','500 Internal Server Error'); print $query->start_html(-title=>''); print $query->end_html(); exit 1; }; undef $reply, $update; # Add new record. $update = new Net::DNS::Update($zone); $update->push( prereq => yxdomain($zone) ); $update->push( update => rr_add("$fqdn 300 $type $ip") ); $reply = $resolver->send($update); if ($reply) { if ( $reply->header->rcode eq 'NOERROR' ) { print STDERR "Update succeeded\n"; print $query->header('text/html','204 No response'); } else { print STDERR 'Update failed: ', $reply->header->rcode, + "\n"; print $query->header('text/html','500 Internal Server Error'); print $query->start_html(-title=>''); print $query->end_html(); exit 1; } } else { print STDERR 'Update failed: ', $resolver->errorstring, "\n"; print $query->header('text/html','500 Internal Server Error'); print $query->start_html(-title=>''); print $query->end_html(); exit 1; } exit 0; sub qdecode { my ($dbrec, $rest) = @_; use Crypt::CBC; use MIME::Base64 qw(encode_base64url decode_base64url); my $cipher = Crypt::CBC->new( -key => 'a pass phrase', -cipher => 'Blowfish', -keysize => 56 ); my $decoded = decode_base64url($dbrec); my $decrypted = $cipher->decrypt($decoded); my @result = split(/\|/, $decrypted, 3); return \@result; };

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1081958]
help
Chatterbox?
[shmem]: pseudo chip?
[stevieb]: well, what happens is the Arduino 'listens' for requests r/w, and does the appropriate thing when it's interrupted based on the 'register' address sent in. It's ugly as it was my first attempt, but I've got great new ideas I'm just sitting.
[stevieb]: ...down to implement now. Here's the sketch as it currently sits
[shmem]: well I use I2C and SPI and stuff, but creating a pseudo chip looks to me like lot of indirection and memory clutter... not?
[choroba]: Are you going to use the device soon? Related to your comment about "not having much time to do a lot of coding"...
[stevieb]: sure, but I'm just learning ;) I consider it practice to get a good understanding of what goes on *after* an I2C/SPI request is made
[shmem]: ah ok. Gonna read that. but now....
shmem compiles himself into his template
[stevieb]: this is my RPi:: distribution overall automation build system physical layout. It doesn't encompass all of my RPi dists yet, ...
[stevieb]: ...but I'm getting close. I've been soldering my own PCBs to gain that experience as well, before I have my own manufactured.

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (9)
As of 2017-06-25 22:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How many monitors do you use while coding?















    Results (572 votes). Check out past polls.