еще раз о DynDNS

Обсуждаем сайт и форум.

Модератор: f0s

Аватара пользователя
andy03
проходил мимо
Сообщения: 5
Зарегистрирован: 2010-02-12 20:56:18
Откуда: Киев, Украина

еще раз о DynDNS

Непрочитанное сообщение andy03 » 2010-02-18 23:20:43

Есть идея и успешная реализация автономного (без использования сторонних сервисов)
DynDNS сервера, если кому надо расскажу и приведу примеры

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35271
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

Re: еще раз о DynDNS

Непрочитанное сообщение Alex Keda » 2010-02-19 0:09:10

расскажи
Убей их всех! Бог потом рассортирует...

Аватара пользователя
andy03
проходил мимо
Сообщения: 5
Зарегистрирован: 2010-02-12 20:56:18
Откуда: Киев, Украина

Re: еще раз о DynDNS

Непрочитанное сообщение andy03 » 2010-02-19 14:18:34

в кратце это выглядит следующим образом:
на сервере нужен настроенный софт - apach2, php, php-extensions, bind9
клиенты подключаются к апачу (на заранее подготовленную страницу) посредством curl и получают свой адрес
затем с помощью nsupdate обновляют свою запись в зоне на сервере

страница на апаче защищена с помощью htpasswd
обновления bind разрешены только владельцам TSIG ключей

проверял и тестировал на сервере freebsd 7.2 и 8.0
на клиентах (windpws xp) в шедулере выполняется jscript, который получает адрес и обновляет зону

Аватара пользователя
andy03
проходил мимо
Сообщения: 5
Зарегистрирован: 2010-02-12 20:56:18
Откуда: Киев, Украина

Re: еще раз о DynDNS

Непрочитанное сообщение andy03 » 2010-02-22 22:20:25

Иногда есть необходимость обращаться по имени клиента, а не по адресу (адреса динамические). Сейчас это частично реализовано — есть локальный домен mydomain.local удаленные точки регистрируются в локальном демене, и доступны по имени из локальной сети офиса.
Тестировалось на:
сервере freebsd 7.2 и freebsd 8.0, софт: apache 2.2, php, php-extensions (возможно не нужен), bind9;
клиентах Windows XP, софт: curl, bind9.

Настройка сервера.
В /usr/local/etc/apache22/http.conf добавим следующую секцию:

Код: Выделить всё

Alias /ipaddress "/usr/local/www/ipaddress/"
<Directory "/usr/local/www/ipaddress">
    Options Indexes
    AllowOverride All
    DirectoryIndex index.php
    Order allow,deny
    Allow from All
    AuthName "Who are you?"
    AuthType Basic
    AuthUserFile /usr/local/www/ipaddress/.htpasswd
    Require valid-user
