乐于分享
好东西不私藏

Openclaw 应用实例(一)——一句话获取那个男人所有设备IPv6地址

Openclaw 应用实例(一)——一句话获取那个男人所有设备IPv6地址
O1 需求来源
最近大家都在玩Openclaw,我也有加入一些500人左右的大群里面,试图看看大家有没有玩的很好的,结果并没有达到自己预期。这么强大的东西,很多人都用在所谓的对话养成游戏一样。并没有看到有人养成很好的skill。于是开始思考,有没有能通过Openclaw直接用很低的技术门槛来解决生活以及工作中的需求。
刚好今天想远程一下家里的电脑,按照以前,我肯定是先通过家里的路由器软件先唤醒家里的办公电脑,然后再登录路由器查看办公电脑的IPV6地址,最后使用Windows自带的远程桌面程序直接发起远程链接。突然灵感来了我完全可以把这个形成很成熟的SKILL,每当我需要远程时只需要给Openclaw讲一下她能直接给我正确的IPV6地址即可。
O2 技术分析
已知家里的网络结构大致如下:运营商的光纤入户光猫下接两大不同品牌的路由器(避免同款路由器一旦出现漏洞全军覆没),家用路由器1用作家用电脑手机及访客的互联网访问。家用路由器2为各类家具(冰箱、电视、洗衣机、空调、家用摄像头)等专用网络。家用路由器2策略隔离拒绝所有家用路由器1网段访问,同时非必要端口在家用路由器1全部关闭,关闭IPV6功能,仅保留IPV4,避免通过IPV6直接暴露在互联网。
本次主要是使用IPv6从互联网访问家用PC,首先来拆分方案实现步骤。
第一步:首先要如何能够随时控制家用PC的开机和关机。
第二步:电脑开机后要能够自动通过DHCP协议从路由器获取到IPv6地址
第三步:我需要Openclaw能够通过SKILL技能随时获取到家里电脑获取到的最新的IPv6地址,能够通过APP对接插件发送到我手机上对应的APP上。
第四步:每当我需要远程家里电脑时,我只需要问APP上对接的AI助理“给我家里电脑的IPv6地址”即可获取到IPv6然后我就可以在互联网使用该IPv6进行远程登录。
对Openclaw和IPv6比较熟悉的兄弟可能已经瞬间能明白我是如何实现的。上面四步实际就是一个简单的IPv6远程登录访问SKILL的雏形。接下来我带大家根据我的思路来完善该SKILL,实现以后无需再装远程软件、各种反向代理内网穿透工具等即可在任意互联网下远程控制自己家里的电脑。
O3 具体实现
第一步如何实现随时控制家用PC的开机关机?
我这里是通过家用路由器1的网络唤醒功能来实现对家用PC的唤醒开机,现在诸多计算机主板都支持,网络唤醒(Wake-on-LAN)自己在电脑启用该功能就行。我觉得比什么网络开机模块、网络智能插板唤醒电脑要好很多,毕竟不花钱还技术门槛低。
     并且网络唤醒也很简单,只需要对应网卡的MAC地址即可。
第二步:电脑开机后要能够自动通过DHCP协议从路由器获取到IPv6地址
IPv6的功能运营商基本默认是不给用户开启的,大多需要你联系给你加装宽带的小哥要到光猫的超级管理员账号密码,然后你研究一下登录光猫后台IPv6启用,之后把光猫的防火墙等级调整为低级甚至关闭,不然有可能哪怕家里路由器获取到了IPv6地址也是无法正常使用的。这里我就不截图了,因为我家里光猫的超级管理员账户被我改的忘记了。光猫配置好以后就是要配置家用路由器1,让它能够获取到正常的公网IPv6。我这里配置的IPv6 DHCP有状态+无状态模式才正常获取到24开头的正常公网IPv6 IP。 
如果你看到仅仅是fe80开头的是不行的,这些开头的IP是保留IP无法用于互联网通信。当然现在我直接去路由器的IPv6终端去查看电脑获取的IPv6拿去远程也是可以的。但是这样太烦了,你每次都要唤醒电脑然后再登录路由器后台再点开对应功能去查看IPv6,而且IPv6这么长一串,我要不的不是这种效果,我要的是我60岁老太太来了也能立刻要到结果进行远程登录。
第三步把查IP和看IP的工作交给Openclaw
现在Openclaw已经对接飞书、微信等各大APP,所以我们可以通过飞书或者微信直接让我的助理智能体(红后)来做这一项工作。
我们首先梳理查看和获取IPv6的步骤:
①通过浏览器访问路由器Web后台,输入账号密码。
②找到IPv6查看功能找到自己电脑的IPv6,可以通过MAC地址或者计算机名称很轻松找到对应的IPv6。 
③然后就可以复制对应的IPv6,使用微软自带的远程桌面工具进行远程控制了,彻底告别远控软件(远程软件你首先得装客户端,而且远程接口实际在这些厂商的云节点上,万一有个漏洞啥的,我觉得安全隐私难以保障。)
接下来我们让Openclaw来实现我们上述功能,首先在同网段路由器下部署Openclaw对接好APP,我这里用的飞书。
把上述步骤通过文字描述给AI最后固化成SKILL。简直不要太简单,直接描述自己的需求就行:
然后我把登录链接以及能够看到IPv6的链接以及用户名和密码发给她,她直接调用了我的浏览器输入了账号密码并顺利获取到了准确的IPv6结果。
一般情况下到这里就可以固化成SKILL了,现在仍然没有达到我问红后一句“告诉我家里电脑IPv6地址”的效果,她需要我告诉她账号密码,然后等待她打开我Openclaw本地电脑的浏览器然后等待很长时间她完成账号密码输入后,才能顺利获取数据。这一点不丝滑。
三句话虽然能让那个男人花18W,但是AI没有参天树,我叫查德你记住。我只想一句话要那个男人所有设备的IPv6地址。!
第四步:达到一句话获取IPv6的目的
很显然让AI机器人通过Openclaw去模仿人打开浏览器和输入账号密码是比较消耗token的,而且等待时间比较长。那么打开浏览器这条路需要优化,我这里选择直接让Openclaw通过python脚本编写代码将账号密码以及HTTP请求包方式直接向路由器request获取登录之后的cookie之后,然后再访问IPv6信息的URL,获取到返回结果后通过飞书范式化展示给我即可。
具体实现如下:直接告诉她你的想法就行了,让她自己去实现,当然这背后是我给我的AI设定思考链条,她会按照我的设定去探索答案。以下是效果,她遇到了问题,反馈我说登录失败了。
然后我把从浏览器抓到的http请求包丢给她
这里出了问题,她说她登录成功了,但是没有权限,我分析了一下她实际上并没有登录成功。
这里我让她把刚才发送的HTTP请求包发给我,我一看就知道是因为她的cookie:sess_key的值并不正确。所以实际是并没有登录成功。
发现问题就好办了,直接把抓到的具备sess_key的返回包发给她,
告诉她每次的sees_key在登录请求之后路由器反馈的响应包里,你需要将这个sees_key替换到下面的请求包,就能获取到预期的内容了。
她知道了如何使用,就解决了该问题。
这次仅仅用时11秒就完成了该任务,相比于通过浏览器2分多钟的等待已经有了应用价值。不然等待两分钟还不如我直接登录浏览器自个儿看呢。自此终于实现了一句话获取那个男人所有设备IPv6的能力。
O4 这就完了?
作为一个精致的完美主义者,这就完了?当然没有,必须清晰地认识到,未来优秀的人肯定是谁能在有限的token(中文:词元)资源下能创造更大的价值才是厉害的家伙。 至于token为什么有限,呵呵问资本家。那么该如何降低该SKILL的token消耗呢?
最终实现整个SKILL正文文本仅有13行、脚本其获取IPv6地址的脚本ipv6.py有256行。但是Openclaw实际加载的时候仅需要传递这13行的上下文,如果没有将脚本拆分出来,那么传递的上下文将达到200多行。消耗token不说,还会延长响应时间。
#IPv6 获取工具自动登录路由器并获取设备的 IPv6 地址。## 快速使用直接运行脚本:bashpython3 ~/.openclaw/workspace/skills/ipv6/ipv6.py## 配置- 路由器地址: 192.168.XX.XX- 用户名: xxxx- 密码已内置在脚本中## 功能- 自动登录 路由器- 获取所有设备的 IPv6 地址- 显示设备信息:主机名、MAC、在线时间、流量等
   AI的脚本如下(涉及个人隐私就暂时不放源脚本了):她给出这个256行代码的脚本不到1分钟!
