Skip to content

Instantly share code, notes, and snippets.

@billryan
Forked from chuangbo/README.md
Last active August 30, 2022 13:41
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save billryan/239778f0821937939c8c140bdddd6840 to your computer and use it in GitHub Desktop.
Save billryan/239778f0821937939c8c140bdddd6840 to your computer and use it in GitHub Desktop.
DNSPod DDNS Python Script

替换上你的ID, Token, domain, sub_domain 就可以运行了。(ID,Token) 可以从 API 鉴权方式升级为 Token 获得。 脚本会在后台一直运行,初始化时会根据 sub_domain 查询是否已经创建,每隔30秒检查一遍IP,如果修改了就更新IP。

以 Archlinux 为例,按照如下步骤操作即可设置开机启动这个 DDNS 服务。

sudo wget -O /usr/local/bin/dnspod_ddns.py https://gist.github.com/billryan/239778f0821937939c8c140bdddd6840/raw/dnspod_ddns.py
sudo chmod +x /usr/local/bin/dnspod_ddns.py
sudo wget -O /etc/systemd/system/dnspod-ddns.py.service https://gist.github.com/billryan/239778f0821937939c8c140bdddd6840/raw/dnspod-ddns.service
sudo systemctl start dnspod-ddns
sudo systemctl enable dnspod-ddns

更详细的教程可移步 https://blog.yuanbin.me/posts/2016/07/DDNS-for-home-server.html

[Unit]
Description=DNSPod DDNS Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/dnspod_ddns.py
KillSignal=SIGINT
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import requests
import time
import logging
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)
class DNSPod(object):
"""DNSPod ddns application."""
def __init__(self, params):
"""Initialize with params."""
self._params = params
def run(self, params=None):
if params is None:
params = self._params
public_ip = self.get_public_ip()
# get record_id of sub_domain
record_list = self.get_record_list(params)
if record_list['code'] == '10':
# create record for empty sub_domain
record_id = self.create_record(params, public_ip)
remote_ip = public_ip
elif record_list['code'] == '1':
# get record id
record_id = record_list['record_id']
remote_ip = record_list['ip_value']
else:
logger.error('!!!can not get record_id!!!')
return -1
params['record_id'] = record_id
current_ip = remote_ip
while True:
try:
public_ip = self.get_public_ip()
if current_ip != public_ip:
logger.warning("update IP from %s to %s" % (current_ip, public_ip))
if self.ddns(params, public_ip):
current_ip = public_ip
else:
logger.info("IP remains %s" % public_ip)
except Exception as e:
logger.error(e)
pass
time.sleep(30)
def get_public_ip(self):
"""Get public ip via dnspod."""
sock = socket.create_connection(('ns1.dnspod.net', 6666), timeout=30)
ip = sock.recv(16)
sock.close()
return ip.decode('utf-8')
def get_record_list(self, params):
"""Get record list.
https://www.dnspod.cn/docs/records.html#record-list
:return: dict of code, record_id and IP value
"""
record_list_url = 'https://dnsapi.cn/Record.List'
r = requests.post(record_list_url, data=params)
code = r.json()['status']['code']
record_id = r.json()['records'][0]['id'] if code == '1' else ""
ip_value = r.json()['records'][0]['value'] if code == '1' else ""
return dict(code=code, record_id=record_id, ip_value=ip_value)
def create_record(self, params, ip):
"""Create record if not created before.
https://www.dnspod.cn/docs/records.html#record-create
:return: record_id of new record
"""
params['value'] = ip
record_create_url = 'https://dnsapi.cn/Record.Create'
r = requests.post(record_create_url, data=params)
logger.warning('create new record %s.%s with IP %s' % (params['sub_domain'], params['domain'], ip))
assert r.json()['status']['code'] == '1'
record_id = r.json()['record']['id']
return record_id
def ddns(self, params, ip):
"""Update ddns ip.
https://www.dnspod.cn/docs/records.html#dns
"""
params['value'] = ip
ddns_url = 'https://dnsapi.cn/Record.Ddns'
r = requests.post(ddns_url, data=params)
logger.info('status: %s, reason: %s' % (r.status_code, r.reason))
return r.json()['status']['code'] == '1'
def main():
# initialize params
# Use Token, check https://support.dnspod.cn/Kb/showarticle/tsid/227
ID = '23333' # replace with your ID
Token = '233333333333333333333333' # replace with your Token
params = dict(
login_token=("%s,%s" % (ID, Token)),
format='json',
domain='example.com', # replace with your domain
sub_domain='test', # replace with your sub_domain
record_type='A',
record_line='默认'
)
dnspod = DNSPod(params)
dnspod.run()
if __name__ == "__main__":
main()
@StarDuster
Copy link

readme 有手误,
sudo wget -O /etc/systemd/system/dnspod-ddns.py.service https://gist.github.com/billryan/239778f0821937939c8c140bdddd6840/raw/dnspod-ddns.service
应为
sudo wget -O /etc/systemd/system/dnspod-ddns.service https://gist.github.com/billryan/239778f0821937939c8c140bdddd6840/raw/dnspod-ddns.service

@rankun203
Copy link

rankun203 commented Aug 30, 2022

If your get_public_ip also failed, try to replace it with this:

    def get_public_ip(self):
        """Get public ip via dnspod."""
        res = requests.get("http://www.net.cn/static/customercare/yourip.asp")
        matches = re.search('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', res.text)
        ip = matches.group(0)
        return ip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment