Во времена ROS 5.x была потребность поднимать туннель к роутеру с белым динамическим адресом. В ROS 5 мы задавали не имя, а IP-адрес. Варианта 2: сервис DDNS, реализацию которого рассмотрим вкратце и второй о котором и будет рассказ.
Появилась идея сделать центр куда бы роутеры рапортовали свои адреса, и считывали адреса других. Решено было пойти путем наименьшего сопротивления – сайт на РНР.
На данный момент реализовано пару несложных вещей.
Реализовано через запрос к скрипту с указанием своего (роутера) имени и пароля:
Имя и пароль нужны что бы никто не мог замаскироваться под вас и не инициировал подключение вашего роутера к своему или не мог считать адрес вашего роутера. Через утилиту fetch мы открываем нужный скрипт на сервере и через GET передаем имя и пароль. Скрипт же через $_SERVER['REMOTE_ADDR'] получает внешний адрес роутера и записывает его в БД.
Опять же через ту же утилиту вызываем веб-скрипт:
dst-path=«adr.txt» – указываем что полученные данные сохранять в файл. На самой веб-странице у нас сугубо текст с адресом запрашиваемого роутера:
$query=«SELECT address FROM table_routers WHERE ((id='$_GET[i]') AND (password='$_GET[p]'))»;
$adr=mysql_query($query) or die (mysql_error());
$router=mysql_fetch_assoc($adr);
echo $router[address];
:global routeradr [/file get adr.txt contents] – глобальной переменной присваиваем значение содержимого файла. Потом эту переменную можно при менять по потребности и желанию.
Всё так же как в предыдущем скрипте, но файл мы импортируем в конфиг роутера, а потом удаляем этот файл.
Для чего это необходимо? Например, Вы по невнимательности обрезали себе доступ к роутеру в фаерволе. Тогда можно добавить на сайте скрипт для этого роутера с котором указываете исправленные правила фаервола. Роутер следуя расписанию конектится к сайту, там РНР смотрит есть ли в БД непереданные скрипты для этого роутера:
Сначала мы проверяем верно ли заданы пароль и номер роутера (чтобы никто другой не мог считать ваш скрипт, может вы там пароли в конфиге меняете), а потом смотрим какой скрипт стоит в очереди не переданных для этого роутера.
Этот метод не решает ВОЗНИКШИЕ проблемы, он помогает их предотвратить. То есть необходимо предварительно «подстелить соломки» и забить в scheduler раз в Х минут/часов проверку роутером наличия новых скриптов для него.
Так же этот метод хорош, когда роутер имеет серую айпишку, а доступ к нему надо получить из вне. Забиваем скрипт поднятия ВПН-туннеля к своей белой айпишке и через заданное время имеем доступ к устройству даже за 10-ю НАТами.
Вот такая вот коротенькая история. Буду раз замечаниям и идеям что еще можно прикрутить к такому сервису. В планах еще небольшая статистика – что бы роутер сливал в БД пару своих параметров, например температуру, загрузку процессора и прочие.
Как бонус кусок готовых скриптов, о которых я писал в начале, получения ip с имени хоста и добавления его в политику IPsec.
Плюс в том что работает в связке Mikrotik + мыльницы которые поддерживают ddns и ipsec (Dlink 804 на пример). Скрипт который достает из дднс имени удаленного пира IP адрес и вставляет его в нужную политику:
И скрипт который подставляет на удаленной стороне текущий ip в политику ipsec:
Появилась идея сделать центр куда бы роутеры рапортовали свои адреса, и считывали адреса других. Решено было пойти путем наименьшего сопротивления – сайт на РНР.
На данный момент реализовано пару несложных вещей.
Оглашение своего адреса
Реализовано через запрос к скрипту с указанием своего (роутера) имени и пароля:
:local number "ROUTER_NUMBER";
:local pass "PASSWORD";
/tool fetch url="http://whoami.ho.ua/adr.php\?i=$number&p=$pass" mode=http
Имя и пароль нужны что бы никто не мог замаскироваться под вас и не инициировал подключение вашего роутера к своему или не мог считать адрес вашего роутера. Через утилиту fetch мы открываем нужный скрипт на сервере и через GET передаем имя и пароль. Скрипт же через $_SERVER['REMOTE_ADDR'] получает внешний адрес роутера и записывает его в БД.
Считывание чужого адреса
Опять же через ту же утилиту вызываем веб-скрипт:
:local number "ROUTER_NUMBER";
:local pass "PASSWORD";
/tool fetch url="http://whoami.ho.ua/getadr.php\?i=$number&p=$pass" mode=http dst-path="adr.txt"
:global routeradr [/file get adr.txt contents]
dst-path=«adr.txt» – указываем что полученные данные сохранять в файл. На самой веб-странице у нас сугубо текст с адресом запрашиваемого роутера:
$query=«SELECT address FROM table_routers WHERE ((id='$_GET[i]') AND (password='$_GET[p]'))»;
$adr=mysql_query($query) or die (mysql_error());
$router=mysql_fetch_assoc($adr);
echo $router[address];
:global routeradr [/file get adr.txt contents] – глобальной переменной присваиваем значение содержимого файла. Потом эту переменную можно при менять по потребности и желанию.
Считывание скрипта из БД
:local number "ROUTER_NUMBER";
:local pass "PASSWORD";
/tool fetch url="http://whoami.ho.ua/getscript.php\?i=$number&p=$pass" mode=http dst-path="script.rsc"
import file-name=script.rsc
/file remove script.rsc
Всё так же как в предыдущем скрипте, но файл мы импортируем в конфиг роутера, а потом удаляем этот файл.
Для чего это необходимо? Например, Вы по невнимательности обрезали себе доступ к роутеру в фаерволе. Тогда можно добавить на сайте скрипт для этого роутера с котором указываете исправленные правила фаервола. Роутер следуя расписанию конектится к сайту, там РНР смотрит есть ли в БД непереданные скрипты для этого роутера:
SELECT id FROM table_routers WHERE ((id='$_GET[i]') AND (password='$_GET[p]'))
$adr=mysql_query($query) or die (mysql_error());
$router=mysql_fetch_assoc($adr);
$query="SELECT script, id FROM table_scripts WHERE ((router='$router[id]') AND (executed='N')) ORDER BY id ASC LIMIT 1";
Сначала мы проверяем верно ли заданы пароль и номер роутера (чтобы никто другой не мог считать ваш скрипт, может вы там пароли в конфиге меняете), а потом смотрим какой скрипт стоит в очереди не переданных для этого роутера.
Этот метод не решает ВОЗНИКШИЕ проблемы, он помогает их предотвратить. То есть необходимо предварительно «подстелить соломки» и забить в scheduler раз в Х минут/часов проверку роутером наличия новых скриптов для него.
Так же этот метод хорош, когда роутер имеет серую айпишку, а доступ к нему надо получить из вне. Забиваем скрипт поднятия ВПН-туннеля к своей белой айпишке и через заданное время имеем доступ к устройству даже за 10-ю НАТами.
Вот такая вот коротенькая история. Буду раз замечаниям и идеям что еще можно прикрутить к такому сервису. В планах еще небольшая статистика – что бы роутер сливал в БД пару своих параметров, например температуру, загрузку процессора и прочие.
Как бонус кусок готовых скриптов, о которых я писал в начале, получения ip с имени хоста и добавления его в политику IPsec.
Плюс в том что работает в связке Mikrotik + мыльницы которые поддерживают ddns и ipsec (Dlink 804 на пример). Скрипт который достает из дднс имени удаленного пира IP адрес и вставляет его в нужную политику:
:local nname RHost1;
:log info "start $nname";
:local newip [:resolve "rmotehost1.zapto.org"];
:local curip [/ip ipsec policy get [/ip ipsec policy find comment=$nname] sa-dst-address];
:log info "newip = $newip";
:log info "currentip = $curip";
:if ($newip != $curip) do={
:log info "ip $nname is $curip not $newip";
/ip ipsec policy set [/ip ipsec policy find comment=$nname] sa-dst-address=$newip;
:log info "end $nname";
}
И скрипт который подставляет на удаленной стороне текущий ip в политику ipsec:
:global lastip
:local wanip
:local wanif "pppoe-out1"
:if ([ :typeof $lastip ] = nil ) do={ :global lastip "0" }
:local wanip [ /ip address get [/ip address find interface=$wanif ] address ]
:if ([ :typeof $wanip ] = nil ) do={
:log info ("WANIP: no ip address on $wanif .")
} else= {
:for i from=( [:len $wanip] - 1) to=0 do={
:if ( [:pick $wanip $i] = "/") do={
:set wanip [:pick $wanip 0 $i];
:log info ("wan ip now is $wanip")
}
}
:if ($wanip != $lastip) do={
:log info ("Renew ipsec Policy: $wanif -> $wanip")
#Подставляем в политику ipsec
/ip ipsec policy set 0 sa-src-address=$wanip
:global lastip $wanip
}
}
Комментарии (11)
erazel
21.09.2015 11:21У меня в логах записи только от скачивания файла. От простого запроса в логах ничего не пишет.
DarkByte
21.09.2015 14:08+4Сначала мы проверяем верно ли заданы пароль и номер роутера (чтобы никто другой не мог считать ваш скрипт, может вы там пароли в конфиге меняете), а потом смотрим какой скрипт стоит в очереди не переданных для этого роутера.
Никто другой, кроме пользователя с логином «'))||1#», ага.erazel
24.09.2015 15:27Не совсем понял. напишите команду полностью. а то у меня что то не получается. Выдает пустую страницу и всё.
DarkByte
24.09.2015 15:54И если указать валидные параметры i и p, то тоже выдаст пустую страницу, ведь скриптов для выполнения в базе нету. Чтобы страница была не пустая, можно, например, ввести вместо id «')) UNION SELECT '\')) UNION SELECT VERSION(),1 #\''#».
Bo0oM
21.09.2015 14:08+9SELECT id FROM table_routers WHERE ((id='$_GET[i]') AND (password='$_GET[p]'))
Проститеerazel
24.09.2015 15:12Ну тут РНР как пример идеи, не более. Не хватало еще для учебного примера проводить кучу проверок и остракизмов на служебные символы.
Xeenon
24.09.2015 16:58есть же PDO и bind параметры
$term = "a"; $term = "'$term%'"; $sql = "SELECT username FROM `user` WHERE username LIKE :term LIMIT 10"; $core = Connect::getInstance(); $stmt = $core->dbh->prepare($sql); $stmt->bindParam(':term', $term, PDO::PARAM_STR); $stmt->execute(); $data = $stmt->fetchAll();
evg_krsk
Немного не по теме: а скажите, вы смогли подавить вывод в лог записи от /tool fetch? Судя по коду, вроде нет. А то логи забиваются.
AcidVenom
Они же перезаписываются, нет?
evg_krsk
Перезаписываются. Но я то том, что в однотипных записях от /tool fetch теряются интересные записи лога.
AcidVenom
Ааа, вот вы о чем. Я для себя решил установкой в юсб-хаб старой флешки на 2Гб.
Не думаю, что есть встроенные способы отключить логирование. Ну только если не писать в память (или вообще куда-либо) system, info.