Ни о чём →
DNS-хостинг Яндекса vs Динамический IP
В сентябре прошлого 2010 года компания Яндекс открыла для публичного использования DNS-хостинг в рамках Почты для доменов. Радости пользователей не было предела, топик был встречен массой положительных комментариев, а Яндекс был объявлен корпорацией добра.
К сожалению администрирование DNS-записей было предусмотрено только через web-интерфейс. API для администрирования предусмотрено не было, до сих пор не появилось, и возможно еще долго не появится. Этот факт опечалил многих владельцев доменов с динамическим IP не меньше, чем перевод отличного бесплатного сервиса free.editdns.net на платную основу (для custom доменов), в связи с покупкой последнего компанией DynDNS.
Убедившись, что чуда не случилось, я взял в рукиPython напильник с целью исправить эту несправедливость…
Первым делом я отправился к всезнающему Google в поисках хоть какой нибудь информации об API сервисов Яндекса. Первым мне попалось подробное описание API Почты для доменов. Увы, из 32 имеющихся функций в нем не оказалось ничего, связанного с администрированием DNS-хостинга, и я продолжил поиски. Добавив к запросу волшебные слова python, а затем и c sharp, я наткнулся на статью Алексея Немиро с подробным описанием работы браузера при авторизации на сервисах Яндекса и примерами кода на VB и C#.
Прочитав статью и убедившись, что все же придется имитировать браузер, я вооружился FireBug'ом и HTTP Analyzer'ом. Потратив немного времени на изучение тонкостей авторизации и работы с DNS-хостингом, я выяснил, что авторизация на сервисах Яндекса работает достаточно просто. Процедура авторизации начинается с куки yandexuid, получаемой при входе на любой сервис Яндекса:
Получив куку yandexuid браузер передает POST-запросом логин, пароль и таймстамп в формате UNIX. Если с формированием запроса проблем не возникло, то с формулой таймстампа я просидел долго:
Получив волшебный idkey, в ответ на запрос «Установить постоянную авторизацию на этом компьютере» потребовалось сформировать запрос, имитирующий нажатие кнопки «Нет»:
Теперь, имея под рукой все необходимые куки, для работы с Почтой для доменов достаточно имитировать нажатие кнопки «Сохранить» в редакторе DNS-записей через внутренний AJAX API:
Как и в предыдущем случае, на этом этапе заголовок Accept оказался обязательным. Впрочем это не самое важное. Для получения ns_record_id пришлось разобрать HTML-код страницы со списком DNS-записей:
Так как это была моя первая программа на Python, я ограничился httplib и ручным формированием кук. Добавив в этот коктейль параметр командной строки, парсинг конфига и получение внешнего IP, я получил простой скрипт для обновления DNS-записи на DNS-хостинге Яндекса.
скачать исходный код и пример конфига
К сожалению администрирование DNS-записей было предусмотрено только через web-интерфейс. API для администрирования предусмотрено не было, до сих пор не появилось, и возможно еще долго не появится. Этот факт опечалил многих владельцев доменов с динамическим IP не меньше, чем перевод отличного бесплатного сервиса free.editdns.net на платную основу (для custom доменов), в связи с покупкой последнего компанией DynDNS.
Убедившись, что чуда не случилось, я взял в руки
Первым делом я отправился к всезнающему Google в поисках хоть какой нибудь информации об API сервисов Яндекса. Первым мне попалось подробное описание API Почты для доменов. Увы, из 32 имеющихся функций в нем не оказалось ничего, связанного с администрированием DNS-хостинга, и я продолжил поиски. Добавив к запросу волшебные слова python, а затем и c sharp, я наткнулся на статью Алексея Немиро с подробным описанием работы браузера при авторизации на сервисах Яндекса и примерами кода на VB и C#.
Прочитав статью и убедившись, что все же придется имитировать браузер, я вооружился FireBug'ом и HTTP Analyzer'ом. Потратив немного времени на изучение тонкостей авторизации и работы с DNS-хостингом, я выяснил, что авторизация на сервисах Яндекса работает достаточно просто. Процедура авторизации начинается с куки yandexuid, получаемой при входе на любой сервис Яндекса:
Copy Source | Copy HTML
- def initialize(self):
- connection = httplib.HTTPConnection('www.yandex.ru')
- connection.request('GET', '/')
-
- response = connection.getresponse()
- cookies = response.getheader('set-cookie', None)
- response.close()
-
- match = re.search('(?<=yandexuid=)[^;]*', cookies)
- self._yandexuid = match.group( 0)
- print 'yandexuid =', self._yandexuid
Получив куку yandexuid браузер передает POST-запросом логин, пароль и таймстамп в формате UNIX. Если с формированием запроса проблем не возникло, то с формулой таймстампа я просидел долго:
Copy Source | Copy HTML
- def login(self):
- content = 'login={0}&passwd={1}×tamp={2}'
- content = content.format(self._login, self._passwd, self.timestamp())
-
- connection = httplib.HTTPConnection('passport.yandex.ru')
- connection.request('POST', '/passport?mode=auth', content, {'Cookie': self.getcookies()})
-
- response = connection.getresponse()
- content = response.read()
- response.close()
-
- match = re.search('idkey\"\s.*', content)
- match = re.search('(\d\w*)', match.group( 0))
- self._idkey = match.group( 0)
- print 'idkey =', self._idkey
Получив волшебный idkey, в ответ на запрос «Установить постоянную авторизацию на этом компьютере» потребовалось сформировать запрос, имитирующий нажатие кнопки «Нет»:
Copy Source | Copy HTML
- def authenticate(self):
- content = 'filled=yes×tamp={0}&idkey={1}&no=%D0%9D%D0%B5%D1%82'
- content = content.format(self.timestamp(), self._idkey)
-
- connection = httplib.HTTPConnection('passport.yandex.ru')
- connection.request('POST', '/passport?mode=auth', content, {'Cookie': self.getcookies()})
-
- response = connection.getresponse()
- cookies = response.getheader('set-cookie', None)
-
- ... парсинг кук регекспами ...
-
- response.close()
Теперь, имея под рукой все необходимые куки, для работы с Почтой для доменов достаточно имитировать нажатие кнопки «Сохранить» в редакторе DNS-записей через внутренний AJAX API:
Copy Source | Copy HTML
- def updatedomain(self, ns_record_id):
- content = 'domain={0}&ns_record_id={1}&ns_rec_type=A&ns_subdomain=%40&ns_weight=&ns_port=&ns_content={2}&ns_priority=1'
- content = content.format(self._domain, ns_record_id, self._externalip)
-
- connection = httplib.HTTPSConnection('pdd.yandex.ru')
- connection.request('POST', '/ajax/ns_simple_record_edit.ajax.xml', content,\
- {'Accept': 'application/json, text/javascript, */*',\
- 'Cookie': self.getcookies()})
- response = connection.getresponse()
- response.close()
Как и в предыдущем случае, на этом этапе заголовок Accept оказался обязательным. Впрочем это не самое важное. Для получения ns_record_id пришлось разобрать HTML-код страницы со списком DNS-записей:
Copy Source | Copy HTML
- def domainlist(self):
- connection = httplib.HTTPSConnection('pdd.yandex.ru')
- connection.request('GET', '/domain_ns/{0}/'.format(self._domain), None,\
- {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',\
- 'Cookie': self.getcookies(),\
- 'Referer': 'https://pdd.yandex.ru'})
-
- response = connection.getresponse()
- content = response.read()
-
- block = re.findall('item:\s\'[\d]+\'(.+)value="[\w\.]+"', content)
-
- for item in block:
- match = re.search('(?<=item:\s\')[\d]*', item)
- ns_record_id = match.group( 0)
-
- match = re.search('ns_subdomain(.+?)value=\"(.+?)\"', item)
- match = re.search('(?<=value=)\".+?\"', match.group( 0))
- ns_subdomain = match.group( 0)
-
- match = re.search('ns_rec_type(.+?)value=\"(.+?)\"', item)
- match = re.search('(?<=value=)\".+?\"', match.group( 0))
- ns_rec_type = match.group( 0)
-
- match = re.search('ns_content(.+?)value=\"(.+?)\"', item)
- match = re.search('(?<=value=)\".+?\"', match.group( 0))
- ns_content = match.group( 0)
-
- record = 'ns_record_id = {0} | ns_subdomain = {1} | ns_rec_type = {2} | ns_content = {3}'
- print record.format(ns_record_id, ns_subdomain, ns_rec_type , ns_content)
-
- response.close()
Так как это была моя первая программа на Python, я ограничился httplib и ручным формированием кук. Добавив в этот коктейль параметр командной строки, парсинг конфига и получение внешнего IP, я получил простой скрипт для обновления DNS-записи на DNS-хостинге Яндекса.
скачать исходный код и пример конфига
28.06.2011 12:34+0400