Skip to content

Add 'devproxy system-proxy reset' and restore previous system proxy settings - #2100

Open
waldekmastykarz wants to merge 6 commits into
dotnet:mainfrom
waldekmastykarz:issue-2060-add-a-command-to-restore-system-proxy-se-ffa2f5
Open

waldekmastykarz wants to merge 6 commits into
dotnet:mainfrom
waldekmastykarz:issue-2060-add-a-command-to-restore-system-proxy-se-ffa2f5

Conversation

@waldekmastykarz

Copy link
Copy Markdown
Collaborator

Resolves #2060

Problem

A graceful shutdown turns the system proxy off, but a killed or crashed Dev Proxy leaves the OS pointing at a dead port. Even a graceful shutdown only flipped ProxyEnable/proxy state off and left Dev Proxy's ProxyServer value behind, and it turned off any proxy the user had configured before (e.g. a corporate proxy). Crash recovery only existed for detached instances (via state files); a killed foreground instance left nothing to recover from.

Changes

  • Snapshot before taking over. SystemProxyManager.Enable records the current OS proxy settings plus the owning PID in system-proxy-backup.json in the Dev Proxy config folder:
    • Windows: previous ProxyEnable / ProxyServer registry values (including "value didn't exist").
    • macOS: per network service web/secure web proxy server, port, and enabled state (networksetup -get[secure]webproxy).
    • An existing snapshot is kept, so a re-enable after a crash doesn't overwrite the original settings with Dev Proxy's.
  • Restore instead of just disabling. Disable puts the snapshot back (Windows: set/delete registry values + WinINET refresh; macOS: toggle-proxy.sh off, then networksetup to restore previous servers/states). Without a snapshot it behaves as before. If restoring fails, the snapshot is kept so it can be retried.
  • New command: devproxy system-proxy reset [--force]. Restores the settings Dev Proxy changed and removes stale instance records. Refuses (exit 1) when a live Dev Proxy owns the system proxy unless --force is passed. On Linux, where Dev Proxy doesn't change the system proxy, it's a no-op.
  • Automatic recovery on startup. Startup reconciliation now also runs for foreground starts (previously only --detach) and treats a snapshot whose PID is dead as a stale registration, so killed foreground instances are recovered too. It never touches settings owned by a live instance.

Notes / decisions

  • Command name: the issue suggested devproxy proxy reset (name TBD). I went with devproxy system-proxy reset since devproxy proxy is ambiguous with Dev Proxy itself. Happy to rename.
  • Startup cleanup is automatic in all sessions rather than prompting in interactive ones, consistent with the existing detached-mode reconciliation and to avoid blocking startup on input.
  • Linux: Dev Proxy doesn't configure gsettings today (it only logs a hint), so there's nothing to snapshot/restore there.
  • Docs: the troubleshooting page (No internet connection after using the proxy) lives in the docs repo and should mention devproxy system-proxy reset once this ships.

Testing

  • Unit tests for networksetup output parsing, restore command generation, and snapshot store round-trip/corrupt-file handling.
  • dotnet build + full DevProxy.Tests pass. Verified devproxy system-proxy reset --help and detached start/stop with --as-system-proxy false. I didn't run the restore against this machine's real system proxy settings.

…ettings

Dev Proxy now records the OS proxy settings it is about to replace (Windows
ProxyEnable/ProxyServer, macOS networksetup web/secure web proxies) together
with the owning PID, and restores them when it stops instead of just turning
the system proxy off.

Because the snapshot outlives the process, a killed or crashed instance
(foreground or detached) can be recovered:
- 'devproxy system-proxy reset' restores the settings on demand
- Dev Proxy restores a stale registration automatically on startup

Closes dotnet#2060

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@waldekmastykarz
waldekmastykarz requested a review from a team as a code owner November 5, 2026 10:47
Copilot AI balanced review requested due to automatic review settings November 5, 2026 10:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Proxy recovery can silently fail and delete its backup, while forced resets can disable a restored corporate proxy and configuration errors can block recovery entirely.

5 open issues
What changed in this PR

Adds system-proxy recovery to Dev Proxy, preserving previous OS settings so they can be restored after shutdown or a crash.

Changes:

  • Saves Windows and macOS proxy settings before Dev Proxy takes over.
  • Adds devproxy system-proxy reset [--force] and extends automatic recovery to foreground starts.
  • Adds tests for snapshot persistence and macOS parsing and restore commands.
File Description
DevProxy/​State/​StateManager.cs Exposes process-liveness checks for recovery.
DevProxy/​Proxy/​SystemProxySnapshot.cs Adds snapshot storage and macOS settings helpers.
DevProxy/​Proxy/​SystemProxyManager.cs Captures and restores settings; tracks live and orphaned owners.
DevProxy/​Program.cs Runs recovery before foreground startup.
DevProxy/​Commands/​SystemProxyCommand.cs Implements the reset command and force option.
DevProxy/​Commands/​StopCommand.cs Adapts stop reporting to the revised recovery results.
DevProxy/​Commands/​DevProxyCommand.cs Registers the system-proxy command.
DevProxy.Tests/​SystemProxyManagerTests.cs Tests snapshot persistence and macOS helpers.
DevProxy.Abstractions/​Proxy/​ISystemProxyManager.cs Documents restoration behavior for cleanup.

