设置外网ipv6访问宽带家庭电脑、简单五步设置群晖NAS绑定自有域名利用ipv6实现外网访问

我家的电信宽带升级成了ipv6,用了路由器后,家里的好几台电脑和手机都分配到了以240e开头的公网ipv6。我觉得要把ipv6充分利用起来,所以想起了远程控制家里的电脑,想自己打造智慧家庭,所以把一台用蜗牛星际改装的黑群晖设置成外网能够访问,所以参考了大神们的代码后,自己写出了阿里云域名ipv6自动解析的linux代码,在文章后面,我要写出参考的文章及我遇到的坑,以供参考。(此代码可以运用于linux任何家庭电脑或家庭虚拟机的动态域名解析,以后有机会写个windows下的)

1.注册阿里云账号。

2.注册一个域名。

如果域名不在阿里云解析托管,需要先转过去,具体方法是联系域名提供商修改域名的DNS服务器,修改方式参考这里:https://help.aliyun.com/knowledge_detail/39844.html
然后去控制台找到云解析,将域名添加进去;

3.到阿里云控制中心找到access key和secret并保存下来(强烈建议遵循阿里云安全最佳实践的说明 ,使用RAM子用户的AccessKey);

参考:https://help.aliyun.com/document_detail/28647.html

4.到群晖控制中心找到任务计划新增一个计划。

新增->计划的任务->用户自定义脚本

设置10分钟定时

复制以下内容,根据自己的情况修改中文部分并添加到任务设置自定义脚本

#!/bin/sh
aliddns_name=”你的域名前缀”
aliddns_domain=”你的域名”
aliddns_ak=”你的AccessKeyId”
aliddns_sk=”你的AccessKeySecret”

# 获取本地ipv6并与以前保存的ipv6比较
# 获取本地ipv6,我这边有三个ipv6,一个是240e开头的互联网能互相访问的,
# 一个是240e开头的临时网址,但互联网不能访问,却能访问互联网。
# 一个是fe80开头的本地ipv6,应该舍弃
# 得筛选出那个互联网能够互访的ipv6
ip=$(/sbin/ifconfig eth0 | grep 'inet6 addr' | sed 's/^.*addr://g' ) 

# 获取本地保存的已经解析过的ipv6
oldip=$(cat /root/ip.txt 2>&1)
echo $oldip
if [ -n $oldip ]
    then
  result=$(echo $ip | grep $oldip)
  if [ -n $result ]
        then
    echo 跟以前保存的一样,没必要解析,退出。
        exit 0
    fi
fi 

# 在ip.sb网站上查到一个本地ipv6,我发现,都是临时ipv6
# 不知道再有什么选择能互访的ipv6的办法?
localip=$(curl -6 ip.sb)
# 将本机三个ipv6保存进数组
OLD_IFS=$IFS
IFS=/
array=($ip)
IFS=$OLD_IFS
# 取掉临时的和fe80开头的ipv6,留下能互访问的ipv6
for var in ${array[@]}
  do
  result=$(echo $var | grep fe80)
  echo var是$var
  if [[ $result !=  ]]
  then
    echo 是内网ipv6退出
    continue
  fi
  if [[ $var = $localip ]]
  then
    echo 是不能互访的ipv6返回
    continue
  fi
  length=${#var}
  ipv6num=16
  if [[ $length -gt $ipv6num ]];
  then
    echo 是可以互访的ipv6,退出选择
    ip=$var
    break
  else
    echo 长度太小
    continue
  fi 
done
ip=`echo $ip`
echo $ip ###正确ip
echo 数组元素个数为: ${#array[*]}
echo $ip >/root/ip.txt ##把ip替换到文件中

# 安装阿里云cli
cg=$(aliyun version 2>&1)
cg=${cg:0:1}
if ! [[ $cg -gt 0 ]] 2>/dev/null
    then
    # 下载阿里cli
    wget https://aliyuncli.alicdn.com/aliyun-cli-linux-latest-amd64.tgz
    # 解压
    tar xzvf aliyun-cli-linux-latest-amd64.tgz
    # 复制到系统文件夹
    cp aliyun /usr/local/bin
    # cli初始化设置
    aliyun configure set 
    --profile akProfile 
    --mode AK 
    --region cn-hangzhou 
    --access-key-id $aliddns_ak 
    --access-key-secret $aliddns_sk
fi
# 得到解析id
get_recordid() {
    grep -Eo 'RecordId: [0-9]+' | cut -d':' -f2 | tr -d ''
}
# 向阿里云域名cli获取解析id
query_recordid() {
    aliddns_record_id=`aliyun alidns  DescribeDomainRecords --DomainName $aliddns_domain --RRKeyWord $aliddns_name --Type AAAA`
  echo -n $aliddns_record_id
  }
# 修改解析
update_record() {
    aliyun alidns UpdateDomainRecord --RR $aliddns_name --RecordId $1 --Type AAAA --Value $ip
}
# 添加解析
add_record() {
    aliyun alidns AddDomainRecord --DomainName $aliddns_domain --RR $aliddns_name --Type AAAA --Value $ip
}
if [ $aliddns_record_id =  ]
then
    aliddns_record_id=`query_recordid | get_recordid`
  echo $aliddns_record_id
fi
if [ $aliddns_record_id =  ]
then
    aliddns_record_id=`add_record | get_recordid`
    echo added record $aliddns_record_id
else
    update_record $aliddns_record_id
    echo updated record $aliddns_record_id
fi
————————————————
版权声明:本文为CSDN博主「shyshyshy33」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shyshyshy33/article/details/104146447

参考的文章:https://blog.csdn.net/weixin_43858126/article/details/86529782

遇到的坑:

1、这个代码是ipv4下的代码,我在改造的时候,里面的阿里云签名代码一直出错,所以我就下载了阿里云cli,用阿里云cli来解析域名,代码量变少了,设置也成功了。

2、原来代码中的get_recordid()少打了一个空格,得不到recordid,我改过来了。

3、在阿里云设置获取access key和secret时,我把RAM子用户的权限没有设置,设置后就成功了。

阿里云cli参考:https://help.aliyun.com/product/29991.html

阿里云解析参考:https://help.aliyun.com/product/29697.html

我的联系方式:QQ:306805680 微信:shuizhongyue-_

我的黑群晖网址:http://nas.cpsj.pub:5000/ 为了节省电,没有经常开,且ipv4不能访问,只能用ipv6。

黑群晖ipv4访问地址:http://nas.qunhui.caojiawan.cn/(利用frp内网穿透实现)

我的博客地址:https://caojiawan.cn/

阿里ddns其他设置代码:

#!/bin/bash

# 更新日志
# Update 20180914 :
# [Fix] 再次修复: CPU 100%占用问题
#       这次找到了AliDDNS卡100%死循环的原因,并且加了一个小的检测机制,理论上应该不会再出现
#       CPU卡100%的问题了(如果有问题请私信脚本作者,谢谢!)

BuildTime=20180914

# 专家模式开关
# 注意: 只有当你了解整个AliDDNS工作流程,并且有一定的动手能力,希望对AliDDNS脚本的更多参数进行
#       深度定制时,你可以打开这个开关,会提供更多可以设置的选项,但如果你不懂、超级小白,请不要
#       打开这个开关!因打开专家模式后配置失误发生的问题,作者不负任何责任!
#       如需打开专家模式,请将脚本文件中的 Switch_AliDDNS_ExpertMode 变量值设置为1,即可打开
#       专家模式,如需关闭,请将此值设置为0!
Switch_AliDDNS_ExpertMode=0

# ===================================================================================
#
# 下面的代码均为程序的核心代码,请不要触动任何地方的代码,直接运行脚本即可使用!
#
# ===================================================================================

# Shell环境初始化
# 字体颜色定义
Font_Black=33[30m  
Font_Red=33[31m 
Font_Green=33[32m  
Font_Yellow=33[33m  
Font_Blue=33[34m  
Font_Purple=33[35m  
Font_SkyBlue=33[36m  
Font_White=33[37m 
Font_Suffix=33[0m
# 消息提示定义
Msg_Info=${Font_Blue}[Info] ${Font_Suffix}
Msg_Warning=${Font_Yellow}[Warning] ${Font_Suffix}
Msg_Error=${Font_Red}[Error] ${Font_Suffix}
Msg_Success=${Font_Green}[Success] ${Font_Suffix}
Msg_Fail=${Font_Red}[Failed] ${Font_Suffix}
# Shell变量开关初始化
Switch_env_is_root=0
Switch_env_curl_exist=0
Switch_env_openssl_exist=0
Switch_env_nslookup_exist=0
Switch_env_sudo_exist=0
Switch_env_system_release=none
# AliDDNS组件-变量初始化
AliDDNS_DomainName=
AliDDNS_SubDomainName=
AliDDNS_TTL=
AliDDNS_AK=
AliDDNS_SK=
AliDDNS_LocalIP=
AliDDNS_DomainServerIP=
# ServerChan组件-变量初始化
Switch_ServerChan_Enable=0
ServerChan_SCKEY=
ServerChan_Text=
ServerChan_Content=

# Shell脚本信息显示
echo -e ${Font_Green}
#=========================================================
# AliDDNS 工具 (阿里云云解析修改工具)
# 
# Build:    ${BuildTime}
# 支持平台:  CentOS/Debian/Ubuntu
# 作者:     iLemonrain (原作者: kyriosli/koolshare-aliddns)
# Blog:     https://blog.ilemonrain.com
# E-mail:   ilemonrain@ilemonrain.com
#========================================================

${Font_suffix}

# 检查Root权限,并配置开关
function_Check_Root(){
  if [ `id -u` != 0 ]; then
        Switch_env_is_root=0
    else
        Switch_env_is_root=1
    fi
}

function_Check_Enviroment(){
    if [ -f /usr/bin/curl ]; then
        Switch_env_curl_exist=1
    else
        Switch_env_curl_exist=0
    fi
    if [ -f /usr/bin/openssl ]; then
        Switch_env_openssl_exist=1
    else
        Switch_env_openssl_exist=0
    fi
    if [ -f /usr/bin/nslookup ]; then
        Switch_env_nslookup_exist=1
    else
        Switch_env_nslookup_exist=0
    fi
    if [ -f /usr/bin/sudo ]; then
        Switch_env_sudo_exist=1
    else
        Switch_env_sudo_exist=0
    fi
    if [ -f /etc/redhat-release ]; then
        Switch_env_system_release=centos
    elif [ -f /etc/lsb-release ]; then
        Switch_env_system_release=ubuntu
    elif [ -f /etc/debian_version ]; then
        Switch_env_system_release=debian
    else
        Switch_env_system_release=unknown
    fi
}

function_Install_Enviroment(){
    if [ ${Switch_env_curl_exist} = 0 ] || [ ${Switch_env_openssl_exist} = 0 ] || [ ${Switch_env_nslookup_exist} = 0 ]; then
        echo -e ${Msg_Warning}未检查到必需组件或者组件不完整,正在尝试安装……
        if [ ${Switch_env_is_root} = 1 ]; then
            if [ ${Switch_env_system_release} = centos ]; then
                echo -e ${Msg_Info}检测到系统分支:CentOS
                echo -e ${Msg_Info}正在安装必需组件……
                yum install curl bind-utils openssl -y
            elif [ ${Switch_env_system_release} = ubuntu ]; then
                echo -e ${Msg_Info}检测到系统分支:Ubuntu
                echo -e ${Msg_Info}正在安装必需组件……
                apt-get install curl dnsutils openssl -y
            elif [ ${Switch_env_system_release} = debian ]; then
                echo -e ${Msg_Info}检测到系统分支:Debian
                echo -e ${Msg_Info}正在安装必需组件……
                apt-get install curl dnsutils openssl -y
            else
                echo -e ${Msg_Warning}系统分支未知,取消环境安装,建议手动安装环境!
            fi
            if [ -f /usr/bin/curl ]; then
                Switch_env_curl_exist=1
            else
                Switch_env_curl_exist=0
                echo -e ${Msg_Error}curl组件安装失败!可能会影响到程序运行!建议手动安装!
            fi
            if [ -f /usr/bin/openssl ]; then
                Switch_env_openssl_exist=1
            else
                Switch_env_openssl_exist=0
                echo -e ${Msg_Error}openssl组件安装失败!可能会影响到程序运行!建议手动安装!
            fi
            if [ -f /usr/bin/nslookup ]; then
                Switch_env_nslookup_exist=1
            else
                Switch_env_nslookup_exist=0
                echo -e ${Msg_Error}nslookup组件安装失败!可能会影响到程序运行!建议手动安装!
            fi
        elif [ -f /usr/bin/sudo ]; then
            echo -e ${Msg_Warning}检测到当前脚本并非以root权限启动,正在尝试通过sudo命令安装……
            if [ ${Switch_env_system_release} = centos ]; then
                echo -e ${Msg_Info}检测到系统分支:CentOS
                echo -e ${Msg_Info}正在安装必需组件 (使用sudo)……
                sudo yum install curl bind-utils -y
            elif [ ${Switch_env_system_release} = ubuntu ]; then
                echo -e ${Msg_Info}检测到系统分支:Ubuntu
                echo -e ${Msg_Info}正在安装必需组件 (使用sudo)……
                sudo apt-get install curl dnsutils -y
            elif [ ${Switch_env_system_release} = debian ]; then
                echo -e ${Msg_Info}检测到系统分支:Debian
                echo -e ${Msg_Info}正在安装必需组件 (使用sudo)……
                sudo apt-get install curl dnsutils -y
            else
                echo -e ${Msg_Warning}系统分支未知,取消环境安装,建议手动安装环境!
            fi
        else
            echo -e ${Msg_Error}系统缺少必需环境,并且无法自动安装,建议手动安装!
        fi
    fi
}

# 判断是否有已存在的配置文件 (是否已经配置过环境)
function_AliDDNS_CheckConfig(){
    if [ -f /etc/OneKeyAliDDNS/config.cfg ]; then
        echo -e ${Msg_Info}检测到存在的配置,自动读取现有配置n       如果你不需要,请通过菜单中的清理环境选项进行清除
        # 读取配置文件
        AliDDNS_DomainName=`sed '/^AliDDNS_DomainName=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        AliDDNS_SubDomainName=`sed '/^AliDDNS_SubDomainName=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        AliDDNS_TTL=`sed '/^AliDDNS_TTL=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        AliDDNS_AK=`sed '/^AliDDNS_AK=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        AliDDNS_SK=`sed '/^AliDDNS_SK=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        AliDDNS_LocalIP=`sed '/^AliDDNS_LocalIP=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        AliDDNS_DomainServerIP=`sed '/^AliDDNS_DomainServerIP=/!d;s/.*=//' /etc/OneKeyAliDDNS/config.cfg | sed 's///g'`
        if [ ${AliDDNS_DomainName} =  ] || [ ${AliDDNS_SubDomainName} = 0 ] || [ ${AliDDNS_TTL} =  ] 
                || [ ${AliDDNS_AK} =  ] || [ ${AliDDNS_SK} =  ] || [ ${AliDDNS_LocalIP} =  ] 
                || [ ${AliDDNS_DomainServerIP} =  ]; then
            echo -e ${Msg_Error}配置文件有误,请检查配置文件,或者建议清理环境后重新配置 !
            exit 1
        fi
        Switch_AliDDNS_Config_Exist=1
    else
        Switch_AliDDNS_Config_Exist=0
    fi
}

function_AliDDNS_SetConfig(){
    # AliDDNS_DomainName
    if [ ${AliDDNS_DomainName} =  ]; then
        echo -e n${Msg_Info}请输入一级域名 (比如 example.com)
      read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_DomainName
        [ ${AliDDNS_DomainName} = h ] && function_document_AliDDNS_DomainName && echo -e ${Msg_Info}请输入一级域名 (比如 example.com) && read -p (此项必须填写,查看提示请输入 h): AliDDNS_DomainName
        while [ -z ${AliDDNS_DomainName} ]
      do
        echo -e ${Msg_Error}此项不可为空,请重新填写
            echo -e ${Msg_Info}请输入一级域名 (比如 example.com)
          read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_DomainName
      done
    fi
    # AliDDNS_SubDomainName
    if [ ${AliDDNS_SubDomainName} =  ]; then
        echo -e n${Msg_Info}请输入二级域名 (比如 ddns)
      read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_SubDomainName
        [ ${AliDDNS_SubDomainName} = h ] && function_document_AliDDNS_SubDomainName && echo -e ${Msg_Info}请输入二级域名 (比如 ddns) && read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_SubDomainName
        while [ -z ${AliDDNS_SubDomainName} ]
      do
        echo -e ${Msg_Error}此项不可为空,请重新填写
            echo -e ${Msg_Info}请输入二级域名 (比如 ddns)
            read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_SubDomainName
      done
    fi
    # AliDDNS_TTL
    if [ ${AliDDNS_TTL} =  ]; then
        echo -e n${Msg_Info}请输入记录的TTL(Time-To-Live)值:
      read -p (默认为600,查看帮助请输入“h”): AliDDNS_TTL
        [ ${AliDDNS_TTL} = h ] && function_document_AliDDNS_TTL && echo -e ${Msg_Info}请输入记录的TTL(Time-To-Live)值: && read -p (默认为600): AliDDNS_TTL
        [ -z ${AliDDNS_TTL} ] && echo -e ${Msg_Info}检测到输入空值,设置AliDDNS_TTL值为:“600” && AliDDNS_TTL=600
    fi
    # AliDDNS_AK
    if [ ${AliDDNS_AK} =  ]; then
        echo -e n${Msg_Info}请输入阿里云AccessKey ID
      read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_AK
        [ ${AliDDNS_AK} = h ] && function_document_AliDDNS_AK && echo -e ${Msg_Info}请输入阿里云AccessKey ID && read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_AK
        while [ -z ${AliDDNS_AK} ]
      do
        echo -e ${Msg_Error}此项不可为空,请重新填写
            echo -e ${Msg_Info}请输入阿里云AccessKey ID
            read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_AK
      done
    fi
    # AliDDNS_SK
    if [ ${AliDDNS_SK} =  ]; then
        echo -e n${Msg_Info}请输入阿里云Access Key Secret
      read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_SK
        [ ${AliDDNS_SK} = h ] && function_document_AliDDNS_SK && echo -e ${Msg_Info}请输入阿里云Access Key Secret && read -p (默认为600): AliDDNS_SK
        while [ -z ${AliDDNS_SK} ]
      do
        echo -e ${Msg_Error}此项不可为空,请重新填写
            echo -e ${Msg_Info}请输入阿里云Access Key Secret
            read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_SK
      done
    fi
    # AliDDNS_LocalIP
    if [ ${Switch_AliDDNS_ExpertMode} = 1 ]; then
        if [ ${AliDDNS_LocalIP} =  ]; then
            echo -e n${Msg_Info}请输入获取本机IP使用的命令
          read -p (查看帮助请输入“h”): AliDDNS_LocalIP
            [ ${AliDDNS_LocalIP} = h ] && function_document_AliDDNS_LocalIP && echo -e ${Msg_Info}请输入获取本机IP使用的命令 && read -p (查看帮助请输入“h”): AliDDNS_LocalIP
            [ -z ${AliDDNS_LocalIP} ] && echo -e ${Msg_Info}检测到输入空值,设置执行命令为:“curl -s whatismyip.akamai.com” && AliDDNS_LocalIP=curl -s whatismyip.akamai.com
        fi
    else
        AliDDNS_LocalIP=curl -s whatismyip.akamai.com
    fi
    # AliDDNS_DomainServerIP
    if [ ${Switch_AliDDNS_ExpertMode} = 1 ]; then
        if [ ${AliDDNS_DomainServerIP} =  ]; then
            echo -e n${Msg_Info}请输入解析使用的DNS服务器
          read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_DomainServerIP
            [ ${AliDDNS_DomainServerIP} = h ] && function_document_AliDDNS_DomainServerIP && echo -e ${Msg_Info}请输入解析使用的DNS服务器 && read -p (此项必须填写,查看帮助请输入“h”): AliDDNS_DomainServerIP
            [ -z ${AliDDNS_DomainServerIP} ] && echo -e ${Msg_Info}检测到输入空值,设置默认DNS服务器为:“223.5.5.5” && AliDDNS_DomainServerIP=223.5.5.5
        fi
    else
        AliDDNS_DomainServerIP=223.5.5.5
    fi
}

function_AliDDNS_WriteConfig(){
    # 写入配置文件
    echo -e n${Msg_Info}正在写入配置文件……
    if [ ${Switch_env_is_root} = 1 ]; then 
        Config_configdir=/etc/OneKeyAliDDNS/
    else
        Config_configdir=~/OneKeyAliDDNS/
    fi
    mkdir -p ${Config_configdir}
    rm -f ${Config_configdir}config.cfg
    cat>${Config_configdir}config.cfg<<EOF
AliDDNS_DomainName=${AliDDNS_DomainName}
AliDDNS_SubDomainName=${AliDDNS_SubDomainName}
AliDDNS_TTL=${AliDDNS_TTL}
AliDDNS_AK=${AliDDNS_AK}
AliDDNS_SK=${AliDDNS_SK}
AliDDNS_LocalIP=${AliDDNS_LocalIP}
AliDDNS_DomainServerIP=${AliDDNS_DomainServerIP}
EOF
}

# 帮助文档
function_document_AliDDNS_DomainName(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_DomainName 说明${Font_Suffix}       
       这个参数决定你要修改的DDNS域名中,一级域名的名称。
       请保证你要配置的域名,DNS服务器已经转入阿里云云解析 (免费版企业版都可以),也就是状态
       必须为“正常”或者“未设置解析”,不可以为“DNS服务器错误”等提示。
       此参数和 AliDDNS_SubDomainName 连接到一起 (即 AliDDNS_SubDomainName.AliDDNS_DomainName)
       即为最终配置的DDNS域名。例如AliDDNS.DomainName设置为“example”,AliDDNS_SubDomainName设置为“ddns”
       连接到一起就是“ddns.example.com”n
    AliDDNS_DomainName=
}

function_document_AliDDNS_SubDomainName(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_SubDomainName 说明${Font_Suffix}       
       这个参数决定你要修改的DDNS域名中,二级域名的名称。
       请保证你要配置的域名,DNS服务器已经转入阿里云云解析 (免费版企业版都可以),也就是状态
       必须为“正常”或者“未设置解析”,不可以为“DNS服务器错误”等提示。
       此参数和 AliDDNS_SubDomainName 连接到一起 (即 AliDDNS_SubDomainName.AliDDNS_DomainName)
       即为最终配置的DDNS域名。例如AliDDNS.DomainName设置为“example”,AliDDNS_SubDomainName设置为“ddns”
       连接到一起就是“ddns.example.com”n
    AliDDNS_SubDomainName=
}

function_document_AliDDNS_TTL(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_TTL 说明${Font_Suffix}       
       这个参数决定你要修改的DDNS记录中,TTL(Time-To-Line)时长。
       越短的TTL,DNS更新生效速度越快 (但也不是越快越好,因情况而定)
       免费版产品可设置为 (600-86400) (即10分钟-1天)
       收费版产品可根据所购买的云解析企业版产品配置设置为 (1-86400) (即1秒-1天)
       请免费版用户不要设置TTL低于600秒,会导致运行报错!n
    AliDDNS_TTL=
}

function_document_AliDDNS_AK(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_AK 说明${Font_Suffix}       
       这个参数决定修改DDNS记录所需要用到的阿里云API信息 (AccessKey ID)。
       获取AccessKey ID和AccessKey Secret请移步:
       https://usercenter.console.aliyun.com/#/manage/ak
       ${Font_Red}注意:${Font_Suffix}请不要泄露你的AK/SK给任何人!
       一旦他们获取了你的AK/SK,将会直接拥有控制你阿里云账号的能力!
       为了您的阿里云账号安全,请不要随意分享AK/SK(包括请求帮助时候的截图)!
    AliDDNS_AK=
}

function_document_AliDDNS_SK(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_SK 说明${Font_Suffix}       
       这个参数决定修改DDNS记录所需要用到的阿里云API信息 (Access Key Secret)。
       获取AccessKey ID和AccessKey Secret请移步:
       https://usercenter.console.aliyun.com/#/manage/ak
       ${Font_Red}注意:${Font_Suffix}请不要泄露你的AK/SK给任何人!
       一旦他们获取了你的AK/SK,将会直接拥有控制你阿里云账号的能力!
       为了您的阿里云账号安全,请不要随意分享AK/SK(包括请求帮助时候的截图)!
    AliDDNS_SK=
}

function_document_AliDDNS_LocalIP(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_LocalIP 说明${Font_Suffix}       
       这个参数决定如何获取到本机的IP地址。
       出于稳定性考虑,默认使用whatismyip.akamai.com作为获取IP的方式,
       你也可以指定自己喜欢的获取IP方式。输入格式为需要执行的命令。
       请不要在命令中带双引号!解析配置文件时候会过滤掉!
    AliDDNS_LocalIP=
}

function_document_AliDDNS_DomainServerIP(){
    echo -e ${Msg_Info}${Font_Green}AliDDNS_DomainServerIP 说明${Font_Suffix}       
       这个参数决定如何获取到DDNS域名当前的解析记录。
       会使用nslookup命令查询,此参数控制使用哪个DNS服务器进行解析。
       默认使用“223.5.5.5”进行查询 (因为都是阿里家的东西)
    AliDDNS_DomainServerIP=
}

# 程序核心功能 ===========================================================

# 获取本机IP
function_AliDDNS_GetLocalIP(){
    echo -e ${Msg_Info}正在获取本机IP……
    if [ ${AliDDNS_LocalIP} =  ]; then
        echo -e ${Msg_Error}AliDDNS_LocalIP参数为空或无效!
        echo -e ${Msg_Fail}程序运行出现致命错误,正在退出……
        exit 1
    fi
    AliDDNS_LocalIP=`$AliDDNS_LocalIP 2>&1`
    if [ ${AliDDNS_LocalIP} =  ]; then
        echo -e ${Msg_Error}未能获取本机IP!
        echo -e ${Msg_Fail}程序运行出现致命错误,正在退出……
        exit 1
    else
        echo -e ${Msg_Info}本机IP:${AliDDNS_LocalIP}
    fi
}

# 新版获取域名IP的方法,使用腾讯云的HttpDNS
#
#function_AliDDNS_DomainIP(){
#    echo -e ${Msg_Info}正在获取 $AliDDNS_SubDomainName.$AliDDNS_DomainName 的IP……
#    AliDDNS_DomainIP=`curl -s http://119.29.29.29/d?dn=$AliDDNS_SubDomainName.$AliDDNS_DomainName`
#    if [ $? -eq 0 ]; then
#        # 如果执行成功,分离出结果中的IP地址
#        if [ ${AliDDNS_DomainIP} =  ]; then
#            echo -e ${Msg_Info}解析结果:$AliDDNS_SubDomainName.$AliDDNS_DomainName -> (结果为空)
#            echo -e ${Msg_Warning}$AliDDNS_SubDomainName.$AliDDNS_DomainName 未检测到任何有效的解析记录,可能是DNS记录不存在或尚未生效
#            echo -e ${Msg_Info}程序可能会报告InvalidParameter异常错误,如出现此错误,请前往阿里云云解析面板手动添加一条任意记录值的A解析记录即可!
#        else
#            echo -e ${Msg_Info}解析结果:$AliDDNS_SubDomainName.$AliDDNS_DomainName -> $AliDDNS_DomainIP
#        fi
#        # 进行判断,如果本次获取的新IP和旧IP相同,结束程序运行
#        if [ $AliDDNS_LocalIP = $AliDDNS_DomainIP ]
#        then
#            echo -e ${Msg_Info}当前IP ($AliDDNS_LocalIP) 与 $AliDDNS_SubDomainName.$AliDDNS_DomainName ($AliDDNS_DomainIP) 的IP相同
#            echo -e ${Msg_Success}未发生任何变动,无需进行改动,正在退出……
#            exit 0
#        fi 
#    fi
#}    

# 旧版获取域名IP的方法,如果新版方法发生异常,请删掉新版代码,取消旧版的注释,保存即可!

# 获取DDNS域名当前解析记录IP
function_AliDDNS_DomainIP(){
    echo -e ${Msg_Info}正在获取 $AliDDNS_SubDomainName.$AliDDNS_DomainName 的IP……
    AliDDNS_DomainIP=`nslookup $AliDDNS_SubDomainName.$AliDDNS_DomainName $AliDDNS_DomainServerIP 2>&1`
    if [ $? -eq 0 ]; then
        # 如果执行成功,分离出结果中的IP地址
        AliDDNS_DomainIP=`echo $AliDDNS_DomainIP | grep 'Address:' | tail -n1 | awk '{print $NF}'`
        if [ ${AliDDNS_DomainIP} =  ]; then
            echo -e ${Msg_Info}解析结果:$AliDDNS_SubDomainName.$AliDDNS_DomainName -> (结果为空)
            echo -e ${Msg_Info}$AliDDNS_SubDomainName.$AliDDNS_DomainName 未检测到任何有效的解析记录,可能是DNS记录不存在或尚未生效
        else
            echo -e ${Msg_Info}解析结果:$AliDDNS_SubDomainName.$AliDDNS_DomainName -> $AliDDNS_DomainIP
        fi
    # 进行判断,如果本次获取的新IP和旧IP相同,结束程序运行
        if [ $AliDDNS_LocalIP = $AliDDNS_DomainIP ]
        then
            echo -e ${Msg_Info}当前IP ($AliDDNS_LocalIP) 与 $AliDDNS_SubDomainName.$AliDDNS_DomainName ($AliDDNS_DomainIP) 的IP相同
            echo -e ${Msg_Success}未发生任何变动,无需进行改动,正在退出……
            exit 0
        fi 
    fi
}

function_AliDDNS_GetTimestamp(){
    echo -e ${Msg_Info}正在生成时间戳……
    timestamp=`date -u +%Y-%m-%dT%H%%3A%M%%3A%SZ`
}

urlencode() {
    # urlencode <string>
    out=
    while read -n1 c
    do
        case $c in
            [a-zA-Z0-9._-]) out=$out$c ;;
            *) out=$out`printf '%%%02X' '$c` ;;
        esac
    done
    echo -n $out
}
# URL加密命令
enc() {
    echo -n $1 | urlencode
}
# 发送请求函数
send_request() {
    local args=AccessKeyId=$AliDDNS_AK&Action=$1&Format=json&$2&Version=2015-01-09
    local hash=$(echo -n GET&%2F&$(enc $args) | openssl dgst -sha1 -hmac $AliDDNS_SK& -binary | openssl base64)
    curl -s http://alidns.aliyuncs.com/?$args&Signature=$(enc $hash)
}

# 获取记录值 (RecordID)
get_recordid() {
    grep -Eo 'RecordId:[0-9]+' | cut -d':' -f2 | tr -d ''
}

# 请求记录值 (RecordID)
query_recordid() {
    send_request DescribeSubDomainRecords SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$AliDDNS_SubDomainName.$AliDDNS_DomainName&Timestamp=$timestamp
}
# 更新记录值 (RecordID)
update_record() {
    send_request UpdateDomainRecord RR=$AliDDNS_SubDomainName&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$AliDDNS_TTL&Timestamp=$timestamp&Type=A&Value=$AliDDNS_LocalIP
}
# (Update 20180703 Bugfix : 屏蔽add_record,避免发生记录重复冲突问题,感谢 mylyne 反馈)
# 添加记录值 (RecordID)
# add_record() {
#    send_request AddDomainRecord RR=$AliDDNS_SubDomainName&DomainName=$AliDDNS_DomainName&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$AliDDNS_TTL&Timestamp=$timestamp&Type=A&Value=$AliDDNS_LocalIP
# }

# RecordID更新
function_AliDDNS_UpdateRecord(){
    echo -e ${Msg_Info}正在更新记录……
    if [ ${AliDDNS_RecordID} =  ]; then
        echo -e ${Msg_Info}正在获取RecordID……
        AliDDNS_RecordID=`query_recordid | get_recordid`
        if [ ${AliDDNS_RecordID} =  ]; then
            echo -e ${Msg_Warning}未能获取到RecordID,可能没有检测到有效的解析记录 (RecordID:$AliDDNS_RecordID)
        else
            echo -e ${Msg_Info}RecordID -> $AliDDNS_RecordID
            echo -e ${Msg_Info}正在更新解析记录:$AliDDNS_SubDomainName.$AliDDNS_DomainName -> $AliDDNS_LocalIP ……
            update_record $AliDDNS_RecordID
            echo -e n${Msg_Info}已经更新RecordID:$AliDDNS_RecordID
        fi
    fi
    if [ ${AliDDNS_RecordID} =  ]; then
        # 输出失败结果 (因为没有获取到RecordID)
        echo -e ${Msg_Fail}DDNS记录更新失败!
        exit 1
    else
        # 输出成功结果
        echo -e ${Msg_Success}DDNS记录更新成功,新的IP为:$AliDDNS_LocalIP
        # ServerChan推送组件
        function_ServerChan_SuccessMsgPush
        exit 0
    fi
}

function_AliDDNS_CleanEnviroment(){
    rm -f /etc/OneKeyAliDDNS/config.cfg
    rm -f ~/OneKeyAliDDNS/config.cfg
    rm -f /etc/OneKeyAliDDNS/config-ServerChan.cfg
    rm -f ~/OneKeyAliDDNS/config-ServerChan.cfg
    Switch_env_is_root=0
    AliDDNS_DomainName=
    AliDDNS_SubDomainName=
    AliDDNS_TTL=
    AliDDNS_AK=
    AliDDNS_SK=
    AliDDNS_LocalIP=
    AliDDNS_DomainServerIP=
    Switch_ServerChan_Enable=0
    ServerChan_SCKEY=
    ServerChan_Text=
    ServerChan_Content=
}

function_AliDDNS_ShowVersion(){
    echo -e 
# AliDDNS 工具 (阿里云云解析修改工具)
# 
# Build:    ${BuildTime}
# 支持平台:  CentOS/Debian/Ubuntu
# 作者:     iLemonrain (原作者: kyriosli/koolshare-aliddns)
# Blog:     https://blog.ilemonrain.com
# E-mail:   ilemonrain@ilemonrain.com

exit 0
}

function_ServerChan_Configure(){
    if [ ${ServerChan_SCKEY} =  ]; then
        echo -e n${Msg_Info}请输入ServerChan SCKEY:
      read -p (此项必须填写): ServerChan_SCKEY
        [ ${ServerChan_SCKEY} = h ] && function_document_ServerChan_SCKEY && echo -e ${Msg_Info}请输入ServerChan SCKEY: && read -p (此项必须填写,查看提示请输入 h): ServerChan_SCKEY
        while [ -z ${ServerChan_SCKEY} ]
      do
        echo -e ${Msg_Error}此项不可为空,请重新填写
            echo -e ${Msg_Info}请输入ServerChan SCKEY:
          read -p (此项必须填写): ServerChan_SCKEY
      done
    fi
        if [ ${ServerChan_ServerFriendlyName} =  ]; then
        echo -e n${Msg_Info}请输入服务器名称:请使用中文/英文,不要使用除了英文下划线以外任何符号
      read -p (此项必须填写,便于识别): ServerChan_ServerFriendlyName
        [ ${ServerChan_ServerFriendlyName} = h ] && function_document_ServerChan_ServerFriendlyName && echo -e ${Msg_Info}请输入服务器名称:请使用中文/英文,不要使用除了英文下划线以外任何符号 && read -p (此项必须填写,便于识别): ServerChan_ServerFriendlyName
        while [ -z ${ServerChan_ServerFriendlyName} ]
      do
        echo -e ${Msg_Error}此项不可为空,请重新填写
            echo -e ${Msg_Info}请输入服务器名称:请使用中文/英文,不要使用除了英文下划线以外任何符号
          read -p (此项必须填写,便于识别): ServerChan_ServerFriendlyName
      done
    fi
}

function_ServerChan_CheckConfig(){
    if [ -f /etc/OneKeyAliDDNS/config-ServerChan.cfg ]; then
        Switch_ServerChan_ConfigExist=1
    else
        Switch_ServerChan_ConfigExist=0
    fi
}

function_ServerChan_ReadConfig(){
    if [ -f /etc/OneKeyAliDDNS/config-ServerChan.cfg ]; then
        # 读取配置文件
        Switch_ServerChan_Enable=`sed '/^Switch_ServerChan_Enable=/!d;s/.*=//' /etc/OneKeyAliDDNS/config-ServerChan.cfg | sed 's///g'`
        ServerChan_ServerFriendlyName=`sed '/^ServerChan_ServerFriendlyName=/!d;s/.*=//' /etc/OneKeyAliDDNS/config-ServerChan.cfg | sed 's///g'`
        ServerChan_SCKEY=`sed '/^ServerChan_SCKEY=/!d;s/.*=//' /etc/OneKeyAliDDNS/config-ServerChan.cfg | sed 's///g'`
        # 开关变量设1
        Switch_ServerChan_ConfigExist=1
    else
        Switch_ServerChan_ConfigExist=0
    fi
}

function_ServerChan_WriteConfig(){
    # 写入配置文件
    echo -e n${Msg_Info}正在写入配置文件……
    if [ ${Switch_env_is_root} = 1 ]; then 
        Config_configdir=/etc/OneKeyAliDDNS/
    else
        Config_configdir=~/OneKeyAliDDNS/
    fi
    mkdir -p ${Config_configdir}
    rm -f ${Config_configdir}config-ServerChan.cfg
    cat>${Config_configdir}config-ServerChan.cfg<<EOF
Switch_ServerChan_Enable=${Switch_ServerChan_Enable}
ServerChan_ServerFriendlyName=${ServerChan_ServerFriendlyName}
ServerChan_SCKEY=${ServerChan_SCKEY}
EOF
}

# 如果你有动手能力,可以尝试定制ServerChan推送的消息内容
function_ServerChan_SuccessMsgPush(){
    function_ServerChan_ReadConfig
    if [ ${Switch_ServerChan_ConfigExist} = 1 ]; then
        if [ ${Switch_ServerChan_Enable} = 1 ]; then
            echo -e ${Msg_Info}检测到ServerChan配置,正在推送消息到ServerChan平台……
            ServerChan_Text=服务器IP发生变动_AliDDNSv2
            ServerChan_Content=服务器:${ServerChan_ServerFriendlyName},新的IP为:$AliDDNS_LocalIP,请注意服务器状态
            curl -s http://sc.ftqq.com/$ServerChan_SCKEY.send?text=${ServerChan_Text} -d &desp=${ServerChan_Content}
            if [ $? -eq 0 ]; then
                echo -e n${Msg_Success}ServerChan 推送成功,服务器IP变动消息已经送达微信,请注意查收
            else
                echo -e ${Msg_Warning}ServerChan 推送失败 (curl命令执行出现异常)
            fi
        fi
    fi
    rm -f /etc/OneKeyAliDDNS/_ServerChan_tmp_output
}

Entrance_AliDDNS_Configure_And_Run(){
    function_Check_Root
    function_Check_Enviroment
    function_Install_Enviroment
    function_AliDDNS_CheckConfig
    function_AliDDNS_SetConfig
    function_AliDDNS_WriteConfig
    function_AliDDNS_GetLocalIP
    function_AliDDNS_DomainIP
    function_AliDDNS_GetTimestamp
    function_AliDDNS_UpdateRecord
    exit 0
}

Entrance_AliDDNS_RunOnly(){
    function_AliDDNS_CheckConfig
    if [ ${Switch_AliDDNS_Config_Exist} = 0 ]; then
        echo -e ${Msg_Error} 未检测到任何有效配置,请先不带参数运行程序以进行配置!
        exit 1
    fi
    function_Check_Enviroment
    function_Install_Enviroment
    function_AliDDNS_GetLocalIP
    function_AliDDNS_DomainIP
    function_AliDDNS_GetTimestamp
    function_AliDDNS_UpdateRecord
    exit 0
}

Entrance_AliDDNS_ConfigureOnly(){
    function_Check_Root
    function_Check_Enviroment
    function_Install_Enviroment
    function_AliDDNS_CheckConfig
    function_AliDDNS_SetConfig
    function_AliDDNS_WriteConfig
    echo -e ${Msg_Success}配置文件写入完成
    exit 0
}

Entrance_ServerChan_Config(){
    function_Check_Root
    function_Check_Enviroment
    function_ServerChan_CheckConfig
    if [ ${Switch_ServerChan_ConfigExist} = 1 ]; then
        echo -e ${Msg_Info}ServerChan配置文件已存在,如需重新配置请执行清理环境!
        exit 0
    else
        Switch_ServerChan_Enable=1
        function_ServerChan_Configure
        function_ServerChan_WriteConfig
    fi
    echo -e ${Msg_Success}配置文件写入完成,重新执行脚本即可激活ServerChan功能
    echo -e ${Msg_Info}如需禁用ServerChan,执行清理环境即可
    exit 0
}

Entrance_Global_CleanEnv(){
    echo -e ${Msg_Info}正在清理环境……
    function_AliDDNS_CleanEnviroment
    echo -e ${Msg_Success}环境清理完成,重新执行脚本以开始配置
    exit 0
}

Entrance_Version(){
    function_AliDDNS_ShowVersion
    exit 0
}

case $1 in
    run)
        Entrance_AliDDNS_RunOnly
        ;;
    config)
        Entrance_AliDDNS_ConfigureOnly
        ;;
    clean)
        Entrance_Global_CleanEnv
        ;;
    clean)
        Entrance_Version
        ;;
    *)
        echo -e ${Font_Blue} AliDDNS 工具 (阿里云云解析修改工具)${Font_Suffix} 

使用方法 (Usage):
AliDDNS.sh run       配置并运行工具 (如果已有配置将会直接运行)
AliDDNS.sh config    仅配置工具
AliDDNS.sh clean     清理配置文件及运行环境
AliDDNS.sh version   显示版本信息

        ;;
esac

echo -e ${Msg_Info}选择你要使用的功能: 
echo -e  1. 配置并运行 AliDDNS n 2. 仅配置 AliDDNS n 3. 仅运行 AliDDNS n 4. 配置ServerChan微信推送 n 5. 清理环境 n 0. 退出 n
read -p 输入数字以选择: Function

if [ ${Function} == 1 ]; then
  Entrance_AliDDNS_Configure_And_Run
elif [ ${Function} == 2 ]; then
  Entrance_AliDDNS_ConfigureOnly
elif [ ${Function} == 3 ]; then
  Entrance_AliDDNS_RunOnly
elif [ ${Function} == 4 ]; then
  Entrance_ServerChan_Config
elif [ ${Function} == 5 ]; then
  Entrance_Global_CleanEnv
else
    exit 0
fi

python代码:

#!/usr/bin/env python
# coding=utf-8
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest
from  aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest
import urllib.request
import json
import time
import argparse

# 利用API获取IP
def getRealIp():
    url = https://api.ipify.org/?format=json
    response = urllib.request.urlopen(url)
    html = response.read().decode('utf-8')
    jsonData = json.loads(html)
    return jsonData['ip']

# 利用API获取IP
def getRealIpV6():
    url = https://v6.ident.me/.json
    response = urllib.request.urlopen(url)
    html = response.read().decode('utf-8')
    jsonData = json.loads(html)
    return jsonData['address']

def getRecords(client,rr,domain):
    request= DescribeDomainRecordsRequest()
    request.set_accept_format('json')
    request.set_DomainName(domain)
    request.set_RRKeyWord(rr)
    response = client.do_action_with_exception(request)
    print(str(response, encoding='utf-8'))
    jsonData = json.loads(response)
    return jsonData['DomainRecords']['Record']

def addDomainRecord(client,rr,domain,ip,type):
    request = AddDomainRecordRequest()
    request.set_accept_format('json')
    request.set_Value(ip)
    request.set_Type(type)
    request.set_RR(rr)
    request.set_DomainName(domain)
    response = client.do_action_with_exception(request)
    print(str(response, encoding='utf-8'))
    return json.loads(response)['RecordId']

def updateDomainRecord(client,rr, domain, ip, type):
    records = getRecords(client,rr,domain)
    record_id=None
    for record in records:
        if record['RR'] == rr and record['DomainName']==domain and record['Type']==type:
            record_id=record['RecordId']
            avail_ip=record['Value']
            avail_record=record
            break
    if record_id is None:
        print(不存在记录,正在添加记录)
        addDomainRecord(client,rr,domain,ip,type)
    else:
        print(存在记录:+str(avail_record))
        if avail_ip==ip:
            print(ip未改变,不更改记录,原ip=+avail_ip+,现ip=+ip)
        else:
            print(ip已改变,准备更改记录,原ip=+avail_ip+,现ip=+ip)
            request=UpdateDomainRecordRequest()
            request.set_action_name(UpdateDomainRecord)
            request.set_RR(rr)
            request.set_RecordId(record_id)
            request.set_Type(type)
            request.set_Value(ip)
            request.set_TTL(600)
            request.set_accept_format('json')
            response = client.do_action_with_exception(request)
            print(str(response, encoding='utf-8'))
            return json.loads(response)['RecordId']

#updateDomainRecord('pan4','quancs.site',getRealIp())

if __name__ == __main__:
    parser = argparse.ArgumentParser()
    parser.description = '阿里云云解析工具'
    parser.add_argument(key, help=从https://ak-console.aliyun.com/#/accesskey得到的AccessKeyId, type=str)
    parser.add_argument(secret, help=从https://ak-console.aliyun.com/#/accesskey得到的AccessKeySecret, type=str)
    parser.add_argument(rr,help=RR例子:@, *, www, ..., type=str)
    parser.add_argument(domain, help=domain例子: aliyun.com, baidu.com, google.com, ..., type=str)
    parser.add_argument(--ipv6, help=使用本机的ipv6地址,action=store_true)
    args = parser.parse_args()
    if args.ipv6:
        ip=getRealIpV6()
        type=AAAA
    else:
        ip=getRealIp()
        type=A
    print(本机IP:  + ip)

    client = AcsClient(args.key, args.secret, 'cn-hangzhou')
    updateDomainRecord(client,args.rr,args.domain,ip,type)

发表评论

邮箱地址不会被公开。 必填项已用*标注