【群晖】自动获取动态IPV4并解析到阿里云域名

九术AI

【群晖】自动获取动态IPV4并解析到阿里云域名

首先需要你的域名是在阿里云进行解析使用的才行

获取阿里云的权限

  1. 登录控制台,在头像下面进入 “AccessKey管理” 页面
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  2. 为了安全原因,建议在“用户”-“创建用户”中创建一个专用帐号(需要对子帐号设置单独的权限,否则无法正常操作API)
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  3. 创建成功后会出现下面的页面,页面中右侧会显示 AccessKey ID 和 AccessKey Secret ,找地方保存值,后面会用到
  4. 返回用户管理页面,选择刚才创建的用户,选择添加权限
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  5. 点击“域名”相关的权限添加到右侧中
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  6. 点击“解析”相关的权限并添加
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  7. 保存并退出权限页面

编写脚本

注意修改 if name == ‘main’ 方法中的各个参数值

根据实际需求修改 def __execute() 方法中的各项属性值

修改__execute方法中的your.domain为你自己的站点域名

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
    @Time    : 2023/08/23
    @Author  : LXW
    @Site    : 
    @File    : ipv4.py
    @Software: PyCharm
    @Description:
        - 版本
        -- python==3.8
        -- alibabacloud_alidns20150109==3.0.7
        -- aliyun-python-sdk-domain==3.14.9
        - 依赖安装
        -- pip3 install alibabacloud_alidns20150109==3.0.7
        -- pip3 install aliyun-python-sdk-domain==3.14.9
"""

import json

import requests
from alibabacloud_alidns20150109 import models as alidns_20150109_models
from alibabacloud_alidns20150109.client import Client as Alidns20150109Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient


class RemoteIp:
    def __init__(self, url, username, passwd):
        self.url = url
        self.username = username
        self.passwd = passwd

    def __get_token(self):
        _url = self.url + "/emby/Users/authenticatebyname?X-Emby-Client=Emby%20Web&X-Emby-Device-Name=Chrome%20macOS&X-Emby-Device-Id=fa6b7733-23fc-4cb7-bae3-d7f0536b485e&X-Emby-Client-Version=4.7.13.0&X-Emby-Language=zh-cn"
        content = requests.post(_url, False, {"Username": self.username, "Pw": self.passwd}).text
        return json.loads(content)["AccessToken"]

    def get_remote_addr(self):
        token = self.__get_token()
        full_url = self.url + "/emby/System/Info?X-Emby-Token=" + token
        content = requests.get(full_url, False).text
        addr = list(json.loads(content)["RemoteAddresses"])
        remote_add = str(addr[0]).split(":")[1].replace("/", "")
        return remote_add

def request_params(request, value):
    request.value = value

class AliyunOperation:
    def __init__(self, access_key_id, access_secret):
        """
        初始化
        :param access_key_id: 阿里云AccessKey的ID
        :param access_secret: 阿里云AccessKey的密码
        """
        config = open_api_models.Config(
            # 必填,您的 AccessKey ID,
            access_key_id=access_key_id,
            # 必填,您的 AccessKey Secret,
            access_key_secret=access_secret
        )
        # Endpoint 请参考 https://api.aliyun.com/product/Alidns
        config.endpoint = f'alidns.cn-hangzhou.aliyuncs.com'
        self.client = Alidns20150109Client(config)

    def describe_subdomain_records(self, subdomain, domain_name):
        """
        子域名解析记录查询 https://api.aliyun.com/api/Alidns/2015-01-09/DescribeSubDomainRecords
        这个函数会返回一大堆东西,但是目前我们需要使用的就两个,一个是解析记录的数量,一个就是RecordId,RecordId修改域名解析时需要用到
        :param domain_name:
        :param subdomain:
        :return:
        """
        describe_sub_domain_records_request = alidns_20150109_models.DescribeSubDomainRecordsRequest(
            sub_domain=subdomain,
            domain_name=domain_name
        )
        runtime = util_models.RuntimeOptions()
        try:
            response = self.client.describe_sub_domain_records_with_options(describe_sub_domain_records_request,
                                                                            runtime)
            if 200 == response.status_code:
                return response.body
        except Exception as error:
            # 如有需要,请打印 error
            UtilClient.assert_as_string(error.message)

    def add_record(self, domain_name, rr, domain_type, value):
        """
        新增域名解析记录 https://api.aliyun.com/api/Alidns/2015-01-09/AddDomainRecord
        如果域名解析记录不存在时,就需要新增域名解析记录,新增域名解析记录比较简单,直接填写参数即可
        :param domain_name: 域名名称 baidu.com
        :param rr: 主机记录。如果要解析@.exmaple.com,主机记录要填写”@”,而不是空。
        :param domain_type: 解析记录类型。https://help.aliyun.com/document_detail/29805.html?spm=api-workbench.api_explorer.0.0.6b1a134bcODqcI
        :param value: 记录值。String
        :return:
        """
        add_domain_record_request = alidns_20150109_models.AddDomainRecordRequest(
            domain_name=domain_name,
            rr=rr,
            type=domain_type,
            value=value
        )
        runtime = util_models.RuntimeOptions()
        try:
            response = self.client.add_domain_record_with_options(add_domain_record_request, runtime)
            if 200 == response.status_code:
                return response.body
        except Exception as error:
            # 如有需要,请打印 error
            UtilClient.assert_as_string(error.message)

    def update_record(self, domain_type, value, rr, record_id):
        """
        更新域名解析记录
        如果域名解析记录已存在,则不能使用新增,而是更新域名解析记录。更新的时候需要用到RecordId,这个一般查询的时候就会有返回,直接使用即可
        :param domain_type: 解析记录类型。https://help.aliyun.com/document_detail/29805.html?spm=api-workbench.api_explorer.0.0.6b1a134bcODqcI
        :param value: 记录值。String
        :param rr: 主机记录。如果要解析@.exmaple.com,主机记录要填写”@”,而不是空。
        :param record_id: 解析记录的ID
        :return:
        """
        update_domain_record_request = alidns_20150109_models.UpdateDomainRecordRequest(
            record_id=record_id,
            rr=rr,
            type=domain_type,
            value=value
        )
        runtime = util_models.RuntimeOptions()
        try:
            # 复制代码运行请自行打印 API 的返回值
            self.client.update_domain_record_with_options(update_domain_record_request, runtime)
        except Exception as error:
            # 如有需要,请打印 error
            UtilClient.assert_as_string(error.message)

def __execute():
    # 获取动态 IPV4 地址(如果是IPV6也可以用相同方式获取)
    __remote_addr = __get_from_urls()
    if "None" == __remote_addr:
        __remote_addr = RemoteIp(url=__url, username=__username, passwd=__passwd).get_remote_addr()
    print("current ipv4: " + __remote_addr)
    __aliyun_client = AliyunOperation(access_key_id=__accessKeyId, access_secret=__accessSecret)
    # 查询 example.com 主机下 test.example.com 域名的解析列表
    content = __aliyun_client.describe_subdomain_records("redirect.your.domain", "your.domain")
    print("current desc domain content: " + str(content))
    if 0 == content.total_count:
        # 新增一条 test.example.com 的IPV4域名解析记录(如果是IPV6地址,修改参数 domain_type 为 AAAA)
        __aliyun_client.add_record("your.domain", "redirect", "A", __remote_addr)
    elif 1 == content.total_count:
        # 如果 test.example.com 域名解析已经存在,则进行更新操作
        source = content.domain_records.record[0]
        record_id = source.record_id
        if __remote_addr != source.value:
            __aliyun_client.update_record("A", __remote_addr, "redirect", record_id)
    # else:
    #     # 不推荐使用该方式进行域名解析更新,容易错误更新
    #     sources = content.domain_records.record
    #     for source in sources:
    #         # 因为是更新IP,所以只考虑 A 或者 AAAA
    #         domain_type = source.type
    #         if "A" == domain_type or "AAAA" == domain_type:
    #             record_id = source.record_id
    #             rr = source.rr
    #             __aliyun_client.update_record(domain_type, __remote_addr, rr, record_id)

def __get_from_urls():
    """
    通过url获取本地IP地址
        "https://myip4.ipip.net",
        "https://ddns.oray.com/checkip",
        "https://ip.3322.net",
        "https://4.ipw.cn"
    :return: ip
    """
    ipw = "https://4.ipw.cn"
    response = requests.get(ipw)
    if 200 == response.status_code:
        content = response.text
        return content.strip()
    ip = "https://ip.3322.net"
    response = requests.get(ip)
    if 200 == response.status_code:
        content = response.text
        return content.strip()
    myip4 = "https://myip4.ipip.net"
    response = requests.get(myip4)
    if 200 == response.status_code:
        content = response.text.split(":")[1]
        content = content.replace("来自于", "")
        return content.strip()
    ddns = "https://ddns.oray.com/checkip"
    response = requests.get(ddns)
    if 200 == response.status_code:
        content = response.text.split(":")[1]
        return content.strip()
    return "None"

if __name__ == '__main__':
    # emby相关参数,可以不填
    __url = "http://127.0.0.1:8096"
    __username = "emby_user"
    __passwd = "emby_passwd"
    # 域名解析权限,必填
    __accessKeyId = "__accessKeyId"
    __accessSecret = "__accessSecret"
    __execute()

运行

这里以群晖NAS举例

  1. 登录群晖“控制面板”-“终端机和SNMP”,打开SSH端口
  2. SSH登录群晖后台,查看python相关依赖(Python3.8下载可以通过套件方式直接下载,无须后台手动下载安装)
  3. 上传脚本到群晖文件夹中,这里以 “/volume1/schedule/ipv4_aliyun.py” 为例
  4. 登录“控制面板”-“任务计划”,新增任务
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  5. 创建任务,这里的用户最好选择具有管理员权限的帐号
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  6. 自定义任务执行的周期
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  7. 任务设置,这里的脚本路径必须是完整的路径,可以在“文件”管理中右键上传的脚本文件,查看属性中的路径进行复制
    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Java中,我们可以使用InetAddress类来通过域名获取IP地址。InetAddress类提供了getByName()方法,可以接受一个String类型的域名参数,并返回一个InetAddress对象,该对象包含了与该域名相关的IP地址信息。 要获取所有的IPv4和IPv6地址,我们可以使用getAddress()和getAllByName()方法。getAddress()用于获取当前主机的IP地址,而getAllByName()则返回与指定域名相关的所有IP地址。 以下是一个展示如何通过域名获取所有IPv4和IPv6的示例代码: ```java import java.net.InetAddress; import java.net.UnknownHostException; public class IPAddressExample { public static void main(String[] args) { String domainName = "www.example.com"; try { InetAddress[] addresses = InetAddress.getAllByName(domainName); for (InetAddress address : addresses) { if (address.getAddress().length == 4) { // IPv4 address System.out.println("IPv4: " + address.getHostAddress()); } else if (address.getAddress().length == 16) { // IPv6 address System.out.println("IPv6: " + address.getHostAddress()); } } } catch (UnknownHostException e) { e.printStackTrace(); } } } ``` 在上述示例中,我们首先指定了要查询的域名,然后调用InetAddress类的getAllByName()方法来获取与该域名相关的所有IP地址。接着我们通过检查返回的IP地址的长度来判断是IPv4还是IPv6地址,并将其打印输出。 需要注意的是,由于某些域名可能有多个IP地址,因此getAllByName()方法将返回一个InetAddress数组。我们需要遍历该数组来获取所有的IP地址。 希望以上信息对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CarolLXW

你的鼓励是我最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值