#!/usr/bin/env python3""" IPv6 获取脚本直接调用  API 获取设备 IPv6 地址"""import requestsimport jsonimport sysimport hashlibimport base64# 配置ROUTER_IP = "你的路由器IP"USERNAME = "用户名"PASSWORD = "密码"BASE_URL = f"http://{ROUTER_IP}"def encrypt_password(password):    """     密码加密方式:    1. passwd: MD5(password)    2. pass: Base64("salt_11" + password)    """    # MD5 哈希    passwd_md5 = hashlib.md5(password.encode()).hexdigest()    # Base64 编码 (salt_11 + password)    pass_base64 = base64.b64encode(f"salt_11{password}".encode()).decode()    return passwd_md5, pass_base64class API:    def __init__(self):        self.session = requests.Session()        self.cookie = None    def login(self):        """登录  路由器"""        url = f"{BASE_URL}/Action/login"        # 加密密码        passwd_md5, pass_base64 = encrypt_password(PASSWORD)        #  登录使用 JSON 格式,密码需要加密        payload = {            "username": USERNAME,            "passwd": passwd_md5,            "pass": pass_base64,            "remember_password": None        }        try:            response = self.session.post(                url,                 json=payload,                headers={                    "Content-Type": "application/json;charset=UTF-8",                    "Accept": "application/json, text/plain, */*",                    "Origin": BASE_URL,                    "Referer": f"{BASE_URL}/login"                },                timeout=10            )            result = response.json()            if result.get("Result") == 10000:                self.cookie = response.cookies.get("sess_key")                print(f"登录成功")                return True            else:                print(f"登录失败: {result}")                return False        except Exception as e:            print(f"登录错误: {e}")            return False    def get_ipv6_devices(self):        """获取 IPv6 设备列表"""        if not self.cookie:            if not self.login():                return None        url = f"{BASE_URL}/Action/call"        #  API 调用参数 - 正确的 func_name 和参数        payload = {            "func_name": "monitor_lanipv6",            "action": "show",            "param": {                "TYPE": "data,total",                "ORDER_BY": "ip_addr_int",                "orderType": "IP",                "limit": "0,20",                "ORDER": ""            }        }        headers = {            "Content-Type": "application/json;charset=UTF-8",            "Accept": "application/json, text/plain, */*",            "Origin": BASE_URL,            "Referer": f"{BASE_URL}/"        }        # 手动设置 cookie,确保包含所有必要的字段        cookies = {            "username": USERNAME,            "sess_key": self.cookie,            "login": "1"        }        try:            response = self.session.post(                url,                 json=payload,                headers=headers,                cookies=cookies,                timeout=10            )            result = response.json()            if result.get("Result") == 30000:  # 成功返回码是 30000                return result.get("Data", {}).get("data", [])            else:                print(f"获取数据失败: {result}")                return None        except Exception as e:            print(f"获取数据错误: {e}")            return None    def format_output(self, devices):        """格式化输出"""        if not devices:            print("没有找到 IPv6 设备")            return        print(f"\n{'='*60}")        print(f"📡 路由器 IPv6 设备列表")        print(f"{'='*60}\n")        for i, device in enumerate(devices, 1):            hostname = device.get('hostname', '未命名')            ipv6 = device.get('ip_addr', 'N/A')            mac = device.get('mac', 'N/A')            link_addr = device.get('link_addr', 'N/A')            uptime = device.get('uptime', 'N/A')            connect_num = device.get('connect_num', 0)            total_up = device.get('total_up', 0)            total_down = device.get('total_down', 0)            # 转换流量为可读格式            total_up_gb = total_up / (1024**3)            total_down_gb = total_down / (1024**3)            print(f"设备 {i}: {hostname}")            print(f"  🌐 IPv6: {ipv6}")            print(f"  🔗 Link-local: {link_addr}")            print(f"  📍 MAC: {mac}")            print(f"  ⏱️ 上线时间: {uptime}")            print(f"  🔗 连接数: {connect_num}")            print(f"  📊 流量: 上行 {total_up_gb:.2f} GB / 下行 {total_down_gb:.2f} GB")            print()        print(f"共 {len(devices)} 台设备在线")        print(f"{'='*60}\n")def main():    import argparse    parser = argparse.ArgumentParser(description='IPv6 获取工具')    parser.add_argument('--json', action='store_true', help='以 JSON 格式输出')    parser.add_argument('--host', type=str, help='指定设备主机名')    args = parser.parse_args()    api = API()    devices = api.get_ipv6_devices()    if not devices:        print("获取设备列表失败")        sys.exit(1)    # 如果指定了主机名,只显示该设备    if args.host:        devices = [d for d in devices if args.host.lower() in d.get('hostname', '').lower()]        if not devices:            print(f"未找到主机名为 '{args.host}' 的设备")            sys.exit(1)    # JSON 输出    if args.json:        output = []        for d in devices:            output.append({                'hostname': d.get('hostname', ''),                'ipv6': d.get('ip_addr', ''),                'mac': d.get('mac', ''),                'link_local': d.get('link_addr', '')            })        print(json.dumps(output, indent=2, ensure_ascii=False))    else:        api.format_output(devices)if __name__ == "__main__":    main()
接着加固:为了避免群组成员获取到敏感信息,将该SKILL列为禁我个人可用。
O5 还有优化空间吗?
当然还有优化的空间,只不过今天篇幅有限。就先到此位置,敬请期待Openclaw应用实例(二):一句话系列之......

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料