零成本远程访问家庭PC:WireGuard+DDNS+Python全自动方案

👉 工具网址:https://www.noip.com

你是不是也有过这种冲动?

人在外地,家里那台精心组装的电脑却闲着。想远程连回去,搜了一圈教程,发现不是要买树莓派,就是要给运营商交钱搞静态IP,甚至还得换个带DDNS的企业级路由器。钱包一听就怂了。

别急。这篇文章就是为你准备的。我从零开始,只用了三样东西:

  • WireGuard(免费开源VPN)
  • No-IP(免费动态DNS)
  • 一个Python脚本(自己写的)

就搞定了从孟买远程连接喀拉拉邦家里电脑的全套方案。不用花钱,不用额外硬件,而且全自动——电脑一开机,脚本自动跑,IP变了也不怕。


核心问题:动态IP + 没公网IP?

大多数家庭宽带都没有固定的公网IP,路由器重启或者ISP刷新,你的WAN IP就变了。就算用WireGuard搭好VPN,IP一变连接就断。

解决方案就是动态DNS(DDNS):把一个固定的域名(比如 ximangh.ddns.net)始终指向你最新的公网IP。No-IP提供免费的DDNS服务,但问题来了——IP变了之后,得有人去更新这个记录。

手动更新?不可能每次都盯着。所以我写了个Python脚本,自动搞定这件事。

我的自动化Python脚本

脚本逻辑很简单:

  1. 调用API获取当前公网IP
  2. 和上次保存的IP比较
  3. 如果变了,就自动更新No-IP的DDNS记录
  4. 把新IP存下来,下次对比用

下面是带中文注释的完整代码,你可以直接复制使用:

import requests  
import os  
import ipaddress  
import logging

# 设置日志,方便看执行情况
logging.basicConfig(  
    level=logging.INFO,  
    format="%(asctime)s [%(levelname)s] %(message)s"  
)

# 从环境变量读No-IP账号密码,不要写死在代码里
NOIP_USER = os.environ.get("NOIP_USER")  
NOIP_PASS = os.environ.get("NOIP_PASS")  
HOSTNAME = os.environ.get("DDNS_HOSTNAME", "ximangh.ddns.net")  # 你的DDNS域名
IP_FILE = "public_ip.txt"  # 存上一次IP的文件

def get_public_ip():  
    """从 ipify 获取当前公网IP,并验证格式"""
    response = requests.get(  
        "https://api.ipify.org?format=json",  
        timeout=10,  
        verify=True  
    )  
    response.raise_for_status()  
    ip = response.json()["ip"]  
    ipaddress.ip_address(ip)  # 校验,非法IP会报错
    logging.info(f"获取到当前公网IP: {ip}")  
    return ip

def read_saved_ip(filename):  
    """读取上次保存的IP"""
    if not os.path.exists(filename):  
        logging.info("没有找到保存IP的文件")  
        return None  
    with open(filename, "r") as file:  
        ip = file.read().strip()  
    logging.info(f"上次保存的IP: {ip}")  
    return ip

def save_ip(filename, ip):  
    """把新的IP保存到文件"""
    with open(filename, "w") as file:  
        file.write(ip)  
    logging.info(f"新IP已保存: {ip}")

def update_noip(ip):  
    """通过No-IP的API更新DDNS记录"""
    if not NOIP_USER or not NOIP_PASS:  
        logging.error("环境变量NOIP_USER或NOIP_PASS未设置!")  
        return

    response = requests.get(  
        "https://dynupdate.no-ip.com/nic/update",  
        params={"hostname": HOSTNAME, "myip": ip},  
        auth=(NOIP_USER, NOIP_PASS),  
        headers={"User-Agent": "my-ddns-updater/1.0"},  
        timeout=10,  
        verify=True  
    )

    result = response.text.strip()  

    if result.startswith("good"):  
        logging.info(f"No-IP更新成功: {result}")  
    elif result.startswith("nochg"):  
        logging.info(f"No-IP: IP未变化: {result}")  
    elif result == "nohost":  
        logging.error("No-IP错误:主机名不存在")  
    elif result == "badauth":  
        logging.error("No-IP错误:认证失败")  
    elif result == "abuse":  
        logging.error("No-IP错误:账号被滥用封禁")  
    else:  
        logging.warning(f"No-IP未知响应: {result}")

def main():  
    try:  
        current_ip = get_public_ip()  
        saved_ip = read_saved_ip(IP_FILE)  

        if saved_ip == current_ip:  
            logging.info("IP未变化,无需更新")  
        else:  
            logging.info(f"IP已变化: {saved_ip} → {current_ip}")  
            save_ip(IP_FILE, current_ip)  
            update_noip(current_ip)  

    except ValueError as e:  
        logging.error(f"获取到无效IP: {e}")  
    except requests.RequestException as e:  
        logging.error(f"网络错误: {e}")  

if __name__ == "__main__":  
    main()

怎么让它全自动跑?

把脚本设为开机自启就行。Windows用户:

  • Win+R 输入 shell:startup,打开启动文件夹
  • 创建一个 .bat 文件,内容写 python your_script.py
  • 或者直接用任务计划程序设置

这样每次电脑一开机联网,脚本就自动检查IP,变了就更新DDNS。你再也不用手动登录No-IP了。

最终效果

  • WireGuard VPN 让你远程连接像在家一样
  • No-IP DDNS 让域名始终指向最新IP
  • Python脚本 让更新完全自动化

现在我用手机、笔记本,随便哪里都能远程连回喀拉拉邦的家里电脑。零成本,纯自建,安全可靠。

你唯一需要额外做的事情:在路由器上设置一个端口转发(WireGuard默认端口51820),或者直接用UPnP自动映射。

安全注意:我把No-IP密码存在环境变量里,而不是硬编码。公网IP也做了校验,请求加了超时和TLS验证。WireGuard用了现代加密,且为每位客户端分配独立的/32地址,严格控制访问。

学到了什么?

如果当时我有钱,可能直接买现成的远程方案,那就永远学不会DDNS、VPN、API调用和自动化脚本这些东西。限制反而逼出了创造力。

这就是我现在的远程方案——每次连回去,都觉得自己挺牛。


直达网址:No-IP 官方免费DDNS服务

类似文章