华为云 FunctionGraph 云函数 DDNS:零成本维护 iBMC 域名解析
为什么需要云函数 DDNS?
场景很常见:家里断电或服务器关机后,IPv6 前缀可能变化。此时服务器没开机,没法自己更新 DNS——那就需要一台 永远在线 的东西来帮你做这件事。
华为云 FunctionGraph 免费额度非常慷慨(每月 100 万次调用、40 万 GB-秒),跑一个 DDNS 脚本几乎零成本。本文记录完整的部署过程。
整体思路
- 云函数定时触发(每 10 分钟)
- DNS 解析
xiaoajun.cn获取服务器当前 IPv6 地址 - 提取 IPv6 前缀(前 4 段)
- 用 iBMC 的 MAC 地址通过 EUI-64 算法 算出后缀
- 拼接出完整 iBMC IPv6 → 更新 DNS 记录
ibmc.xiaoajun.cn
关键优势:不需要直接连接 iBMC,不需要服务器开机。只要服务器曾经获取过 IPv6 地址且 DNS 记录还在,就能算出 iBMC 的地址。
EUI-64 算法
IPv6 无状态自动配置中,设备用 MAC 地址生成接口 ID:
- MAC:
3c:e8:24:71:e3:33 - 中间插入
ff:fe:3c:e8:24:ff:fe:71:e3:33 - 第 7 位取反:
3c→0011 1100→ 第 7 位翻转 →0011 1110→3e - 结果:
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
- 控制台 → 函数工作流 FunctionGraph
- 创建函数 → 选择:
- 运行时:Python 3.10
- 上传方式:zip 包
- 入口函数:ddns_ibmc_cloud_sdk.handler
- 上传刚才打包的
ibmc_ddns_fg.zip - 创建函数后进入配置页
步骤五:配置函数
基本设置
- 内存:128 MB(够用)
- 超时时间:30 秒(DNS 查询 + API 调用需要一点时间)
配置定时触发器
- 「触发器」→「创建触发器」
- 选择「定时触发器」
- Cron 表达式:
0 */10 * * * *(每 10 分钟执行一次) - 点击确定
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 的域名解析都由云函数保障。