</Directory>
Далее создадим каталог: mkdir /usr/local/www/ipaddress
И положим файл index.php, следующего содержания (взял на http://www.phpfaq.ru/ip):

Код: Выделить всё

<?php
   $ip=$_SERVER['REMOTE_ADDR'];
   echo $ip;
?>
При обращении к этой страничке клиенты узнают свой «белый адрес» с помощью curl. Далее определим тех пользователей, которым необходимо получать свой адрес:

Код: Выделить всё

htpasswd -cb /usr/local/www/ipaddress/.htpasswd firstsuser userpassword
Для проверки в браузере введем: http://ip-address/ipaddress/ в результате должны увидеть приглашение ввести имя пользователя и пароль, вводим и любуемся своим внешним адресом, если нет, проверяем логи apache.
С апачем покончено, далее сервер имен. С помощью rndc-confgen генерируем ключ.
В /etc/namedb/named.conf добавим следующую запись:

Код: Выделить всё

key "rndc-key" {
      algorithm hmac-md5;
      secret "только_что_сгенерированный_ключ==";
};

zone "mydomain.local"      {
        type             master;
        file             "dynamic/mydomain.local";
        allow-update     { key "rndc-key"; };
};
И создадим файл зоны dynamic/mydomain.local, я просто скопировал файл для локалхост и подправил.
Для проверки попробуем nsupdate обновить запись в зоне mydomain.local, я для этого использовал файл nsupdate.conf:

Код: Выделить всё

server 192.168.0.1
key rndc-key только_что_сгенерированный_ключ==
zone mydomain.local.
update delete test.mydomain.local. A
update add test.mydomain.local. 600 A 192.168.0.182
send
Выполним:

Код: Выделить всё

nsupdate nsupdate.conf
И проверим:

Код: Выделить всё

nslookup test.mydomain.local 192.168.0.1
Должен вернуть адрес тестовой машины, если нет, включаем и смотрим логи сервера имен.
С сервером закончили.
Для клиентской части нужен curl (распространяется с поддержкой ssl и без) и bind9. Из пакета bind9 нам понадобится только nsupdate, его библиотеки и vcredist_x86.exe. На стороне клиента выполняется следующий скрипт, там все понятно, описывать нечего:

Код: Выделить всё

var WshShell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");

var workdir = "d:\\nsupdate\\";
var lastaddrr = "lastaddrr.txt";
var lastip = "127.0.0.1";

if (fso.FileExists(lastaddrr))
{
  var fileObj = fso.GetFile(workdir + lastaddrr);
  var ts = fileObj.OpenAsTextStream(1, -2);

  // если файл создался 10 минут и более назад затираем его
  var x=new Date(fileObj.DateLastModified);
  var y=new Date();
  if (Math.floor((y-x)/(1000*60)) >= 10)
  {
    ts.Close();
    fso.DeleteFile(workdir + lastaddrr, true);
  }
  // иначе читаем из него адрес
  else
  {
  var lastip = ts.ReadLine();
  ts.Close();
  }
}

var stdout = WScript.StdOut;
var stdin = WScript.StdIn;

// определим программы и их аргументы
var curl = workdir + "curl.exe -u firstuser:userpassword http://192.168.0.1/ipaddress/index.php";
var nsupdate = workdir + "nsupdate.exe";

// если наш ДНС пингается, пытаемся получить свой адрес и обновить зону
// иначе молча выходим
var objLocalWMI = GetObject("Winmgmts:");
var enumPingStatus = new Enumerator(objLocalWMI.ExecQuery("Select StatusCode from Win32_PingStatus Where Address='192.168.0.1'"));
if(enumPingStatus.item().StatusCode == 0)
{
  // определяем внешний IP-address
  var oExec = WshShell.Exec(curl);

  // проинициализируем переменные
  var currentip = oExec.stdout.ReadLine();

  if (lastip !== currentip)
  {
    var server = "server 192.168.0.1";
    var key = "key rndc-key только_что_сгенерированный_ключ==";
    var zone = "zone mydomain.local.";
    var update_del = "update delete mydomain.local. A";
    var update_add = "update add mydomain.local. 600 A" + "\ " + currentip;
    var send = "send";

    // отправим данные серверу
    oExec = WshShell.Exec(nsupdate);
    oExec.StdIn.Write(server + "\n");
    oExec.StdIn.Write(key + "\n");
    oExec.StdIn.Write(zone + "\n");
    oExec.StdIn.Write(update_del + "\n");
    oExec.StdIn.Write(update_add + "\n");
    oExec.StdIn.Write(send + "\n");

    // save current ip to file
    ts = fso.CreateTextFile(workdir + lastaddrr, true);
    ts.WriteLine(currentip);
    ts.Close();
  }
}
Этот jscript запускаем на выполнение каждые 5 минут в планировщике. Если сервер не пингуется — молча выходим, если адрес не менялся — ничего обновлять не будем, если в течение 10 минут адрес не менялся (определим по времени создания файла) адрес все равно обновим, а файл удалим, последний полученный адрес сохраним в файл и на него будем ориентироваться в течение 10 минут.

В общем все, кажется ничего не забыл, если где ошибся - поправьте.

P.S. У клиентского скрипта обнаружен недостаток, люди жалуются, что "...периодически мелькают черные окна...", скрипт переписал, окна все равно мелькают :oops: но сейчас они свернутые и неактивные.