注册表破解chrome,edge阻止浏览器连接本地websocket

BrowserRole (Delphi)

用于给 Windows Chrome + Edge 写入/回滚 Local Network Access 相关企业策略,解决公网页面连接局域网/本机 WebSocket 服务时被新版本浏览器限制的问题。

功能

  • `apply <origin>`: 写入策略(Chrome + Edge)

  • `rollback`: 回滚策略(Chrome + Edge)

文件

  • `ChromeRole.dpr`:控制台程序源码(你可编译成 `BrowserRole.exe`)

编译

用 Delphi 直接打开 `ChromeRole.dpr` 编译。

使用

  1. 以管理员权限运行(必须)

  2. 应用策略:

```bat

BrowserRole.exe apply https://etk.example.com

```

  1. 回滚策略:

```bat

BrowserRole.exe rollback

```

  1. 执行后重启浏览器,访问 `chrome://policy` 和 `edge://policy` 点击 `Reload policies` 验证。

写入的策略位置

Chrome:

  • `HKLM\SOFTWARE\Policies\Google\Chrome\LocalNetworkAccessRestrictionsTemporaryOptOut` = `1`

  • `HKLM\SOFTWARE\Policies\Google\Chrome\LocalNetworkAccessAllowedForUrls\1` = `<origin>`

  • `HKLM\SOFTWARE\Policies\Google\Chrome\LocalNetworkAllowedForUrls\1` = `<origin>`

Edge:

  • `HKLM\SOFTWARE\Policies\Microsoft\Edge\LocalNetworkAccessRestrictionsTemporaryOptOut` = `1`

  • `HKLM\SOFTWARE\Policies\Microsoft\Edge\LocalNetworkAccessAllowedForUrls\1` = `<origin>`

  • `HKLM\SOFTWARE\Policies\Microsoft\Edge\LocalNetworkAllowedForUrls\1` = `<origin>`

> 说明:`TemporaryOptOut` 是过渡策略,后续大版本可能移除,建议长期仍推进插件/服务端改造(例如更规范的权限与安全通信方案)。

复制代码
program ChromeRole;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Win.Registry,
  Winapi.Windows;

const
  CHROME_POLICY_ROOT = 'SOFTWARE\Policies\Google\Chrome';
  EDGE_POLICY_ROOT = 'SOFTWARE\Policies\Microsoft\Edge';

  SUBKEY_LNA_ALLOWED_OLD = 'LocalNetworkAccessAllowedForUrls';
  SUBKEY_LNA_ALLOWED_NEW = 'LocalNetworkAllowedForUrls';

  VALUE_TEMP_OPT_OUT = 'LocalNetworkAccessRestrictionsTemporaryOptOut';

procedure WriteStatus(const S: string);
begin
  Writeln(S);
end;

function SetDwordValue(const Root, Name: string; Value: Cardinal): Boolean;
var
  R: TRegistry;
begin
  Result := False;
  R := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY);
  try
    R.RootKey := HKEY_LOCAL_MACHINE;
    if R.OpenKey(Root, True) then
    begin
      R.WriteInteger(Name, Integer(Value));
      Result := True;
    end;
  finally
    R.Free;
  end;
end;

function SetStringValue(const Root, Name, Value: string): Boolean;
var
  R: TRegistry;
begin
  Result := False;
  R := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY);
  try
    R.RootKey := HKEY_LOCAL_MACHINE;
    if R.OpenKey(Root, True) then
    begin
      R.WriteString(Name, Value);
      Result := True;
    end;
  finally
    R.Free;
  end;
end;

procedure DeleteValueIfExists(const Root, Name: string);
var
  R: TRegistry;
begin
  R := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY);
  try
    R.RootKey := HKEY_LOCAL_MACHINE;
    if R.OpenKey(Root, False) then
      if R.ValueExists(Name) then
        R.DeleteValue(Name);
  finally
    R.Free;
  end;
end;

procedure DeleteKeyTreeIfExists(const ParentPath, SubKeyName: string);
var
  R: TRegistry;
begin
  R := TRegistry.Create(KEY_WRITE or KEY_WOW64_64KEY);
  try
    R.RootKey := HKEY_LOCAL_MACHINE;
    if R.OpenKey(ParentPath, False) then
      if R.KeyExists(SubKeyName) then
        R.DeleteKey(SubKeyName);
  finally
    R.Free;
  end;
end;

procedure ApplyBrowserPolicies(const BrowserPolicyRoot, BrowserName, Origin: string);
var
  KeyOld: string;
  KeyNew: string;
begin
  KeyOld := BrowserPolicyRoot + '\\' + SUBKEY_LNA_ALLOWED_OLD;
  KeyNew := BrowserPolicyRoot + '\\' + SUBKEY_LNA_ALLOWED_NEW;

  if not SetDwordValue(BrowserPolicyRoot, VALUE_TEMP_OPT_OUT, 1) then
    raise Exception.CreateFmt('Failed to write %s TemporaryOptOut policy. Run as administrator.', [BrowserName]);

  if not SetStringValue(KeyOld, '1', Origin) then
    raise Exception.CreateFmt('Failed to write %s %s.', [BrowserName, SUBKEY_LNA_ALLOWED_OLD]);

  if not SetStringValue(KeyNew, '1', Origin) then
    raise Exception.CreateFmt('Failed to write %s %s.', [BrowserName, SUBKEY_LNA_ALLOWED_NEW]);
end;

procedure RollbackBrowserPolicies(const BrowserPolicyRoot: string);
begin
  DeleteValueIfExists(BrowserPolicyRoot, VALUE_TEMP_OPT_OUT);
  DeleteKeyTreeIfExists(BrowserPolicyRoot, SUBKEY_LNA_ALLOWED_OLD);
  DeleteKeyTreeIfExists(BrowserPolicyRoot, SUBKEY_LNA_ALLOWED_NEW);
end;

procedure ApplyPolicies(const Origin: string);
begin
  if Origin.Trim.IsEmpty then
    raise Exception.Create('origin is empty. Example: https://etk.example.com');

  ApplyBrowserPolicies(CHROME_POLICY_ROOT, 'Chrome', Origin);
  ApplyBrowserPolicies(EDGE_POLICY_ROOT, 'Edge', Origin);

  WriteStatus('Policies applied successfully for Chrome and Edge.');
  WriteStatus('Please restart browsers and open chrome://policy / edge://policy -> Reload policies');
end;

procedure RollbackPolicies;
begin
  RollbackBrowserPolicies(CHROME_POLICY_ROOT);
  RollbackBrowserPolicies(EDGE_POLICY_ROOT);

  WriteStatus('Policy rollback finished for Chrome and Edge.');
  WriteStatus('Please restart browsers and open chrome://policy / edge://policy -> Reload policies');
end;

procedure PrintUsage;
begin
  Writeln('Usage:');
  Writeln('  BrowserRole.exe apply <origin>');
  Writeln('  BrowserRole.exe rollback');
  Writeln('');
  Writeln('Examples:');
  Writeln('  BrowserRole.exe apply https://etk.example.com');
  Writeln('  BrowserRole.exe rollback');
end;

var
  Cmd: string;
  Origin: string;

begin
  try
    if ParamCount = 0 then
    begin
      PrintUsage;
      ExitCode := 1;
      Exit;
    end;

    Cmd := LowerCase(Trim(ParamStr(1)));

    if Cmd = 'apply' then
    begin
      if ParamCount < 2 then
        raise Exception.Create('Missing origin. Example: BrowserRole.exe apply https://etk.example.com');
      Origin := Trim(ParamStr(2));
      ApplyPolicies(Origin);
      ExitCode := 0;
    end
    else if Cmd = 'rollback' then
    begin
      RollbackPolicies;
      ExitCode := 0;
    end
    else
    begin
      PrintUsage;
      ExitCode := 1;
    end;
  except
    on E: Exception do
    begin
      Writeln('Error: ' + E.Message);
      Writeln('Tip: run this program as Administrator.');
      ExitCode := 2;
    end;
  end;
end.
相关推荐
lichenyang4534 小时前
Docker 学习笔记(一):为什么需要镜像、容器和仓库?
前端
kyriewen4 小时前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
IT_陈寒4 小时前
SpringBoot自动配置的坑,我的API突然就404了
前端·人工智能·后端
free355 小时前
从 0 实现一个 Tiny JavaScript VM:项目架构拆解
javascript
GBASE5 小时前
G术时刻 |GBase 8s数据库事务并发控制之封锁技术介绍(下)
数据库
奇奇怪怪的5 小时前
Embedding 模型 10+ 横向评测
前端
陈广亮5 小时前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端
子兮曰5 小时前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
敲代码的鱼5 小时前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios