Wednesday, April 10, 2019

Membuat Server Dynamic DNS Dan Script Update Pada Mikrotik

Sebagian besar ISP broadband saat ini memberikan IP address dinamik kepada pelanggannya dan kita diharuskan untuk membayar lebih mahal untuk bisa mendapatkan ip statik. Padahal seperti kita ketahui, sangat penting bagi kita untuk mengetahui IP address kita untuk berbagai keperluan seperti melakukan remote maupun web server atau mail server. Hal ini tidak akan menjadi permasalahan manakala kita memiliki IP address statik atau tetap, masalah akan muncul saat IP address tersebut selalu berganti setiap kali koneksi mengalami redial. Tidak mungkin bagi kita mengamati setiap saat ip kita terutama saat kita tidak berada dalam jaringan “rumah” kita.


Sebagai alternatif mengamati perubahan IP address dinamik tersebut, kita membutuhkan service dynamic DNS dimana layanan ini  berfungsi untuk mengupdate IP address terbaru dan menterjemahkan menjadi sebuah alamat host berupa domain atau subdomain. Selanjutnya kita hanya perlu menghapal alamat domain atau subdomain tersebut yang relatif jauh lebih mudah.


Bagi anda yang sudah tidak asing dengan layanan dynamic DNS ini, pasti anda telah mengenal dyndns, no-ip, changeip, afraid & ddns² yang lainnya. Disini saya akan membahas bagaimana membuat sendiri Server Dynamic DNS. Keuntungannya adalah kita bisa menggunakan hostname dengan domain kita sendiri serta berbagai kustomisasi yang jika kita menggunakan layanan free ddns tidak bisa kita dapatkan.


Ok. terlalu panjang pengantar saya. Bahan yang kita perlukan disini adalah :

  1. koneksi internet dengan IP Address dinamik.
  2. Sebuah Server yang memiliki koeneksi internet dengan IP Address statik (disini saya menggunakan VPS) yang telah di install BIND dan WEB SERVER
  3. Sebuah domain yang kita host pada server pada point no. 2 diatas. (contoh disini : domain.com)

Pastikan server DNS atau service BIND anda telah berjalan dengan baik, artinya domain anda telah menggunakan server tersebut sebagai hostnya dimana NS utamanya mengarah pada IP server yang akan digunakan.

Langkah pertama buat dulu key untuk dynamic host yang akan digunakan

dnssec-keygen -a HMAC-MD5 -b 512 -n USER dynhost.domain.com.


Keyword USER pada perintah diatas adalah perintah mutlak dan anda tidak perlu merubahnya. Maka akan terbuat dua buah file dengan nama Kdynhost.domain.com.*.key dan Kdynhost.domain.com.*.private. Selanjutnya Copy key yang dihasilkan ke folder yang sesuai untuk mempermudah kontrol.

mkdir /home/user/dyndns
cp Kdynhost* /home/user/dyndns

Setelah itu masukkan key yang dibuat tadi kedalam zona DNS yang telah ada. Saya menggunakan ubuntu sehingga fila yang perlu di edit adalah /etc/bind/named.conf.local

key dynhost.domain.com. {
algorithm HMAC-MD5;
secret "paste key dari file Kdynhost.domain.com.*.private yang dibuat tadi==";
};

zone "domain.com" {
type master;
file "/var/lib/bind/domain.com.hosts";
allow-transfer {
127.0.0.1;
localnets;
};
update-policy {
grant dynhost.domain.com. name dynhost.domain.com. A;
};
};

Dengan menambahkan script diatas, maka isi dari file /var/lib/bind/domain.com.hosts akan berubah secara dinamik setiap kali kita melakukan perintah update khususnya untuk hostname dynhost.domain.com.

Lakukan restart BIND.

Service bind9 restart

Jika setelah ini anda perlu untuk merubah zona domain.com maka anda harus melakukan freeze agar tidak terjadi konflik saat dilakukan perubahan karena bind dalam kondisi berjalan.

rndc freeze domain.com
nano /var/lib/bind/domain.com.hosts
rndc thaw domain.com

Sampai disini anda telah memiliki dynamic host yang bisa anda update “A record”-nya setiap saat dengan perintah yang dijalankan menggunakan script http/https. Untuk scriptnya, saya menggunakan script CGI. Jadi pastikan anda telah menginstall paket libcgi-pm-perl.

apt-get install libcgi-pm-perl
Kemudian Buat sebuah file dan simpan pada folder dengan nama /home/user/dyndns/cgi-bin/update

nano /home/user/dyndns/cgi-bin/update
Pastekan code script berikut dan edit sesuai dengan yang anda butuhkan

#!/usr/bin/perl
# (c)2013 Max Baker 
# Perl Artistic License 2.0 http://opensource.org/licenses/artistic-license-2.0
#
# This is a dyndns server replacement CGI script that calls bind's nsupdate
# Reference : http://dyn.com/support/developers/api/perform-update/
 
use strict;
use CGI;
 
use vars qw/$q $hostname $myip $wildcard $mx $backmx $offline $nsupdate 
        $remote_user $user $dir %hosts /;
 
$dir = '/home/user/dyndns';
$nsupdate = '/usr/bin/nsupdate';
 
%hosts = (
# Host                    user   zone         key file
'dynhost.domain.com' => [ 'saya','domain.com','Kdynhost.domain.com.+157+28821.key' ],
         );
 
$q = CGI->new;
 
$hostname = $q->param('hostname');
$myip     = $q->param('myip');
$user     = $q->remote_user;
#$offline = $q->param('offline');
#$wildcard= $q->param('wildcard');
#$mx      = $q->param('mx');
#$backmx  = $q->param('backmx');
 
print $q->header();
 
# Check that we have the auth set and are sending non-blank stuff
unless (not_blank($hostname) and not_blank($myip) and not_blank($user)) {
        apachelog("not_blank");
        print "badauth\n";
        exit;
}
 
# Handle Auto-Discover of IP
if ($myip eq 'auto') {
    $myip = $q->remote_addr;
}
 
# Check the IP address makes sense
unless ($myip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) {
        apachelog("bad_ip");
        print "badauth\n";
        exit;
}
# Multiple hosts can be given, separated by a comma
my @hosts = split(',',$hostname);
if (scalar @hosts > 10 ) {
        apachelog("too many");
        print "numhost\n";
        exit;
}
 
foreach my $host (@hosts) {
        # Check if it's a host we allow
        unless (defined $hosts{$host}) {
                apachelog("Bad host");
                print "notfqdn\n";
                last;
        }
        # Check that the user has access to this host
        unless ($hosts{$host}->[0] eq $user) {
                apachelog("Access Denied");
                print "nohost\n";
                last;
        }
        my $key = sprintf("%s/%s",$dir,$hosts{$host}->[2]);
        my $zone = $hosts{$host}->[1];
 
        unless (-r $key) {
                die "Key file $key missing.";
        }
 
        # Perform the update
        unless (open(N,"|$nsupdate -k $key 1>/dev/null")) {
                apachelog("nsupdate failed");
                print "dnserr\n";
                next;
        }
        # There should be no space between the lesser-than signs here, wordpress is adding it, remove.
        print N < < "end_update";
server $zone
zone $zone
update delete $host. A
update add $host. 86400 A $myip
show
send
end_update
        # Should have exited, otherwise we have a problem
        unless (close N) {
                apachelog("nsupdate failed on close");
                print "dnserr\n";
                next;
        }
        print "good\n";
}
 
exit;
 
sub not_blank {
        my $val = $_[0];
        return 1 if defined $val and $val !~ /^\s*$/;
        return 0;
}
 
sub apachelog {
        my $msg = join(' ',@_);
        { no warnings; 
        warn "dyndns : $user $hostname = $myip $msg\n";
        }
}
chmod 755 pada file script tersebut agar bisa di eksekusi

Kemudian buat virtualhost untuk domain.com pada apache untuk melakukan eksekusi script cgi diatas pada browser atau tambahkan pada virtualhost yang sudah ada untuk memberikan permission pada eksekusi file cgi script

ScriptAlias /cgi-bin/ /home/user/dyndns/cgi-bin/
<Directory "/home/user/dyndns/cgi-bin/">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all


<location "/cgi-bin">
AuthName "DDNS@Admin.My.Id"
AuthType Basic
AuthUserFile /home/user/dyndns/.htpasswd
require valid-user


Buat file .htpasswd untuk memasukkan username dan password sebagai autentikasi saat eksekusi file cgi script pada browser maupun script


cd /home/user/dyndns
htpasswd -c .htpasswd saya
Restart Apache

service apache2 restart

Sekarang anda sudah bisa melakukan update melalui browser anda untuk pengetesan

http://domain.com/cgi-bin/update?hostname=dynhost.domain.com&myip=123.123.123.123

Masukkan username dan password yang anda buat tadi. Jika tidak terdapat kesalahan, maka pada browser anda akan ada jawaban

good

Selanjutnya silahkan anda cek record zona domain.com pada server anda dengan perintah dig

dig dynhost.domain.com

maka pada hasil dig akan nampak baris sebagai berikut :

;; ANSWER SECTION:
dynamichost.yourdomain.com.      86400   IN      A       123.123.123.123

Sampai disini script anda sudah berjalan dengan benar, selanjutnya tinggal anda buat script dan scheduler pada router mikrotik untuk update ip secara otomatis
Script update ddns mikrotik (tested on ROS 6.x) :

:global ddnsuser "saya"
:global ddnspass "passwordsaya"
:global iface "pppoe-out1"
:global ddnshost dynhost.domain.com
:global ipddns [:resolve $ddnshost];
:global ipfresh [ /ip address get [/ip address find interface=$iface ] address ]
:if ([ :typeof $ipfresh ] = nil ) do={
   :log info ("myDDNS: $iface tidak memiliki IP Address.")
} else={
   :for i from=( [:len $ipfresh] - 1) to=0 do={ 
      :if ( [:pick $ipfresh $i] = "/") do={ 
    :set ipfresh [:pick $ipfresh 0 $i];
      } 
}

:if ($ipddns != $ipfresh) do={
:log info ("myDDNS: IP $ddnshost = $ipddns")
:log info ("myDDNS: IP-Fresh $iface = $ipfresh")
:log info "myDDNS: Pembaharuan diperlukan, Meminta Update IP ke myDDNS...!"
:global str "/cgi-bin/update\?hostname=$ddnshost&myip=$ipfresh"
/tool fetch address=domain.com src-path=$str mode=http user=$ddnsuser \
password=$ddnspass dst-path=("/myDDNS.".$ddnshost)
:delay 1
:global str [/file find name="myDDNS.$ddnshost"];
/file remove $str
:global ipddns $ipfresh
:log info "myDDNS: IP $iface berhasil diperbaharui menjadi $ipfresh!"
 }
}
Buat scheduler agar bisa di eksekusi setiap menit.

Mohon koreksi ya jika ada yang kurang benar…

Sumber: https://ndra16.my.id/2014/02/membuat-server-dynamic-dns-dan-script-update-pada-mikrotik/