注册表破解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.
相关推荐
陆枫Larry3 分钟前
JavaScript 中的竞态是什么,为啥会有竟态?
前端
IvorySQL2 小时前
PostgreSQL 日报 | JOIN 与外键优化(8 月 9 日)
数据库·postgresql
ltl2 小时前
自治数据库十年回顾:Peloton、NoisePage、OtterTune 到云原生 auto-tuning
数据库
DevUI团队3 小时前
从“即兴创作”到“规格先行”,华为云码道(CodeArts)代码智能体持续深耕企业级规范驱动开发能力
前端·人工智能·后端
weixin_431600444 小时前
NestJS 入门(3):Guard 如何挡住未登录请求?
前端·后端·学习·nest.js
灯澜忆梦4 小时前
【MySQL10】进阶篇 | 索引_#2性能优化
数据库·sql·mysql·性能优化
avi91114 小时前
[AI教做人]AI平台做2项目;一个3D模型展示,另一个框架多人
javascript·人工智能·ai·3d模型·3d引擎·顶点和法线
kyriewen4 小时前
我用Claude Code两天干完了团队两周的排期——周报发出去那一刻我就后悔了
前端·javascript·ai编程
IT_陈寒4 小时前
JavaScript类型转换把我坑惨了,这破玩意真该早点搞明白
前端·人工智能·后端
用户938515635075 小时前
Type vs Interface:读完这篇就没有面试官能难倒你了
前端·面试·typescript