1. #!/bin/bash
    2. #################################################
    3. # AnripDdns v5.08
    4. # Dynamic DNS using DNSPod API
    5. # Original by anrip<mail@anrip.com>, http://www.anrip.com/ddnspod
    6. # Edited by ProfFan
    7. #################################################
    8. #################################################
    9. # 2018-11-06
    10. # support LAN / WAN / IPV6 resolution
    11. # 2019-05-24
    12. # Support Ipv6 truly (Yes, it was just claimed to, but actually not = =!)
    13. # Add another way resolving IPv6, for machines without nvram.
    14. #if you have any issues, please let me know.
    15. # https://blog.csdn.net/Imkiimki/article/details/83794355
    16. # Daleshen mailto:gf@gfshen.cn
    17. #################################################
    18. #Please select IP type
    19. IPtype=1 #1.WAN 2.LAN 3.IPv6
    20. #---------------------
    21. if [ $IPtype = '3' ]; then
    22. record_type='AAAA'
    23. else
    24. record_type='A'
    25. fi
    26. echo Type: ${record_type}
    27. # OS Detection
    28. case $(uname) in
    29. 'Linux')
    30. echo "OS: Linux"
    31. arIpAddress() {
    32. case $IPtype in
    33. '1')
    34. curltest=`which curl`
    35. if [ -z "$curltest" ] || [ ! -s "`which curl`" ]
    36. then
    37. #根据实际情况选择使用合适的网址
    38. #wget --no-check-certificate --quiet --output-document=- "https://www.ipip.net" | grep "IP地址" | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    39. wget --no-check-certificate --secure-protocol=TLSv1_2 --quiet --output-document=- "http://members.3322.org/dyndns/getip" | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    40. #wget --no-check-certificate --secure-protocol=TLSv1_2 --quiet --output-document=- "ip.6655.com/ip.aspx" | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    41. #wget --no-check-certificate --secure-protocol=TLSv1_2 --quiet --output-document=- "ip.3322.net" | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    42. else
    43. curl -k -s "http://members.3322.org/dyndns/getip" | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    44. #curl -L -k -s "https://www.ipip.net" | grep "IP地址" | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    45. #curl -k -s ip.6655.com/ip.aspx | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    46. #curl -k -s ip.3322.net | grep -E -o '([0-9]+\.){3}[0-9]+' | head -n1 | cut -d' ' -f1
    47. fi
    48. ;;
    49. '2')
    50. ip -o -4 addr list | grep -Ev '\s(docker|lo)' | awk '{print $4}' | cut -d/ -f1
    51. ;;
    52. '3')
    53. # 因为一般ipv6没有nat ipv6的获得可以本机获得
    54. #ifconfig $(nvram get wan0_ifname_t) | awk '/Global/{print $3}' | awk -F/ '{print $1}'
    55. ip addr show dev eth0 | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d' | awk 'NR==1' #如果没有nvram,使用这条,注意将eth0改为本机上的网口设备 (通过 ifconfig 查看网络接口)
    56. ;;
    57. esac
    58. }
    59. ;;
    60. 'FreeBSD')
    61. echo 'FreeBSD'
    62. exit 100
    63. ;;
    64. 'WindowsNT')
    65. echo "Windows"
    66. exit 100
    67. ;;
    68. 'Darwin')
    69. echo "Mac"
    70. arIpAddress() {
    71. ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}'
    72. }
    73. ;;
    74. 'SunOS')
    75. echo 'Solaris'
    76. exit 100
    77. ;;
    78. 'AIX')
    79. echo 'AIX'
    80. exit 100
    81. ;;
    82. *) ;;
    83. esac
    84. echo "Address: $(arIpAddress)"
    85. # Get script dir
    86. # See: http://stackoverflow.com/a/29835459/4449544
    87. rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`.
    88. target=$1 fname= targetDir= CDPATH=
    89. # Try to make the execution environment as predictable as possible:
    90. # All commands below are invoked via `command`, so we must make sure that `command`
    91. # itself is not redefined as an alias or shell function.
    92. # (Note that command is too inconsistent across shells, so we don't use it.)
    93. # `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not even have
    94. # an external utility version of it (e.g, Ubuntu).
    95. # `command` bypasses aliases and shell functions and also finds builtins
    96. # in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for that
    97. # to happen.
    98. { \unalias command; \unset -f command; } >/dev/null 2>&1
    99. [ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too.
    100. while :; do # Resolve potential symlinks until the ultimate target is found.
    101. [ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; }
    102. command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
    103. fname=$(command basename -- "$target") # Extract filename.
    104. [ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/'
    105. if [ -L "$fname" ]; then
    106. # Extract [next] target path, which may be defined
    107. # *relative* to the symlink's own directory.
    108. # Note: We parse `ls -l` output to find the symlink target
    109. # which is the only POSIX-compliant, albeit somewhat fragile, way.
    110. target=$(command ls -l "$fname")
    111. target=${target#* -> }
    112. continue # Resolve [next] symlink target.
    113. fi
    114. break # Ultimate target reached.
    115. done
    116. targetDir=$(command pwd -P) # Get canonical dir. path
    117. # Output the ultimate target's canonical path.
    118. # Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path.
    119. if [ "$fname" = '.' ]; then
    120. command printf '%s\n' "${targetDir%/}"
    121. elif [ "$fname" = '..' ]; then
    122. # Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied
    123. # AFTER canonicalization.
    124. command printf '%s\n' "$(command dirname -- "${targetDir}")"
    125. else
    126. command printf '%s\n' "${targetDir%/}/$fname"
    127. fi
    128. )
    129. DIR=$(dirname -- "$(readlink "$0")")
    130. # Global Variables:
    131. # Token-based Authentication
    132. arToken=""
    133. # Account-based Authentication
    134. arMail=""
    135. arPass=""
    136. # Load config
    137. #. $DIR/dns.conf
    138. # Get Domain IP
    139. # arg: domain
    140. arDdnsInfo() {
    141. local domainID recordID recordIP
    142. # Get domain ID
    143. domainID=$(arApiPost "Domain.Info" "domain=${1}")
    144. domainID=$(echo $domainID | sed 's/.*{"id":"\([0-9]*\)".*/\1/')
    145. # Get Record ID
    146. recordID=$(arApiPost "Record.List" "domain_id=${domainID}&sub_domain=${2}&record_type=${record_type}")
    147. recordID=$(echo $recordID | sed 's/.*\[{"id":"\([0-9]*\)".*/\1/')
    148. # Last IP
    149. recordIP=$(arApiPost "Record.Info" "domain_id=${domainID}&record_id=${recordID}&record_type=${record_type}")
    150. recordIP=$(echo $recordIP | sed 's/.*,"value":"\([0-9a-z\.:]*\)".*/\1/')
    151. # Output IP
    152. case "$recordIP" in
    153. [1-9a-z]*)
    154. echo $recordIP
    155. return 0
    156. ;;
    157. *)
    158. echo "Get Record Info Failed!"
    159. return 1
    160. ;;
    161. esac
    162. }
    163. # Get data
    164. # arg: type data
    165. # see Api doc: https://www.dnspod.cn/docs/records.html#
    166. arApiPost() {
    167. local agent="AnripDdns/5.07(mail@anrip.com)"
    168. #local inter="https://dnsapi.cn/${1:?'Info.Version'}"
    169. local inter="https://dnsapi.cn/${1}"
    170. if [ "x${arToken}" = "x" ]; then # undefine token
    171. local param="login_email=${arMail}&login_password=${arPass}&format=json&${2}"
    172. else
    173. local param="login_token=${arToken}&format=json&${2}"
    174. fi
    175. wget --quiet --no-check-certificate --secure-protocol=TLSv1_2 --output-document=- --user-agent=$agent --post-data $param $inter
    176. }
    177. # Update
    178. # arg: main domain sub domain
    179. arDdnsUpdate() {
    180. local domainID recordID recordRS recordCD recordIP myIP
    181. # Get domain ID
    182. domainID=$(arApiPost "Domain.Info" "domain=${1}")
    183. domainID=$(echo $domainID | sed 's/.*{"id":"\([0-9]*\)".*/\1/')
    184. #echo $domainID
    185. # Get Record ID
    186. recordID=$(arApiPost "Record.List" "domain_id=${domainID}&record_type=${record_type}&sub_domain=${2}")
    187. recordID=$(echo $recordID | sed 's/.*\[{"id":"\([0-9]*\)".*/\1/')
    188. #echo $recordID
    189. # Update IP
    190. myIP=$(arIpAddress)
    191. recordRS=$(arApiPost "Record.Modify" "domain_id=${domainID}&sub_domain=${2}&record_type=${record_type}&record_id=${recordID}&record_line=默认&value=${myIP}")
    192. recordCD=$(echo $recordRS | sed 's/.*{"code":"\([0-9]*\)".*/\1/')
    193. recordIP=$(echo $recordRS | sed 's/.*,"value":"\([0-9a-z\.:]*\)".*/\1/')
    194. # Output IP
    195. if [ "$recordIP" = "$myIP" ]; then
    196. if [ "$recordCD" = "1" ]; then
    197. echo $recordIP
    198. return 0
    199. fi
    200. # Echo error message
    201. echo $recordRS | sed 's/.*,"message":"\([^"]*\)".*/\1/'
    202. return 1
    203. else
    204. echo $recordIP #"Update Failed! Please check your network."
    205. return 1
    206. fi
    207. }
    208. # DDNS Check
    209. # Arg: Main Sub
    210. arDdnsCheck() {
    211. local postRS
    212. local lastIP
    213. local hostIP=$(arIpAddress)
    214. echo "Updating Domain: ${2}.${1}"
    215. echo "hostIP: ${hostIP}"
    216. lastIP=$(arDdnsInfo $1 $2)
    217. if [ $? -eq 0 ]; then
    218. echo "lastIP: ${lastIP}"
    219. if [ "$lastIP" != "$hostIP" ]; then
    220. postRS=$(arDdnsUpdate $1 $2)
    221. if [ $? -eq 0 ]; then
    222. echo "update to ${postRS} successed."
    223. return 0
    224. else
    225. echo ${postRS}
    226. return 1
    227. fi
    228. fi
    229. echo "Last IP is the same as current, no action."
    230. return 0
    231. fi
    232. echo ${lastIP}
    233. return 1
    234. }
    235. # DDNS
    236. #echo ${#domains[@]}
    237. #for index in ${!domains[@]}; do
    238. # echo "${domains[index]} ${subdomains[index]}"
    239. # arDdnsCheck "${domains[index]}" "${subdomains[index]}"
    240. #done
    241. . $DIR/dns.conf

    dns.conf同文件下

    1. # 1. Combine your token ID and token together as follows
    2. arToken="241083,69cdb4770564468d0989868d97e035ef"
    3. # 2. Place each domain you want to check as follows
    4. # you can have multiple arDdnsCheck blocks
    5. arDdnsCheck "mmdchat.com" "wk1"
    1. # 1. Combine your token ID and token together as follows
    2. arToken="12345,7676f344eaeaea9074c123451234512d"
    3. dnspod id dnspod 密匙
    4. # 2. Place each domain you want to check as follows
    5. # you can have multiple arDdnsCheck blocks
    6. arDdnsCheck "test.org" "subdomain"
    7. 主域名 子域名