UNIX-системные админы любят роутеры MikrotiK, но часто провайдер не выдаёт статический IP. Сегодня я исправил эту проблему, но бесплатный DynDNS больше не работает. ;( Как и многие системные администраторы, у меня есть доступ к веб-серверу на базе Linux. Тогда я написал скрипт для MikrotiK на основе "HTTP GET" для отправки IP-адреса. Он отправляет мой внешний IP на веб-сервер, а PHP5 часть веб-сервера генерирует файл зоны, совместимый с BIND9. После этого перезагружается конфигурация BIND9 для загрузки новой зоны и отправляется уведомление на вторичный DNS. И мне больше не нужен никакой внешний сервис DDNS.
MikrotiK скрипт
```
:local sendhost "dns.mywebserver.ru";
# Zone
:local host "mydomain.net";
# Access password
:local password "passwordblablabla";
# Mikrotik external IFace
:local iface "beeline-l2tp";
# Location of PHP script in web-server home dir
:local script "/update_dns.php";
# get current IP address from DNS system
:local currentdnsaddress [ :resolve $host ];
# get Mikrotik external address
:local iptemp [ /ip address get [find interface=$iface] address ];
# cut IP without mask
:local str [:pick $iptemp 0 [:find $iptemp "/"]];
# if DNS address not equal our external
:if ($str != $currentdnsaddress) do={
:log info "Update DynamicIP needed, Sending UPDATE...!"
# make request parameters
:local str2 "$script\?hostip=$str&password=$password&host=$host";
:put $str2
# execute GET http request with parameters
/tool fetch address=$sendhost host=$sendhost src-path=$str2 mode=http keep-result=no;
} else={ :log info "DynamicIP: dont need changes"; }
```
PHP5 скрипт update_dns.php
```php
<?
//
// Author: Andrey Bykanov (adm@shodtech.net)
//
// BIND9 Dynamic IP update script
//////////////////////////////////////////////////////////// ////////////////////////////////////////////
$password="passwordblablabla";
$host="mydomain.net";
//////////////////////////////////////////////////////////// ////////////////////////////////////////////
function is_ipv4($string)
{
// The regular expression checks for any number between 0 and 255 beginning with a dot (repeated 3 times)
// followed by another number between 0 and 255 at the end. The equivalent to an IPv4 address.
return (bool) preg_match('/^(?
?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])'.'\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|[0-9])$/', $string);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////
if(isset($_GET["password"]) & isset($_GET["hostip"]) & isset($_GET["host"])) // check for all nesesery parameters is exist
{
if($_GET["password"]!=$password){echo "Неверный пароль: ".$_GET["password"]; die();} // Check password
if($_GET["host"]!=$host) {echo "Неверное имя хоста: ".$_GET["host"]; die();} // Check hostname
if(!(is_ipv4($_GET["hostip"]) & ($_SERVER["HTTP_X_REAL_IP"]==$_GET["hostip"]))){echo " Неверный IP-адрес : ".$_GET["hostip"]; die();} // Check IP address
$zone_time=(integer)(((date('H')*60)+date('i'))/15); // Calculate Zone time, one tick is allmost 15 minutes
$zone_date=date('Ymd').$zone_time; // Calculate complette zone serial eg, YearMonthDayTime
$fp = fopen('shodtech.net_zone_data.txt', 'w'); // zone file name
// Writing BIND9 Zone content
fwrite($fp, "\$ORIGIN mydomain.net. \r\n");
fwrite($fp, "\$TTL 600 ; 10 minutes \r\n");
fwrite($fp, "@ IN SOA ns.mydomain.net. adm.mydomain.net. ( \r\n");
fwrite($fp, " ".$zone_date." ; serial \r\n");
fwrite($fp, " 600 ; refresh (10 minutes) \r\n");
fwrite($fp, " 600 ; retry (10 minutes) \r\n");
fwrite($fp, " 86400 ; expire (1 day) \r\n");
fwrite($fp, " 600 ; minimum (10 minutes) \r\n");
fwrite($fp, " ) \r\n");
fwrite($fp, " NS ns1.mywebserver.ru. \r\n");
fwrite($fp, " NS ns2.mywebserver.ru. \r\n");
fwrite($fp, " A ".$_GET["hostip"]." \r\n"); // Put Mikrotik external IP address
fwrite($fp, "ftp A ".$_GET["hostip"]." \r\n"); // Put Mikrotik external IP address
fwrite($fp, "www A ".$_GET["hostip"]." \r\n"); // Put Mikrotik external IP address
fclose($fp); // Close file
exec('/usr/sbin/rndc reload'); // Reloading BIND9 config (Web-server must have permission for write to /etc/bind/rndc.key)
} else echo "Неверные параметры";
?>
```
Часть конфигурации BIND9 "mydomain.net"
```
{
type master;
file "/var/www/mydomain.net_zone_data.txt"; // Full path to zone file generated by PHP script
allow-update { none;};
allow-query {any; } ;
allow-transfer { 62.12.13.12; } ; // IP to transfer zone (Secondary DNS)
notify yes;
};
```
`.htaccess`
```
Options All -Indexes
Deny from All
<Files "update_dns.php">
Allow from All
</Files>
```
MikrotiK скрипт
```
:local sendhost "dns.mywebserver.ru";
# Zone
:local host "mydomain.net";
# Access password
:local password "passwordblablabla";
# Mikrotik external IFace
:local iface "beeline-l2tp";
# Location of PHP script in web-server home dir
:local script "/update_dns.php";
# get current IP address from DNS system
:local currentdnsaddress [ :resolve $host ];
# get Mikrotik external address
:local iptemp [ /ip address get [find interface=$iface] address ];
# cut IP without mask
:local str [:pick $iptemp 0 [:find $iptemp "/"]];
# if DNS address not equal our external
:if ($str != $currentdnsaddress) do={
:log info "Update DynamicIP needed, Sending UPDATE...!"
# make request parameters
:local str2 "$script\?hostip=$str&password=$password&host=$host";
:put $str2
# execute GET http request with parameters
/tool fetch address=$sendhost host=$sendhost src-path=$str2 mode=http keep-result=no;
} else={ :log info "DynamicIP: dont need changes"; }
```
PHP5 скрипт update_dns.php
```php
<?
//
// Author: Andrey Bykanov (adm@shodtech.net)
//
// BIND9 Dynamic IP update script
////////////////////////////////////////////////////////////
$password="passwordblablabla";
$host="mydomain.net";
////////////////////////////////////////////////////////////
function is_ipv4($string)
{
// The regular expression checks for any number between 0 and 255 beginning with a dot (repeated 3 times)
// followed by another number between 0 and 255 at the end. The equivalent to an IPv4 address.
return (bool) preg_match('/^(?
?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])'.'\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|[0-9])$/', $string);}
////////////////////////////////////////////////////////////
if(isset($_GET["password"]) & isset($_GET["hostip"]) & isset($_GET["host"])) // check for all nesesery parameters is exist
{
if($_GET["password"]!=$password){echo "Неверный пароль: ".$_GET["password"]; die();} // Check password
if($_GET["host"]!=$host) {echo "Неверное имя хоста: ".$_GET["host"]; die();} // Check hostname
if(!(is_ipv4($_GET["hostip"]) & ($_SERVER["HTTP_X_REAL_IP"]==$_GET["hostip"]))){echo " Неверный IP-адрес : ".$_GET["hostip"]; die();} // Check IP address
$zone_time=(integer)(((date('H')*60)+date('i'))/15); // Calculate Zone time, one tick is allmost 15 minutes
$zone_date=date('Ymd').$zone_time; // Calculate complette zone serial eg, YearMonthDayTime
$fp = fopen('shodtech.net_zone_data.txt', 'w'); // zone file name
// Writing BIND9 Zone content
fwrite($fp, "\$ORIGIN mydomain.net. \r\n");
fwrite($fp, "\$TTL 600 ; 10 minutes \r\n");
fwrite($fp, "@ IN SOA ns.mydomain.net. adm.mydomain.net. ( \r\n");
fwrite($fp, " ".$zone_date." ; serial \r\n");
fwrite($fp, " 600 ; refresh (10 minutes) \r\n");
fwrite($fp, " 600 ; retry (10 minutes) \r\n");
fwrite($fp, " 86400 ; expire (1 day) \r\n");
fwrite($fp, " 600 ; minimum (10 minutes) \r\n");
fwrite($fp, " ) \r\n");
fwrite($fp, " NS ns1.mywebserver.ru. \r\n");
fwrite($fp, " NS ns2.mywebserver.ru. \r\n");
fwrite($fp, " A ".$_GET["hostip"]." \r\n"); // Put Mikrotik external IP address
fwrite($fp, "ftp A ".$_GET["hostip"]." \r\n"); // Put Mikrotik external IP address
fwrite($fp, "www A ".$_GET["hostip"]." \r\n"); // Put Mikrotik external IP address
fclose($fp); // Close file
exec('/usr/sbin/rndc reload'); // Reloading BIND9 config (Web-server must have permission for write to /etc/bind/rndc.key)
} else echo "Неверные параметры";
?>
```
Часть конфигурации BIND9 "mydomain.net"
```
{
type master;
file "/var/www/mydomain.net_zone_data.txt"; // Full path to zone file generated by PHP script
allow-update { none;};
allow-query {any; } ;
allow-transfer { 62.12.13.12; } ; // IP to transfer zone (Secondary DNS)
notify yes;
};
```
`.htaccess`
```
Options All -Indexes
Deny from All
<Files "update_dns.php">
Allow from All
</Files>
```
