├── LICENSE ├── README.md ├── README.ru.md ├── com.haunted.yaddns.plist ├── ya.dns.update.sh └── yapdate.sh /LICENSE: -------------------------------------------------------------------------------- 1 | WTFPL or MIT. Whatever you like. 2 | 3 | 4 | Copyright © 2014 Serge Populov 5 | This work is free. You can redistribute it and/or modify it under the 6 | terms of the Do What The Fuck You Want To Public License, Version 2, 7 | as published by Sam Hocevar. 8 | See http://www.wtfpl.net/ for more details. 9 | 10 | 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright © 2014 Serge Populov 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yandex dDNS updater 2 | ### Dynamic DNS client for pdd.yandex.ru (Linux & OS X) 3 | [По-русски / In Russian](README.ru.md) 4 | 5 | A very basic shell script updater for dynamic DNS services provided by . 6 | 7 | ## Instructions: 8 | 9 | 1. Get **token** at [Token management](https://pddimp.yandex.ru/token/index.xml) page. See [Yandex API manual](http://api.yandex.ru/pdd/doc/reference/api-dns_get_token.xml) for details. 10 | 2. Edit **ya.ddns.update.sh** in a text editor, and modify the *hostname*, and *token* fields. 11 | 3. If desired, set `$use_ifconfig='yes'` and `$iface='eth0'`. Otherwise, the script will use http://checkip.dns.he.net to determine your public IP address. 12 | 4. If necessary, `chmod +x ya.ddns.update.sh`. 13 | 5. Run **ya.ddns.update.sh**. 14 | 6. Use system's cron to schedule the updates. Or LaunchDaemon. Whatever floats your boat. 15 | 16 | ### Notes 17 | * Works both for primary domain (*example.com*) and subdomains (*foo.example.com*, *foo.bar.example.com*). 18 | * DNS "A" record for *hostname* must exist before you run this script. 19 | * **yapdate.sh** is a simplier script, but won't work behind router. 20 | 21 | **License**: [WTFPL](http://www.wtfpl.net) or [MIT](http://opensource.org/licenses/MIT).
**Warranty**: None. 22 | 23 | Enjoy! 24 | 25 | *Inspired by [bennettp123](https://github.com/bennettp123)'s [dns.ne.net-updater-mac](https://github.com/bennettp123/dns.ne.net-updater-mac)* 26 | 27 | -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 | # Yandex dDNS updater 2 | ### Dynamic DNS клиент для pdd.ya.ru (Linux & OS X) 3 | [In Russian / По-английски](README.md) 4 | 5 | Простой шелл-скрипт обновления DNS в сервисе . 6 | 7 | ## Инструкция: 8 | 9 | 1. Получите **token** на странице [Token management](https://pddimp.yandex.ru/token/index.xml). Подробности в [руководстве Yandex API](http://api.yandex.ru/pdd/doc/reference/api-dns_get_token.xml). 10 | 2. Откройте **ya.ddns.update.sh** в любом текстовом редакторе, установите *hostname* и *token*. 11 | 3. Можете установить `$use_ifconfig='yes'` и `$iface='eth0'`. Иначе скрипт будет получать внешний IP адрес при помощи сервиса http://checkip.dns.he.net. 12 | 4. Чтобы сделать файл исполняемым, выполните `chmod +x ya.ddns.update.sh` (если нужно). 13 | 5. Запустите **ya.ddns.update.sh**. 14 | 6. Используйте cron для запуска по расписанию. Или LaunchDaemon. Ну или что там у вас. 15 | 16 | ### Замечания 17 | * Работает как с основным доменом (*example.com*), так и с субдоменами (*foo.example.com*, *foo.bar.example.com*). 18 | * "A"-запись в DNS для *hostname* нужно создать до запуска скрипта. 19 | * **yapdate.sh** более простой скрипт, но не работает, если вы за роутером. 20 | 21 | **Лицензия**: [WTFPL](http://www.wtfpl.net) или [MIT](http://opensource.org/licenses/MIT).
**Гарантия**: Никакой. 22 | 23 | Используйте с удовольствием! 24 | 25 | *По мотивам [dns.ne.net-updater-mac](https://github.com/bennettp123/dns.ne.net-updater-mac) от [bennettp123](https://github.com/bennettp123)* 26 | -------------------------------------------------------------------------------- /com.haunted.yaddns.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Disabled 6 | 7 | Label 8 | com.haunted.yaddns 9 | Nice 10 | 15 11 | ProgramArguments 12 | 13 | /Library/Scripts/ya.ddns.update.sh 14 | 15 | StartInterval 16 | 300 17 | RunAtLoad 18 | 19 | LowPriorityIO 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ya.dns.update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # http://projects.populov.com/yandex-ddns-sh/ 3 | 4 | api_url="https://pddimp.yandex.ru/nsapi" 5 | ttl=3600 6 | previous_file_prefix=/tmp/ddns 7 | tag=ru.yandex.ddns 8 | 9 | retval=0 10 | 11 | use_ifconfig='no' # set this to 'yes' to use ifconfig to determine local IP addresses. 12 | iface='eth0' # only needed if $use_ifconfig='yes' 13 | 14 | for hostname_token in \ 15 | "demo.example.com:0290c6501877031d5bcfe880522a1576c4f7144bbeedbd51f3e9f7b8" \ 16 | # "hostname2:token2" #etc... 17 | do 18 | 19 | hostname=$( echo -n "$hostname_token" | sed 's/:.*$//' ) 20 | # echo "Hostname: $hostname" 21 | token=$( echo -n "$hostname_token" | sed 's/.*://' ) 22 | # echo "Token: $token" 23 | subdomain=$( echo -n "$hostname" | sed -r 's/\.?[^.]*\.[^.]*$//' ) 24 | # echo "Subdomain: $subdomain" 25 | domain=$( echo -n "$hostname" | sed s/^"$subdomain\."// ) 26 | # echo "Domain: $domain" 27 | 28 | currentip='' 29 | if [ "$use_ifconfig" = "yes" ]; then 30 | if which ip >/dev/null 2>&1; then 31 | currentip=$(ip addr show dev "$iface" | grep inet\ .*scope\ global | sed -E 's/[^0-9]*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/[0-9]{1,2}.*/\1/g') 32 | elif which ifconfig >/dev/null 2>&1; then 33 | currentip=$(ifconfig en0 inet | grep -E '^.*inet [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.*$' | sed -E 's/^.*inet ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*$/\1/') 34 | else 35 | logmsg="$hostname: could not determine local IP address" 36 | logger -i -t $tag "$logmsg" 37 | echo $logmsg 38 | retval=1 39 | break 40 | fi 41 | else 42 | # currentip=$(curl -4 -s "http://checkip.dns.he.net" | grep -iE "Your ?IP ?address ?is ?: ?" | sed -r 's/.*\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/') 43 | currentip=$(wget -qO- "http://checkip.dns.he.net" | grep -iE "Your ?IP ?address ?is ?: ?" | sed -r 's/.*\s+([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}).*/\1/') 44 | fi 45 | 46 | previous_file="$previous_file_prefix.$hostname" 47 | previous=$(cat "$previous_file" 2>/dev/null) 48 | oldip=$(echo -n "$previous" | sed 's/^[^:]*://') 49 | record_id=$(echo -n "$previous" | sed 's/:.*$//') 50 | 51 | if [ "_$oldip" = "_" ]; then 52 | oldip="unknown" 53 | # getrecords=$(curl -4 -s "$api_url/get_domain_records.xml" -d token=$token -d domain=$domain -d subdomain=$subdomain) 54 | getrecords=$(wget -qO- "$api_url/get_domain_records.xml?token=$token&domain=$domain&subdomain=$subdomain") 55 | getRetval=$? 56 | if [ $getRetval -eq 0 ]; then 57 | message=$(echo "$getrecords" | grep error | sed -r 's/(^.*)|(<\/error>.*$)//g') 58 | else 59 | message="HTTP error" 60 | fi 61 | if [ "_$message" = "_ok" ]; then 62 | domaintest="domain=\"?$hostname\"?[^>]+type=\"?A\"?[^<]+" 63 | records=$(echo "$getrecords" | grep -E $domaintest) 64 | if [ "_$records" = "_" ]; then 65 | logmsg="$hostname DNS \"A\" record not found; skip" 66 | logger -i -t $tag "$logmsg" 67 | echo $logmsg 68 | continue 69 | fi 70 | record=$(echo $records | sed -r 's/.+domain=\"?'"$hostname"'"?[^>]+type="A"//' | sed 's/<\/record.*//') 71 | previous_id=$record_id 72 | record_id=$(echo "$record" | sed -r 's/(^.*\id=\")|(\">.*)//g') 73 | # echo "record_id=$record_id" 74 | remoteip=$(echo "$record" | sed -r 's/.*>//g') 75 | echo "$hostname remote IP: $remoteip" 76 | if [ "_$remoteip" != "_$oldip" ] || [ "_$record_id" != "_$previous_id"]; then 77 | logger -i -t "$tag" "Remote: $hostname:$remoteip" 78 | echo "$record_id:$remoteip" > "$previous_file" 79 | oldip=$remoteip 80 | fi 81 | else 82 | logmsg="Error getting $domain DNS records: $message" 83 | logger -i -t $tag "$logmsg" 84 | echo $logmsg 85 | continue 86 | fi 87 | fi 88 | 89 | if [ "_$currentip" != "_$oldip" ]; then 90 | logmsg="$hostname: old IP: $oldip; current IP: $currentip; updating..." 91 | logger -i -t $tag "$logmsg" 92 | echo $logmsg 93 | # editResult=$(curl -4 -s "$api_url/edit_a_record.xml" -d token=$token -d domain=$domain -d subdomain=$subdomain -d record_id=$record_id -d ttl=$ttl -d content=$currentip) 94 | editResult=$(wget -qO- "$api_url/edit_a_record.xml?token=$token&domain=$domain&subdomain=$subdomain&record_id=$record_id&ttl=$ttl&content=$currentip") 95 | editRetval=$? 96 | if [ $editRetval -eq 0 ]; then 97 | message=$(echo "$editResult" | grep error | sed -r 's/(^.*)|(<\/error>.*$)//g') 98 | else 99 | message="HTTP error" 100 | fi 101 | if [ "_$message" = "_ok" ]; then 102 | echo "$hostname: updated" 103 | logger -i -t "$tag" "$hostname:$currentip" 104 | echo "$record_id:$currentip" > "$previous_file" 105 | else 106 | logmsg="Error updating $hostname: $message" 107 | logger -i -t $tag "$logmsg" 108 | echo $logmsg 109 | fi 110 | else 111 | logmsg="$hostname: old IP same as current IP: $currentip; not updating" 112 | # logger -i -t $tag "$logmsg" 113 | echo $logmsg 114 | editRetval=0 115 | fi 116 | 117 | retval=`bc <> /usr/logs/yandex-dns-update.log 23 | wget --no-check-certificate --header="PddToken: ${token}" \ 24 | --post-data "&domain=${domain}&subdomain=${subdomain}&record_id=${record_id}&ttl=${ttl}&content=${current_ip}" \ 25 | -qO- "https://pddimp.yandex.ru/api2/admin/dns/edit" 26 | rm -f $cache_file 27 | echo $current_ip > $cache_file 28 | fi 29 | 30 | --------------------------------------------------------------------------------