注册表破解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.
相关推荐
daols885 分钟前
vxe-table 渲染器教程一:实现金额输入控件
javascript·vue.js·vxe-table
不好听61317 分钟前
React 核心概念:JSX、组件与数据驱动
前端·react.js
触底反弹19 分钟前
🔥 React 零基础入门(中):500 行屎山代码到组件化的蜕变
前端·javascript·react.js
不好听61319 分钟前
React vs Vue:两大前端框架技术选型深度对比
前端·vue.js·react.js
GuWenyue20 分钟前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue20 分钟前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
小林ixn1 小时前
从 onclick 到 React 合成事件,再到完整应用逻辑:一次前端架构的深度剖析
前端·react.js·前端框架
Csvn2 小时前
🧩「找不到模块」排查全记录——Monorepo 下 TypeScript 路径别名的 5 种「不通」与根治方案
前端
腻害兔2 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
Miao121312 小时前
某海外住宿平台如何在大规模场景下实现指标一致性:Minerva 指标平台实践
大数据·数据库·人工智能