Total Pageviews

Thursday, 19 October 2017

在debian系服务器上安装MyDNS

必須先有一個資料庫(MySQL, PostgreSQL),並且正確設定帳號密碼。並且安裝 MySQL CLient Library (套件名稱類似:libmysqlclient16,搜尋方式 apt-cache search libmysqlclient )
安裝步驟:

cd /tmp
wget http://mydns.bboy.net/download/mydns-1.1.0.tar.gz
tar xvfz mydns-1.1.0.tar.gz

下載原始檔,存到 /tmp 之後解壓縮。

cd mydns-1.1.0/
./configure
make
make install

切換到目錄,並且編譯,預設使用 MySQL ,如果 ./configure –without-mysql 代表使用 PostgreSQL 。編譯完成後,會有提示如下:
  ###  mydns version 1.1.0 installed!
  ###
  ###  See the file QUICKSTART if you are in a hurry.
  ###  Otherwise, consult the manual (in doc/).
  ###
  ###  The MyDNS server program was installed as
  ###  /usr/local/sbin/mydns
  ###
  ###  Your configuration file should be installed as
  ###  /etc/mydns.conf
  ###  (You can auto-create it with "make conf")
  ###
編輯 /etc/mydns.conf ,裡面可以修改資料庫的連線設定,以及執行 MyDNS 的使用者和群組(可設定為 nobody/nogroup)。然後利用 mydns 自己的指令新增資料表:

mydns --create-tables | mysql -u root -p dbname

dbname 是您的資料庫的名稱,這個指令會建立 soa 和 rr 兩個資料表。
接著在資料庫中修改欄位屬性:

ALTER TABLE soa ADD COLUMN active ENUM('Y','N') NOT NULL;
ALTER TABLE soa ADD INDEX (active);
ALTER TABLE soa ADD COLUMN xfer CHAR(255) NOT NULL;

然後在 /etc/init.d 裡面建立一個 shell script
Shell

#! /bin/sh
# mydns Start the MyDNS server
# Author: Falko Timme <ft@falkotimme.com>.
set -e PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=mydns
DAEMON=/usr/local/sbin/$NAME
DESC="MyDNS Server"
SCRIPTNAME=/etc/init.d/$NAME
# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0
case "$1" in
start)
echo -n "Starting $DESC: $NAME"
$DAEMON --background
echo "."
;;
stop)
echo "Stopping $DESC: $NAME."
kill -9 `pidof $NAME` &> /dev/null
;;
restart)
echo "Restarting $DESC: $NAME."
$0 stop && sleep 1
$0 start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
exit 1
;;
esac
exit 0
執行 /etc/init.d/mydns start 看看能不能跑起來,沒有問題的話,讓服務開機自動啟動:

update-rc.d mydns defaults 21 22

接著複製系統裡面內建的管理介面到 www 目錄下:

cp /tmp/mydns-1.0.0/contrib/admin.php /var/www

接著修改 admin.php ,修改資料庫連線設定。如果把 $auto_update_serial 和 $auto_update_ptr 設定為 1 ,系統會在修改資料的時候,自動增加數值。
參考資料:Running A MySQL-Based DNS Server: MyDNS
------------

Here is a working idea of MyDNS dynamic DNS updating. It contains of two parts: client & server.
Prerequisites
  1. you have to alter you ddns_soa MySQL table and add varchar(32) field named ‘ddns_auth’
  2. you need to insert some password there in MD5 format
Part #1
Server looks like a combination of Apache (or NGINX) with SSL access to a script which will change our NS info. Here goes cun-n-paste Perl script (let’s name it mydns_update.pl) code:

#!/usr/bin/perl -w use CGI; use CGI::Carp qw(warningsToBrowser fatalsToBrowser); $mysql_db = 'mydns_db'; $mysql_user = 'mydns_update'; $mysql_pass = 'mydns_pass'; $mysql_soa_table = 'dns_soa'; $mysql_rr_table = 'dns_rr'; $query = new CGI; ## SET DEFAULT VALUES ## DO NOT CHANGE EM ## # # $origin = 0; $ddns_auth = 0; $data = 0; $name = 0; $ttl = 0; $zine_id = 0; $collected = 0; # # ############################################ print "Content-type: text/plain\n\n"; foreach $field (($query->param)) { foreach $value ($query->param($field)) { #print "$field: $value\n"; if (!$origin && $field eq 'origin') { $origin = $value; $collected++; } if (!$ddns_auth && $field eq 'ddns_auth') { $ddns_auth = $value; $collected++; } if (!$data && $field eq 'data') { $data = $value; $collected++; } if (!$name && $field eq 'name') { $name = $value; $collected++; } if (!$ttl && $field eq 'ttl') { $ttl = $value; $collected++; } } } ## $collected should be equal to value of arguments passed to this CGI script if ($collected == 5) { use DBI(); use Digest::MD5 qw(md5_hex); $dbh = DBI->connect("DBI:mysql:database=$mysql_db;host=localhost", $mysql_user, $mysql_pass, {'RaiseError' => 1}); $query = "SELECT id FROM $mysql_soa_table WHERE origin = '$origin' AND ddns_auth = '".md5_hex($ddns_auth)."' LIMIT 1"; #print "$query\n"; $sth = $dbh->prepare($query); $sth->execute(); if ($sth->rows) { $ref = $sth->fetchrow_hashref(); $zone_id = $ref->{'id'}; #print "-->$zone_id<--\n"; if ($zone_id) { print "+OK (zone)\n"; } else { print "+ERR (zone)\n"; } } $sth->finish(); if ($zone_id) { $query = "UPDATE $mysql_rr_table SET data = '$data', ttl = '$ttl', serial = (serial + 1), stamp = NOW() WHERE zone = '$zone_id' AND name = '$name' AND type = 'A' LIMIT 1"; $sth = $dbh->prepare($query); $sth->execute(); $numRows = $sth->rows; if ($numRows) { print "+OK (data)\n"; } else { print "+ERR (data)\n"; } $sth->finish(); $query = "UPDATE $mysql_soa_table SET serial = (serial + 1) WHERE id = '$zone_id' AND origin = '$origin' AND ddns_auth = '".md5_hex($ddns_auth)."' LIMIT 1"; $sth = $dbh->prepare($query); $sth->execute(); $numRows = $sth->rows; if ($numRows) { print "+OK (serial)\n"; } else { print "+ERR (serial)\n"; } $sth->finish(); } $dbh->disconnect(); } 

