Skip to content

Apply regenerates WARP wgcf profile without Table=off/DNS protections → wg-quick fails (no resolvconf) or hijacks all routing → public lockout #5569

Description

@EricPrometheus

Environment

  • Hiddify-Manager 13.0.3, Ubuntu 22.04 (no resolvconf installed), WARP via kernel wg-quick@warp

What happened

During config re-apply, the WARP pass regenerated services/warp/wireguard/wgcf-profile.conf without the protections that generate_warp_wireguard_config() normally applies (sed Table = off + comment DNS =). Two failure modes followed:

  1. wg-quick@warp fails to start: resolvconf: command not found → warp interface deleted → hiddify-core/xray WARP egress dead (route ip+net: no such network interface).
  2. When warp does start with the unprotected profile (AllowedIPs = 0.0.0.0/0, no Table), wg-quick installs its default policy rules (not fwmark 0xca6c lookup 51820), which route all server egress — including replies to new inbound connections — into the tunnel. Result: public SSH/panel/probe all blackholed from the internet while already-established flows keep working; only VCN-private-IP access survives. We were locked out and had to rescue via a sibling instance inside the VCN.

Workaround applied

Table = off
PostUp = ip route add default dev %i metric 2000
PostDown = ip route del default dev %i metric 2000
#DNS = ...   (commented)

This keeps the interface (hiddify-core uses bind_interface) without hijacking global routing.

Also observed during the same upgrade

hiddify-core.service crash-looped 625 times at upgrade time (listen tcp 127.0.0.1:2000: bind: address already in use — stale instance holding the port during the restart race), self-healing only after ~1 hour.

Suggested fix

  • Make every WARP profile generation path apply the Table = off + DNS protections (or make resolvconf an explicit dependency and default the template to a safe Table).
  • Guard hiddify-core restarts against the port-2000 race.

Thanks!

Activity

  1. firexrwt commented on Sep 27, 2026

    @firexrwt

    Hit this on 13.0.3 (upgraded from 12.3.x, Ubuntu 22.04, no resolvconf): after an apply, wg-quick@warp failed with resolvconf: command not found and the regenerated profile had DNS = ... uncommented and no Table = off.

    I think I found why the protections get lost. It's the sed -i calls running on a symlink that ensure_warp_data_links then throws away.

    services/warp/utils.sh, generate_warp_wireguard_config():

    (cd "$svc_dir" && ./wgcf generate >/dev/null 2>&1)
    sed -i 's/\[Peer\]/Table = off\n\[Peer\]/g' "$svc_dir/wgcf-profile.conf"
    ...
    sed -i '/DNS = 1.1.1.1/s/^/# /' "$svc_dir/wgcf-profile.conf"
    mkdir -p /etc/wireguard/
    ensure_warp_data_links wireguard "$svc_dir"
    ln -sf "$svc_dir/wgcf-profile.conf" /etc/wireguard/warp.conf

    On an already-migrated install, $svc_dir/wgcf-profile.conf is a symlink to data/services/warp/wireguard/wgcf-profile.conf (created by an earlier ensure_warp_data_links). Step by step:

    1. wgcf generate writes through the symlink, so the data/ copy gets the fresh, unprotected profile.
    2. GNU sed -i doesn't follow symlinks by default. It writes its output to a new regular file at the link path. The symlink is replaced by a patched regular file, and the data/ copy stays unpatched. Quick check on the same box (GNU sed 4.8):
      $ echo orig > target; ln -s target link; sed -i s/orig/patched/ link
      $ cat target   -> orig
      $ cat link     -> patched   (link is now a regular file)
      
    3. ensure_warp_data_links sees that $svc_dir/wgcf-profile.conf is a regular file while the data/ copy already exists, so it takes the rm -f "$src" branch and re-links to data/. The patched file is deleted.
    4. /etc/wireguard/warp.conf -> $svc_dir/wgcf-profile.conf -> data/ copy = the profile without Table = off and with DNS =. That gives both failure modes described above: resolvconf missing, or wg-quick installing its policy routing for 0.0.0.0/0.

    Every apply goes through check_warp_wireguard_connection -> generate_warp_wireguard_config, so this comes back on every apply, not only once after the upgrade.

    Suggested fix (any of these):

    • sed -i --follow-symlinks ..., or
    • resolve the target first: local profile; profile="$(readlink -f "$svc_dir/wgcf-profile.conf")" and run all the seds on $profile, or
    • call ensure_warp_data_links right after wgcf generate and edit the data/ path directly.

    Manual workaround until then: on readlink -f /etc/wireguard/warp.conf, add Table = off before [Peer], comment out DNS =, then systemctl restart wg-quick@warp. Check with curl --interface warp https://www.cloudflare.com/cdn-cgi/trace (should show warp=on).

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions