手把手教你用 Gitee 替代 DDNS:家庭 IP 自动更新 + 本地快捷访问

手把手教你用 Gitee 替代 DDNS:家庭 IP 自动更新 + 本地快捷访问 ## 前言很多人家中搭建了 NAS、树莓派或小型服务器希望通过固定域名或地址随时访问内网服务。传统的 DDNS 需要依赖域名服务商并且要开放端口、配置防火墙。本文提供一种极简替代方案**利用 Gitee码云私有仓库存储家庭公网 IP通过 Python 脚本自动更新 IP并在本地电脑生成快捷方式**实现类似 DDNS 的效果无需公网域名完全免费。---## 一、方案设计思路1. **家庭服务器**定时获取当前公网 IPv4 和 IPv6通过 Gitee API 写入私有仓库的两个文件 ipv4.txt 和 ipv6.txt。2. **本地电脑**无 Git 依赖通过 Gitee API 直接读取最新 IP并在脚本所在目录生成可直接双击打开的网页快捷方式.url / .webloc / .desktop。3. **运行环境**Windows / macOS / Linux 均可最终可将脚本打包为单文件 exe方便多台设备使用。优点- **无需购买域名**完全利用 Gitee 免费私有仓库。- **同时支持 IPv4 和 IPv6**未来兼容性好。- **纯 Python 实现**可打包为独立可执行文件无需安装 Python 环境也能运行。- **安全可控**私有仓库 个人令牌IP 不会公开。---## 二、准备工作### 1. 注册 Gitee 并创建私有仓库- 访问 [gitee.com](https://gitee.com) 注册账号。- 创建私有仓库例如命名为 homeddns本文使用用户名 georgecn仓库 homeddns。- 在 **设置 → 私人令牌** 生成一个新令牌勾选 projects 权限**复制保存好**只显示一次。### 2. 确认家庭网络具备公网 IP- 访问 [ipv4.ip.sb](https://ipv4.ip.sb) 和 [ipv6.ip.sb](https://ipv6.ip.sb) 检查是否有公网地址。- 若没有公网 IPv4可考虑使用 IPv6 或内网穿透方案本文暂不展开。### 3. 路由器端口转发如果家庭 Web 服务运行在某个内网设备如 192.168.1.100:8080需在路由器中设置端口转发NAT将外网请求的 8080 端口映射到该内网地址。---## 三、家庭服务器端自动更新 IP 到 Gitee### 1. 脚本功能- 依次尝试多个 IP 查询服务ipv4.ip.sb、v4.ident.me 等获取当前公网 IPv4 和 IPv6。- 通过 Gitee API 将 IP 写入仓库文件若文件不存在则创建若存在则更新自动处理 sha。- 若 IP 未变化则跳过更新节省 API 调用。### 2. 完整代码 update_ip_to_gitee.pypython#!/usr/bin/env python3# -*- coding: utf-8 -*-import sysimport ioimport base64import requests# 解决 Windows 控制台 GBK 编码问题if sys.platform win32:sys.stdout io.TextIOWrapper(sys.stdout.buffer, encodingutf-8)# 配置区域 GITEE_TOKEN 你的私人令牌OWNER 你的用户名REPO homeddns # 仓库名BRANCH master # 分支名# IPV4_SERVICES [https://ipv4.ip.sb,https://v4.ident.me,https://api.ipify.org,https://ipv4.icanhazip.com]IPV6_SERVICES [https://ipv6.ip.sb,https://v6.ident.me,https://api6.ipify.org,https://ipv6.icanhazip.com]def fetch_ip(service_list, ip_typeIPv4):for url in service_list:try:print(f尝试从 {url} 获取{ip_type}...)resp requests.get(url, timeout5)if resp.status_code 200:ip resp.text.strip()if ip_type IPv4 and . in ip and : not in ip:return ipelif ip_type IPv6 and : in ip:return ipexcept Exception as e:print(f从 {url} 获取失败: {e})continuereturn Nonedef get_file_sha(file_path):api_url fhttps://gitee.com/api/v5/repos/{OWNER}/{REPO}/contents/{file_path}headers {Authorization: ftoken {GITEE_TOKEN}}params {ref: BRANCH}try:resp requests.get(api_url, headersheaders, paramsparams)if resp.status_code 200:data resp.json()if isinstance(data, dict):return data.get(sha)elif isinstance(data, list):print(f警告{file_path} 是目录不是文件)return Noneelif resp.status_code 404:return Noneelse:print(f获取文件信息异常: {resp.status_code})return Noneexcept Exception as e:print(f请求异常: {e})return Nonedef update_gitee_file(file_path, content):api_url fhttps://gitee.com/api/v5/repos/{OWNER}/{REPO}/contents/{file_path}headers {Authorization: ftoken {GITEE_TOKEN}}new_content_b64 base64.b64encode(content.encode()).decode(utf-8)data {access_token: GITEE_TOKEN,content: new_content_b64,message: fUpdate {file_path},branch: BRANCH}try:resp requests.put(api_url, jsondata, headersheaders)if resp.status_code in (200, 201):print(f[OK] 文件 {file_path} 更新成功)return Trueelif resp.status_code 400 and sha is missing in resp.text:print(f文件 {file_path} 已存在获取 sha 重试...)sha get_file_sha(file_path)if sha:data[sha] sharetry_resp requests.put(api_url, jsondata, headersheaders)if retry_resp.status_code in (200, 201):print(f[OK] 文件 {file_path} 更新成功)return Trueprint(f[ERROR] 更新失败: {resp.status_code})return Falseexcept Exception as e:print(f请求异常: {e})return Falsedef main():print( 开始获取公网IP )ipv4 fetch_ip(IPV4_SERVICES, IPv4)if ipv4:print(f[INFO] IPv4: {ipv4})update_gitee_file(ipv4.txt, ipv4)else:print([ERROR] 无法获取 IPv4)ipv6 fetch_ip(IPV6_SERVICES, IPv6)if ipv6:print(f[INFO] IPv6: {ipv6})update_gitee_file(ipv6.txt, ipv6)else:print([WARN] 无法获取 IPv6)print( 执行完成 )if __name__ __main__:main()### 3. 部署到家庭服务器- 将脚本保存为 update_ip_to_gitee.py。- 安装依赖pip install requests。- 手动执行测试python update_ip_to_gitee.py。- 设置定时任务例如每 5 分钟运行一次- **Windows**使用任务计划程序。- **Linux**crontab -e 添加 */5 * * * * /usr/bin/python3 /path/to/update_ip_to_gitee.py- **宝塔面板**直接添加计划任务执行命令 python /path/to/update_ip_to_gitee.py---## 四、本地电脑一键生成访问快捷方式我们希望在任何电脑上无需 Git拉取最新 IP并生成一个双击就能打开家庭网页的快捷方式。### 1. 脚本功能- 通过 Gitee API 直接获取 ipv4.txt 和 ipv6.txt 的内容。- 自动识别操作系统Windows/macOS/Linux生成对应格式的快捷方式.url / .webloc / .desktop。- 快捷方式保存在脚本所在目录方便移动使用。### 2. 完整代码 sync_and_create_shortcut.pypython#!/usr/bin/env python3# -*- coding: utf-8 -*-import osimport sysimport requestsimport base64# 配置区域 GITEE_TOKEN 你的私人令牌OWNER 你的用户名REPO homeddnsBRANCH masterWEB_PORT 8080 # 你的家庭 Web 服务端口# # 获取脚本所在目录兼容 PyInstaller 打包if getattr(sys, frozen, False):SCRIPT_DIR os.path.dirname(sys.executable)else:SCRIPT_DIR os.path.dirname(os.path.abspath(__file__))# 如果当前目录不可写降级到桌面if not os.access(SCRIPT_DIR, os.W_OK):SCRIPT_DIR os.path.join(os.path.expanduser(~), Desktop)print(f[WARN] 原目录不可写改用桌面目录: {SCRIPT_DIR})def get_file_content(file_path):url fhttps://gitee.com/api/v5/repos/{OWNER}/{REPO}/contents/{file_path}headers {Authorization: ftoken {GITEE_TOKEN}}params {ref: BRANCH}try:resp requests.get(url, headersheaders, paramsparams, timeout10)if resp.status_code 200:data resp.json()content_b64 data.get(content, )if content_b64:return base64.b64decode(content_b64).decode(utf-8).strip()elif resp.status_code 404:print(f[ERROR] 文件 {file_path} 不存在)else:print(f[ERROR] 获取 {file_path} 失败状态码 {resp.status_code})return Noneexcept Exception as e:print(f[ERROR] 网络错误: {e})return Nonedef create_shortcut_windows(filepath, url):content f[InternetShortcut]URL{url}IconFile%SystemRoot%\\System32\\SHELL32.dllIconIndex13with open(filepath, w, encodingutf-8) as f:f.write(content)def create_shortcut_macos(filepath, url):content f?xml version1.0 encodingUTF-8?!DOCTYPE plist PUBLIC -//Apple//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtdplist version1.0dictkeyURL/keystring{url}/string/dict/plistwith open(filepath, w, encodingutf-8) as f:f.write(content)def create_shortcut_linux(filepath, url):content f[Desktop Entry]TypeLinkNameHome WebURL{url}Icontext-htmlwith open(filepath, w, encodingutf-8) as f:f.write(content)def main():if sys.platform win32:create_func create_shortcut_windowsext .urlelif sys.platform darwin:create_func create_shortcut_macosext .weblocelse:create_func create_shortcut_linuxext .desktopprint(f快捷方式将保存在: {SCRIPT_DIR})ipv4 get_file_content(ipv4.txt)ipv6 get_file_content(ipv6.txt)if ipv4:url4 fhttp://{ipv4}:{WEB_PORT}/path4 os.path.join(SCRIPT_DIR, fHome_IPv4{ext})create_func(path4, url4)print(f[OK] IPv4 快捷方式: {path4})print(f URL: {url4})else:print([WARN] 无法获取 IPv4)if ipv6:url6 fhttp://[{ipv6}]:{WEB_PORT}/path6 os.path.join(SCRIPT_DIR, fHome_IPv6{ext})create_func(path6, url6)print(f[OK] IPv6 快捷方式: {path6})print(f URL: {url6})else:print([WARN] 无法获取 IPv6)# 非打包模式或打包但不需要等待时可省略 inputif not getattr(sys, frozen, False):input(按 Enter 退出...)if __name__ __main__:main()### 3. 使用方式- **直接运行 Python 脚本**需安装 requests 库。- **打包为 exe**推荐适合无 Python 环境bashpip install pyinstallerpyinstaller --onefile --noconsole sync_and_create_shortcut.py生成的 exe 文件可以放在任意文件夹如 U 盘、桌面双击运行即生成快捷方式。### 4. 高级用法定时自动更新Windows 下可将 exe 添加到任务计划程序设置每天运行一次确保快捷方式指向最新 IP。---## 五、常见问题与解决方案### 1. 控制台报错 UnicodeEncodeError: gbk codec cant encode character**原因**Windows 默认控制台编码为 GBK而脚本中使用了 emoji✅❌或中文字符。**解决**已在脚本开头强制将 stdout 编码设为 UTF-8并将 emoji 替换为 [OK]、[ERROR] 等 ASCII 文本。### 2. 打包后出现 RuntimeError: input0: lost sys.stdIn**原因**使用 --noconsole 打包后没有控制台input() 无法调用。**解决**在脚本中判断是否打包环境仅当非打包时调用 input或完全删除该行。### 3. Gitee API 返回 sha is missing**原因**文件已存在但更新时未提供 sha 字段。**解决**脚本已实现自动获取 sha 并重试。### 4. 获取不到公网 IPv6**原因**家庭网络可能未分配公网 IPv6 或被光猫/路由器阻止。**解决**检查 [ipv6.ip.sb](https://ipv6.ip.sb) 是否显示地址若没有可只用 IPv4 方案。### 5. 访问快捷方式时打不开网页- 确认路由器已正确配置端口转发。- 确认家庭 Web 服务正在运行。- 尝试用 IPv6 地址直接访问如果支持IPv6 通常不需要端口转发。---## 六、总结通过这套方案你拥有了一个完全自主可控、免费且稳定的动态 IP 同步系统。- **服务器端**每 5 分钟自动将 IPv4/IPv6 写入 Gitee 私有仓库。- **客户端**一键生成快捷方式随时访问家庭服务。你可以将客户端 exe 分享给家人或朋友他们只需双击即可访问你的家庭网页无需安装任何环境。**扩展思路**- 搭配 frp 或 ZeroTier 实现内网穿透彻底解决无公网 IP 的问题。- 将快捷方式部署在手机桌面iOS 可通过“添加到主屏幕”Android 可使用 URL 快捷方式。如果你在使用中遇到任何问题欢迎在评论区留言交流。---**项目源码已开源**Gitee 仓库地址https://gitee.com/你的用户名/homeddns私有仅自己可见客户端脚本可任意分发只需修改配置中的令牌和用户名即可。**感谢阅读祝玩得开心**