Part #2
Client looks like a web client passing some values to your script. You can simply type a web address (for ex.: https://yourdomain.com/cgi-bin/mydns_update.pl?origin=…&ddns_auth=…&name=…&data=…&ttl=…) and mydns_update.pl will update your database.
I’m using home fileserver as a gateway. And from time to time I need to fetch some useful doc’s from it being somewhere far from home. So I need my gateway to update it’s IP if connection was dropped or it was changed somehow. Here goes simple web client:

 #!/usr/bin/perl ############################################################# my $origin = 'some.origin.com.'; my $ddns_auth = 'ddns_auth_field_password'; my $name = 'my_home_file_server_gw'; my $data = get_def_gw(); my $ttl = 600; my $ns2query = '1.2.3.4'; my $ip_from_ns = get_ip_from_ns("${name}.${origin}", $ns2query); my $url = sprintf('https://yourdomain.com/cgi-bin/mydns_update.pl?origin=%s&ddns_auth=%s&name=%s&data=%s&ttl=%s', $origin, $ddns_auth, $name, $data, $ttl); #print $url; exit; update_dns($url) if ($ip_from_ns ne $data); ############################################################# sub update_dns { use LWP::UserAgent; my $ua = new LWP::UserAgent; my $req = new HTTP::Request('GET', $_[0]); my $res = $ua->request($req); if ($res->code != 200) { print $res->code."\n"; print $res->content_type."\n"; print $res->content; } } sub get_def_gw { my $ip = '0.0.0.0'; if (open(PROC, '/bin/netstat -rn | egrep \'^0.0.0.0\' |')) { $in = ; #print $in; $in =~ s/\s+/ /g; @in_ary = split(' ', $in); if ($in_ary[@in_ary-1] =~ /ppp/i) { $ip = get_if_ip($in_ary[@in_ary-1]); } close(PROC); } return $ip; } sub get_ip_from_ns { local $query = $_[0]; local $ns = $_[1]; if (open(PROC, "/usr/bin/host $query $ns |")) { while ($in = ) { chomp($in); $in =~ s/(^\s+|\s+$)//; #print "In: $in\n"; if ($in =~ /^$query/i && $in =~ /(\d+\.\d+\.\d+\.\d+)/) { return $1; } } close(PROC); } return '0.0.0.0'; } 

So let’s explain how it works. As you see, params come to the server script (mydns_update.pl) via GET request and are counted. If you’ve passed everything properly, it will make an updating request to MySQL. You have to pass 5 params: $origin (your domain, for.ex.: mydomain.com.), $ddns_auth (your password in clear-text format), $name (your subdomain, for.ex.: www), $data (an IP you want to be resolved via www.somedomain.com), $ttl (time to live of your subdomain). My script works on Linux, so it have to parse an IP address of default gateway interface. At my home it usually ‘ppp’. Then it compares IP from NS ($ns2query) and current ‘ppp’ interface IP and make an update if they differs.
 ------------------

採用的是 mydns-ng 這套 dns 軟體來管理…
顧名思義,MyDNS-ng 就是用 MySQL 當 Backend 的 Dns Server …
==安裝==
在 Ubuntu 的Repo裡面似乎是沒有 MyDNS… 至少我用 apt-cache search mydns 是找不到的…
既然如此.就只好下載相關的套件自己編譯囉…
首先先確定系統有安裝 build-essential 跟 libmysqlclient-dev 沒有的話請 apt-get install 安裝一下囉!~…
接著跑下面的 script …
cd /tmp
wget http://heanet.dl.sourceforge.net/sourceforge/mydns-ng/mydns-1.2.8.27.tar.gz
tar xvfz mydns-1.2.8.27.tar.gz
cd mydns-1.2.8
./configure
make
make install

安裝完成後, 可以用mydns -c /etc/mydns.conf -b 啟動在背景….
而設定檔 mydns.conf 則已經由 ispconfig 在 /etc/ 產生了…
接著就可以用 ispconfig 的後台進行管理 dns 的動作囉.

from  http://blog.darkhero.net/archives/416

No comments:

Post a Comment