Review effort: Balanced

Comment thread DevProxy/Commands/DevProxyCommand.cs Resolved
Comment thread DevProxy/Commands/SystemProxyCommand.cs Resolved
Comment thread DevProxy/Proxy/SystemProxyManager.cs Resolved
Comment thread DevProxy/Proxy/SystemProxyManager.cs Resolved
Comment thread DevProxy/Commands/SystemProxyCommand.cs Resolved
- Run 'system-proxy reset' before loading config/plugins
- Don't let an instance's shutdown undo a forced reset or another owner
- Treat networksetup timeouts/nonzero exits and toggle-proxy.sh failures as
  restore failures so the snapshot is kept
- Skip disabled macOS services in toggle-proxy.sh and propagate failures
- Report the Linux no-op before checking proxy ownership

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread DevProxy/Commands/SystemProxyCommand.cs Resolved
Comment thread DevProxy/Proxy/SystemProxyManager.cs Resolved
Comment thread DevProxy/Proxy/SystemProxyManager.cs Resolved
Comment thread DevProxy/toggle-proxy.sh Resolved
Comment thread DevProxy/Commands/SystemProxyCommand.cs Resolved
Comment thread DevProxy/Proxy/SystemProxyManager.cs Resolved
- Clear system-proxy ownership on live instances after a forced reset
- Report failed orphan restores distinctly and keep records for retry
- Continue restoring remaining macOS services after a failure
- Fail toggle-proxy.sh when listing network services fails
- Parse standalone reset args with System.CommandLine

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

A partial proxy-disable failure can skip snapshot restoration, leaving affected network services without their previous corporate proxy settings even after retries.

No open issues 🎉

4 previously missed issues

In code that hasn't changed since last review

High severity Restore proxy snapshots even when disabling a service fails

DevProxy/​Proxy/​SystemProxyManager.cs:154

If toggle-proxy.sh off fails for one network service, it can still successfully disable the proxies on the other services. This condition then skips RestoreMacOS entirely, leaving those working services without their previous corporate proxy; retrying repeats the same problem while the failing service remains. Please attempt snapshot restoration even when the disable pass fails, and combine both results so the backup is still retained on either failure.

Medium severity Recognize recovery commands with global options in any position

DevProxy/​Commands/​DevProxyCommand.cs:148

The standalone recovery path is still bypassed when a recursive global option appears between the commands. For example, devproxy system-proxy --no-color reset is valid for the registered command tree, but this positional check returns false. It then builds the application host, where an empty plugins configuration throws before recovery runs. Please recognize the parsed command path independently of global-option placement so these valid invocations also work with broken configurations.

Medium severity Enforce enum validation for standalone options

DevProxy/​Commands/​SystemProxyCommand.cs:56

The registered command validates --output and --log-level as enums, but the standalone path accepts arbitrary strings here. For example, devproxy system-proxy reset --force --log-level typo changes the OS proxy settings instead of rejecting the invalid option before any side effects. Please retain the enum option types in this parser as well.

Medium severity Validate process start time to prevent stale PID ownership

DevProxy/​Proxy/​SystemProxySnapshot.cs:20

After a crash or reboot, the OS can reuse the saved PID for an unrelated process, causing startup recovery to skip restoration and an unforced reset to refuse it. Persist the owner's process start time alongside its PID, refresh both on takeover, and validate both in the ownership and orphan checks. The snapshot's existing CreatedAt cannot identify the current owner because it is preserved across takeovers.

6 resolved since last review

Review effort: Balanced

…ne reset parsing

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@waldekmastykarz

Copy link
Copy Markdown
Collaborator Author

Addressing the previously missed issues from the latest review, fixed in d14a489:

  • Restore snapshots even when disabling fails: fixed. RestoreMacOS now always runs when a snapshot exists, and either failure keeps the snapshot.
  • Global options in any position: fixed. IsSystemProxyResetCommand skips --output/--log-level (and their values) and --no-color before matching the command path.
  • Enum validation in the standalone parser: fixed. It now uses Option<OutputFormat?> and Option<LogLevel?>, so --log-level typo is rejected before any OS change.
  • PID start-time validation: not changing this here. The existing instance state (StateManager.IsProcessRunning, GetOrphanedSystemProxyStatesAsync, stop, status) identifies instances by PID only. The snapshot follows the same model on purpose, so ownership checks stay consistent across the code. If a PID is reused, the worst case is that automatic cleanup is skipped and reset asks for --force, which the error message explains. Validating start time for every PID-based check is a broader change that belongs in a separate issue.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Attached option values cause valid system-proxy reset commands to bypass the standalone recovery path, allowing broken configuration to block the reset.

1 open issue

Review effort: Balanced

Comment thread DevProxy/Commands/DevProxyCommand.cs Resolved
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A help flag in a response file is ignored, causing system-proxy reset --force --help to reset the system proxy instead of displaying help.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread DevProxy/Commands/SystemProxyCommand.cs Resolved
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human review is needed to assess interacting recovery, ownership, and command-routing risks that could lose recovery records or unexpectedly alter system proxy settings.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a command to restore system proxy settings after Dev Proxy was killed or crashed

2 participants