DDNS No-IP自动更新IPv6地址的的Python脚本
目前No-IP的更新工具暂不支持更新ipv6,而我的公网ip来自手机热点,所以公网ip并非是固定的,有需要更新ip的需求。因此写了个脚本。参考官网的协议完成
官网协议地址:https://www.noip.com/integrate/request
源码供参考,如果有帮到您的话可以给一个赞吗:
import socket
import base64
import os
import re
import time
class netParam:
def __init__(self):
self.host = "dynupdate.no-ip.com"
self.usrname = "xxxxxxxx@xxxxxx.com"
self.passwd = "xxxxxxxxxxxxxxxx"
self.domain = "xxxxxxxxxxx.ddns.net"
self.timeval = 5 * 60
self.server_port = 80
def getIPv6Address():
output = os.popen("ipconfig /all").read()
# print(output)
result = re.findall(r"(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})", output, re.I)
return result[0][0]
def getip(domain):
address = socket.getaddrinfo(domain, 'http')
return address[0][4][0]
if __name__ == "__main__":
param = netParam()
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 不经过WAIT_TIME,直接关闭
tcp_sock.setblocking(False) # 设置非阻塞编程
tcp_sock.settimeout(1)
link_statu = False
send_data_len = 0
old_ipv6addr = ""
fisrt_flag = True
# 按协议,对usrname:passwd进行base64编码
raw_key = param.usrname + ":" + param.passwd
print("raw key: " + raw_key)
encode_key = base64.b64encode(raw_key.encode("utf-8"))
encode_key = str(encode_key)[2:len(str(encode_key)) - 1]
print("encode key: " + encode_key)
#构造请求头部的内容,由于本机ip可能变化,因此这里没有直接把GET方法写进去,而是放在循环体中做
requestParam = ""
#requestParam += "GET /nic/update?hostname=" + param.domain + ""
requestParam += "Host: dynupdate.no-ip.com\r\n"
requestParam += "Authorization: Basic " + encode_key + "\r\n"
requestParam += "User-Agent: None\r\n\r\n"
print("request:\n" + requestParam)
while(True):
# 每次运行等待timeval(此处是5分钟)的间隔,避免频繁更新
if (True != fisrt_flag):
time.sleep(param.timeval)
fisrt_flag = False
# 获取ipv6地址,若地址没有发生改变,则不上报更新
ipv6addr = getIPv6Address()
if ('2' != ipv6addr[0] or '4' != ipv6addr[1] or '0' != ipv6addr[2]):
print("ipv6 addr invalid!")
continue
if (0 != len(ipv6addr)):
print("ipv6 addr: " + ipv6addr)
if (ipv6addr == old_ipv6addr):
print("ip not change, continue")
continue
# 构造请求的头部GET方法内容
requestHead = "GET "
requestHead += "/nic/update?hostname=" + param.domain + "&myip=" + ipv6addr + " HTTP/1.1\r\n"
# 建立tcp连接
if (False == link_statu):
server_ip = getip(param.host)
print("server ip is :" + server_ip)
try:
tcp_sock.connect((server_ip, param.server_port))
print("connect server success")
link_statu = True
except Exception as err:
print("connect server failed, exception:", err)
continue
# 发送数据
send_data = requestHead + requestParam
send_data_len = 0
while send_data_len < len(send_data):
time.sleep(0.1)
try:
send_data_len += tcp_sock.send(send_data[send_data_len:].encode())
print("send " + str(send_data_len) + " data")
except Exception as err:
print("send data error, exception: ", err)
print("close tcp socket")
tcp_sock.close()
link_statu = False
break
if (send_data_len != len(send_data)):
continue
print("send data:" + send_data)
# 检查结果,更新成功则把当前ip记录为旧ip
if (True == link_statu):
try:
recv_data = tcp_sock.recv(2048)
print("server reply:\n" + str(recv_data))
except Exception as err:
print("recv data error, exception: ", err)
tcp_sock.close()
link_statu = False
if (-1 != str(recv_data).find("HTTP/1.1 200 OK")):
old_ipv6addr = ipv6addr
print("update ip success")
print("end")