春风得意马蹄疾 记录技术,分享生活
随笔: 34 分类: 15 评论: 1 阅读: 2,212

华为云 FunctionGraph 云函数 DDNS:零成本维护 iBMC 域名解析

📅 发表于 2026-06-22 22:59:22 👁 阅读 52 次 💬 评论 0

为什么需要云函数 DDNS?

场景很常见:家里断电或服务器关机后,IPv6 前缀可能变化。此时服务器没开机,没法自己更新 DNS——那就需要一台 永远在线 的东西来帮你做这件事。

华为云 FunctionGraph 免费额度非常慷慨(每月 100 万次调用、40 万 GB-秒),跑一个 DDNS 脚本几乎零成本。本文记录完整的部署过程。

整体思路

  1. 云函数定时触发(每 10 分钟)
  2. DNS 解析 xiaoajun.cn 获取服务器当前 IPv6 地址
  3. 提取 IPv6 前缀(前 4 段)
  4. 用 iBMC 的 MAC 地址通过 EUI-64 算法 算出后缀
  5. 拼接出完整 iBMC IPv6 → 更新 DNS 记录 ibmc.xiaoajun.cn

关键优势:不需要直接连接 iBMC,不需要服务器开机。只要服务器曾经获取过 IPv6 地址且 DNS 记录还在,就能算出 iBMC 的地址。

EUI-64 算法

IPv6 无状态自动配置中,设备用 MAC 地址生成接口 ID:

  1. MAC: 3c:e8:24:71:e3:33
  2. 中间插入 ff:fe3c:e8:24:ff:fe:71:e3:33
  3. 第 7 位取反:3c0011 1100 → 第 7 位翻转 → 0011 11103e
  4. 结果:3ee8:24ff:fe71:e333

所以只要知道服务器前缀 + iBMC 的 MAC,就能算出 iBMC 的完整 IPv6。

前提条件

华为云 DNS 服务 已开通并有托管域名
iBMC 的 AAAA 记录 已在 DNS 中创建 ibmc.xiaoajun.cn
API 密钥 (AK/SK) 华为云「我的凭证」中创建
FunctionGraph 服务 华为云控制台开通

步骤一:获取必要参数

登录华为云控制台,记录以下信息:

# 1. AK/SK - 「我的凭证」→「访问密钥」
AK = 'HPUA...'
SK = 'f5V5...'

# 2. DNS 区域 ID - 「云解析 DNS」→ 域名 → 管理 → 基本信息
ZONE_ID = '8aac...'

# 3. Record Set ID - 点击 ibmc.xiaoajun.cn 编辑 → URL 中的 recordset_id
RECORDSET_ID = 'ff808...'

# 4. Region - 华北-北京四
REGION = 'cn-north-4'

步骤二:编写云函数代码

保存为 ddns_ibmc_cloud_sdk.py

"""iBMC DDNS - 华为云 FunctionGraph 云函数"""
import socket
from huaweicloudsdkcore.auth.credentials import BasicCredentials
from huaweicloudsdkdns.v2 import DnsClient, UpdateRecordSetRequest
from huaweicloudsdkdns.v2 import UpdateRecordSetReq, ShowRecordSetRequest
from huaweicloudsdkcore.region.region import Region

# === 配置(替换为你的实际值)===
AK = '你的AK'
SK = '你的SK'
REGION = Region(id='cn-north-4', endpoint='dns.cn-north-4.myhuaweicloud.com')
ZONE_ID = '你的ZoneID'
RECORDSET_ID = '你的RecordSetID'
# iBMC MAC: 3c:e8:24:71:e3:33 → EUI-64 后缀
IBMC_EUI64_SUFFIX = '3ee8:24ff:fe71:e333'

def handler(event, context):
    print('=== iBMC DDNS Cloud ===')

    # 1. 通过 DNS 解析获取服务器 IPv6 前缀
    server_addr = None
    for x in socket.getaddrinfo('xiaoajun.cn', None, socket.AF_INET6):
        addr = x[4][0]
        parts = addr.split(':')
        # 排除 link-local、ULA、过期地址
        if parts[0].startswith('fe8') or parts[0].startswith('fd'):
            continue
        if len(parts) > 3 and parts[3] == 'fe80':
            continue
        server_addr = addr
        break

    if not server_addr:
        print('无法获取服务器 IPv6 地址')
        return {'status': 'skip'}

    prefix = ':'.join(server_addr.split(':')[:4])
    ibmc_addr = f'{prefix}:{IBMC_EUI64_SUFFIX}'

    print(f'服务器: {server_addr}')
    print(f'前缀:   {prefix}')
    print(f'iBMC:   {ibmc_addr}')

    # 2. 创建 DNS 客户端
    cred = BasicCredentials(AK, SK)
    client = DnsClient.new_builder() \
        .with_credentials(cred) \
        .with_region(REGION) \
        .build()

    # 3. 查询当前 DNS 记录
    sr = ShowRecordSetRequest(
        zone_id=ZONE_ID,
        recordset_id=RECORDSET_ID
    )
    resp = client.show_record_set(sr)
    current = resp.records[0] if resp.records else None
    print(f'DNS 当前: {current}')

    # 4. 比较并更新
    if current == ibmc_addr:
        print('IP 未变化,无需更新')
        return {'status': 'unchanged', 'ip': ibmc_addr}

    ur = UpdateRecordSetRequest(
        zone_id=ZONE_ID,
        recordset_id=RECORDSET_ID
    )
    ur.body = UpdateRecordSetReq(records=[ibmc_addr], ttl=600)
    resp = client.update_record_set(ur)
    print(f'更新结果: {resp.status}')
    return {'status': 'updated', 'old': current, 'new': ibmc_addr}

步骤三:打包依赖(关键步骤)

华为云 FunctionGraph 不支持运行时 pip install,必须将依赖打包进 zip。

在 Linux 或 WSL 中执行:

# 1. 创建临时目录
mkdir -p /tmp/ibmc_fg

# 2. 安装依赖到该目录
pip3 install --target /tmp/ibmc_fg \
  huaweicloudsdkdns \
  huaweicloudsdkcore \
  defusedxml

# 3. 复制函数代码
cp ddns_ibmc_cloud_sdk.py /tmp/ibmc_fg/

# 4. 打包(进入目录打包,确保解压后代码在根目录)
cd /tmp/ibmc_fg
zip -r ~/ibmc_ddns_fg.zip .

打包后 zip 大约 5MB,包含所有递归依赖。

步骤四:上传到华为云 FunctionGraph

  1. 控制台 → 函数工作流 FunctionGraph
  2. 创建函数 → 选择:
    • 运行时:Python 3.10
    • 上传方式:zip 包
    • 入口函数:ddns_ibmc_cloud_sdk.handler
  3. 上传刚才打包的 ibmc_ddns_fg.zip
  4. 创建函数后进入配置页

步骤五:配置函数

基本设置

  • 内存:128 MB(够用)
  • 超时时间:30 秒(DNS 查询 + API 调用需要一点时间)

配置定时触发器

  1. 「触发器」→「创建触发器」
  2. 选择「定时触发器」
  3. Cron 表达式:0 */10 * * * *(每 10 分钟执行一次)
  4. 点击确定

Cron 说明:华为云使用 7 位 cron 格式

秒 分 时 日 月 周 年
0  */10  *  *  *  *  *

步骤六:测试验证

在函数页面点击「测试」,创建空白测试事件并执行。

正常输出:


=== iBMC DDNS Cloud ===
服务器: 2408:8270:1034:a370:5cd8:9e55:c6b3:3
前缀:   2408:8270:1034:a370
iBMC:   2408:8270:1034:a370:3ee8:24ff:fe71:e333
DNS 当前: 2408:8270:1034:a370:3ee8:24ff:fe71:e333
IP 未变化,无需更新

费用说明

华为云 FunctionGraph 免费额度(每月):

调用次数 100 万次
资源使用 40 万 GB-秒

本脚本每 10 分钟执行一次:

  • 每月调用:约 4,320 次(4.3‱ 的免费额度)
  • 每次耗时 3-4 秒,128MB 内存:约 0.5 GB-秒/次
  • 每月资源:约 2,160 GB-秒(0.5% 的免费额度)

完全免费,放心使用。

监控与日志

在 FunctionGraph 控制台可以查看:

  • 监控信息:调用次数、成功率、执行时长
  • 日志:点击「查看函数日志」跳转到日志流,查看每次执行的详细输出

常见问题

Q: 执行报 401 错误?

A: 检查 AK/SK 是否正确。可以重新创建一组密钥。

Q: 执行报 ModuleNotFoundError?

A: 依赖没打包完整。用 pip install --target 确保所有递归依赖都打包了(特别是 huaweicloudsdkcore、defusedxml)。

Q: iBMC 拿到的是过期地址?

A: IPv6 有多个地址(永久 + 临时),代码里已过滤了 4 段包含 fe80 的过期地址。如果还有问题,检查 server_prefix() 函数的过滤条件。

Q: 如果服务器一直关机,前缀会变吗?

A: 短期内(几小时到几天)运营商可能不会回收前缀。如果长时间关机导致前缀变化,云函数会通过 DNS 解析拿不到有效地址而跳过更新,不会把错误 IP 写进 DNS。

总结

现在你有了一个 7×24 小时运行的 DDNS 守护者,完全免费,不需要任何本地设备开机。无论服务器还是你的电脑是否在线,iBMC 的域名解析都由云函数保障。

📂 分类:服务器维护
评论 (0)
技术分享者 · 记录成长的每一步
✨ 特效 ON