?

Log in

No account? Create an account

Previous Entry | Next Entry

Не многие знают, что у Яндекса есть бесплатный DNS-хостинг. Еще меньше тех кто знает, что у этого сервиса есть API. Вот с помощью него я и решил прописывать динамический ip который получаю от провайдера в DNS.
Незамысловатое описание протокола находится тут: http://api.yandex.ru/pdd/doc/api-pdd/reference/api-dns.xml

В принципе, все можно было бы написать парой строк в командной строке, если бы не то обстоятельство что скрипт этот должен работать на роутере. Роутер асусовский со стандартным джентльменским набором: busybox, openssl и много другой полезной хрени.

Первая проблема с которой я столкнулся — wget который идет из коробки не поддерживает https. Зато есть в комплекте openssl. С помощью небольшого магического скрипта получаем нечто, что может дернуть https URL и получить какой-то результат. Это нечто не претендует на совершенство, но лучше я сделать не смог.

#!/bin/sh
HOST=$1 
QUERY=$2 

counter=20
while [[ ! "$counter" = "0" ]]; do
        counter=$((counter-1))
        res=$( (usleep 10000; echo "GET $QUERY HTTP/1.0"; echo ; usleep 500000) | openssl s_client -connect $HOST 2>/dev/null | grep -E "HTTP/[0-9]+[.][0-9]+" -A 1000000)
        if [[ ! "$( echo "$res" | grep -E "HTTP/[0-9]+[.][0-9]+ +200 +OK")" = "" ]]; then
                echo "$res" | awk '{if ($1 == "") a=100; if (a == 100) print}' | tail -n +2 | sed '$ d'
                exit 0
        fi
done

echo "$res" >&2
exit 1

Запускается этот скрипт как-то так: ./get.sh pddimp.yandex.ru:443 "/nsapi/get_domain_records.xml?token=$TOKEN&domain=$DOMAIN"
Следующая нетривиальная задача — распарсить XML, который приходит в качестве ответа. Для этого я использовал вот этот скрипт на awk: http://lawker.googlecode.com/svn/fridge/lib/awk/xmlparse.awk после небольших правок он отлично заработал на busybox-овом awk-е.
Ну и последний шаг — позвать все в нужном порядке:

#!/bin/sh

TOKEN="secret"
DOMAIN="dimonb.com"
SUBDOMAIN="@"
TTL=900
LOG=/tmp/dnsupdate.log
DIR=/jffs/scripts

current=$(sh $DIR/get.sh pddimp.yandex.ru:443 "/nsapi/get_domain_records.xml?token=$TOKEN&domain=$DOMAIN" 2>$LOG)
echo $current >>$LOG


if [[ "$(echo "$current" | grep -E "<error>ok</error>")" = "" ]]; then
    echo error >&2
    echo "$current" >&2
    exit 1
fi

record=$(echo $current | awk -f $DIR/xmlparse.awk | while read line; do
    if [[ "$line" = "begin RECORD" ]]; then
        record="started"
    elif [[ "$line" = "end RECORD" ]]; then
        if [[ "$domain" = "$DOMAIN" && "$subdomain" = "$SUBDOMAIN" ]]; then
            if [[  "$type" = "CNAME" || "$type" = "A" ]]; then
                echo "$id $domain $type $subdomain: $data" >>$LOG
                echo "$id $domain $type $subdomain $data"
                break
            fi
        fi
        unset record
    elif [[ ! "$record" = "" ]]; then
        if [[ "${line%* *}" = "attrib" ]]; then
            attrib=${line#attrib *}
        elif [[ "${line%* *}" = "value" ]]; then
            if [[ "$attrib" = "domain" ]]; then
                domain="${line#value *}"
            fi
            if [[ "$attrib" = "type" ]]; then
                type="${line#value *}"
            fi
            if [[ "$attrib" = "subdomain" ]]; then
                subdomain="${line#value *}"
            fi
            if [[ "$attrib" = "id" ]]; then
                id="${line#value *}"
            fi
        elif [[ "${line%* *}" = "data" ]]; then
            data="${line#data *}"
        fi
    fi
done)

echo $record


if [[ ! "$record" = "" ]]; then
    if [[ "$(echo "$record" | awk '{print $3}')" = "A" ]]; then
        current=$(sh $DIR/get.sh pddimp.yandex.ru:443 "/nsapi/edit_a_record.xml?token=$TOKEN&domain=$DOMAIN&subdomain=$SUBDOMAIN&ttl=$TTL&content=$1&record_id=$(echo "$record" | awk '{print $1}')" 2>>$LOG)
        if [[ "$(echo "$current" | grep -E "<error>ok</error>")" = "" ]]; then
            echo error >&2
            echo "$current" >&2
            exit 1                                                                                                                                                  
        fi  
    fi
    

else
    current=$(sh $DIR/get.sh pddimp.yandex.ru:443 "/nsapi/add_a_record.xml?token=$TOKEN&domain=$DOMAIN&subdomain=$SUBDOMAIN&ttl=$TTL&content=$1" 2>>$LOG)
    if [[ "$(echo "$current" | grep -E "<error>ok</error>")" = "" ]]; then
        echo error >&2
        echo "$current" >&2
        exit 1
    fi
fi

Скрипту нужно передать в качестве единственного параметра: ip. Он найдет корневую запись и пропишет ее для вашего домена. Внешний ip можно получить так: wget -q -O - http://ifconfig.me/ip или любым другим доступным способом.

Comments

( 2 comments — Leave a comment )
blindnatasha
Aug. 30th, 2013 07:17 am (UTC)
Для меня пока это все мудрено. А скрипты я только пробовала писать для Jaws. (Jaws "Скрин-ридер" программа для слепых).
dimonbb
Aug. 30th, 2013 07:21 am (UTC)
Не волнуйся по этому поводу. Для 90% программистов это тоже мало что значащие слова и буквы :)
( 2 comments — Leave a comment )