Skip to content

[Bug] 系统 VPN 的「始终开启 / On Demand」在系统重启后失效,开机不会自动连接 #48

Description

@yutong8209

问题描述

在 App 内「更多 → 按需求连接」中开启「始终开启 (Always On)」后,回到首页点「启动」连一次,当前连接正常,终端执行 scutil --nc show "Clash by Hako" 也显示 OnDemandEnabled: TRUE。但系统重启(关机再开机)后,即使系统 VPN 显示已开启,「始终开启」也不会再自动连接代理,必须手动打开 App 点「启动」才能恢复。

复现步骤

  1. App 内「更多 → 按需求连接」→ 打开「始终开启 (Always On)」
  2. 首页「启动」连接一次
  3. 终端执行 scutil --nc show "Clash by Hako",确认 OnDemandEnabled: TRUE
  4. 重启系统
  5. 重启后代理不会自动连接,且 OnDemand 被写回 FALSE(「按需求连接」界面开关看似还开着,但实际已失效)

根因分析

问题出在 App 退出时的处理逻辑。在 apple/HakoClient/Sources/Mac/HakoMacQuit.swift 中,当 App 终止且隧道正在运行时,会调用 stop();而 VPNController.swiftstop() 会将 isOnDemandEnabled 置为 false 并执行 saveToPreferences() 写回系统配置(即 disarm OnDemand)。

由于系统「关机 / 重启 / 注销」也会触发 App 的退出路径,于是每次重启都会执行一次 disarm,把用户在 App 里设置的“始终开启”撤销掉。这正是「设置后重启即失效」的根因。

值得注意:代码中已经存在 .readerQuitLeavingTunnelRunning 场合走 return .terminateNow(不调用 stop、保留隧道),说明作者本意是要区分「用户主动退出」与「系统终止」——只是目前系统终止仍走了对隧道 disarm 的路径。

建议修复

  • 监听系统关机 / 电源关闭通知(如 NSWorkspace.willPowerOffNotification / NSWorkspaceWillPowerOffNotification)。
  • 在该通知触发时直接 return .terminateNow跳过 stop() / disarmOnDemandForUserStop,从而保留系统级 On Demand 配置。
  • 仅当用户在 App 内主动「停止 / 断开」或 Cmd+Q 退出时,才走原有的 disarm 逻辑。

这样「始终开启」才能在开机 / 重启后持续生效,无需用户每次手动启动。

环境信息

  • App: Clash by Hako(com.hako.network)v1.0.10
  • macOS(Apple Silicon)
  • 系统 VPN(Packet Tunnel / Network Extension)模式,无本地代理端口

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions