系统出现大量HTTP Auto Proxy Detection Worker Process

By | 2019年2月7日

如果不关心原理,可直接下载本人编译好的修复版:Shadowsocks/SS修复版 ShadowsocksR/SSR修复版

今天打开任务管理器,发现有大量“HTTP Auto Proxy Detection Worker Process”进程,画风如下:

根据进程名称,应该和代理有关,因为电脑上开着Shadowsocks。但是这么多什么鬼?打群架吗?

退出SS程序,发现这些进程不会随之退出。意识到这超出了我的知识范围,于是马上打开Google学学。根据有限的搜索结果,基本上确认和SS有关,并且仅会出现在1809版的Windows 10上。我今天才发现这个现象,顺便确认了系统是1809版的bug10:

花了一个多小时理解WPAD、PAC和pacjsworker.exe关系,并加上自己反复测验,得到一些结论:

  1. HTTP Auto Proxy Detection Worker Process进程的程序文件是”C:\Windows\System32\pacjsworker.exe”,由WPAD服务启动;
  2. 这些进程不能手工杀死,重启系统才能解决,用户退出(logout)再登录也不行;
  3. WPAD服务(Win HTTP Web Proxy Auto Discovery Service)的属性不能修改,通过重启WPAD服务杀死进程的路也不通;
  4. 1809版本才会出现,在这之前版本的系统上运行正常;根据Twitter链接https://twitter.com/epakskape/status/1007316208087994368,应该是build 17692引入新功能导致;
  5. 情况复现:打开SS客户端,选择PAC模式,勾选启用系统代理;然后按电源键(或其他方式)让电脑进入休眠;接着唤醒电脑进入桌面,任务管理器中就多了一个HTTP Auto Proxy Detection Worker Process进程;如此反复进入休眠又启动,每次都会出现一个新进程;
  6. 后来发现不需要休眠也能复现情况:打开SS客户端,选择PAC模式,打开任务管理器;然后不断禁用/启用系统代理,在任务管理器窗口中可实时看到每次启用系统代理后都会多一个进程;
  7. 最新版的SS客户端依然有这个问题;
  8. 每次SS启动系统代理后的PAC地址均不同;
  9. PAC地址中的secret参数仅在勾选“保护本地PAC(secure local PAC)”选项时才会出现,但t参数一直都在。

根据网上知识,加上个人实验和思考,对问题原因的理解为:WPAD是系统关键服务,用户不能更改;以PAC模式启动SS时,SS会在LAN配置中设置一个新的PAC脚本地址;WPAD检测到有新的PAC脚本地址,唤醒一个新的pacjsworker.exe进程监听该地址;PAC地址失效后,监听进程不退出,于是进程堆积,慢慢出现几十上百个进程的壮观场景。

总结问题根源:1. Windows 10的进程不自动退出;2. 每次从休眠过来后,SS客户端生成不同的PAC地址并将其配置到LAN设置中。

把问题搞清楚了,解决方案基本上章口就莱:

  1. 使用全局模式;全局模式不会设置PAC配置脚本,WPAD服务也就不会拉起新的进程;
  2. 等待巨硬修复问题;去年下半年就爆出问题,到现在问题依旧,应该有得等(本人最近才更新1809版本,故而发现得迟);另外我不认为这是巨硬的锅,他们未必会修复;
  3. 重新编译SS客户端,生成相同的PAC(至少未重启SS客户端前PAC地址应一致)。

我的解决方案是重新编译SS客户端,根据 @Joelism 的提示及自己理解,做了两个方案的客户端:

  1. 方案一:总是生成相同的PAC地址,除非人工编辑”pac-secret.txt”文件。改动代码如下:

    // 文件: shadowsocks-csharp\Controller\Service\PACServer.cs
    public void UpdateConfiguration(Configuration config)
    {
    this._config = config;
    
    if (config.secureLocalPac)
    {
    // 注释掉部分
    // var rd = new byte[32];
    // RNG.GetBytes(rd);
    // PacSecret = $"&secret={Convert.ToBase64String(rd)}";
    if (!File.Exists(PAC_SECRET_FILE))
    {
    var rd = new byte[32];
    RNG.GetBytes(rd);
    string secret = Convert.ToBase64String(rd);
    PacSecret = $"secret={secret}";
    File.WriteAllText(PAC_SECRET_FILE, secret);
    }
    else
    {
    PacSecret = $"secret={File.ReadAllText(PAC_SECRET_FILE)}";
    }
    }
    else
    {
    PacSecret = "";
    }
    // 注释掉部分
    // PacUrl = $"http://127.0.0.1:{config.localPort}/pac?t={GetTimestamp(DateTime.Now)}{PacSecret}";
    PacUrl = $"http://127.0.0.1:{config.localPort}/pac?{PacSecret}";
    }
    

    这个方案保证不管系统休眠重启,还是退出SS客户端再打开,都只会有一个HTTP Auto Proxy Detection Worker Process进程。

  2. 仅当系统中无PAC进程运行时才生成新的PAC地址并设置到LAN中。代码如下:

    // 文件: shadowsocks-csharp\Controller\ShadowsocksController.cs
    protected void Reload()
    {
    Encryption.RNG.Reload();
    // some logic in configuration updated the config when saving, we need to read it again
    _config = Configuration.Load();
    StatisticsConfiguration = StatisticsStrategyConfiguration.Load();</code>
    
    if (privoxyRunner == null) {
        privoxyRunner = new PrivoxyRunner();
    }
    if (_pacServer == null) {
        _pacServer = new PACServer();
        _pacServer.PACFileChanged += pacServer_PACFileChanged;
        _pacServer.UserRuleFileChanged += pacServer_UserRuleFileChanged;
        // 这一行代码从外部移入
        _pacServer.UpdateConfiguration(_config);
    }
    // 每次唤醒都更新的代码删除 
    // _pacServer.UpdateConfiguration(_config);
    if (gfwListUpdater == null) { 
        gfwListUpdater = new GFWListUpdater(); 
        gfwListUpdater.UpdateCompleted += pacServer_PACUpdateCompleted;
        gfwListUpdater.Error += pacServer_PACUpdateError; 
    }
    ...
    }
    

    这个方案保证不退出SS客户端情况下只有一个pacjsworker.exe进程。缺点是如果频繁退出并重启SS客户端,同样会出现有大量进程的现象。

根据源代码思路,我认为第二种方案更合理,是原作者想要的。当然你应该想得到,我是先根据网上提示实现方案一,测试达到效果后继续思考才做出的方案二。从这个角度也是方案二更合理。

两个方案的exe文件我都编译好了,需要请自取:方案一 方案二

如果你用的SSR,请到这个页面下载:ShadowsocksR/SSR修复版

稍后我会发一个pull request到官方库,使用方案二修复该问题。

问题相关网页

相关文章

9 thoughts on “系统出现大量HTTP Auto Proxy Detection Worker Process

  1. 头像alex romance

    本机win10 1809,所以默认使用的应该是dotnet4.0的组件,而且运行官方版本的dotnet4.0的ssr没有出现需要下载dotnet3.5包括2.0的提示。我对比您打包的exe,dotnet4.0和dotnet2.0的两个exe文件大小一致,但是官方版本的两个exe大小是不同的。所以是不是您的打包选项还有点问题。最后两个问题哈,一个是现在的官方库地址麻烦告知一下好么,另一个是您pull 到官方库的进度怎么样了?

    Reply
  2. 头像alex romance

    你好,下载您的ssr修复版后,使用dotnet4.0提示需要下载framework3.5包括2.0 ,但是dotnet2.0也是提示需要下载framework3.5包括2.0,那4.0那版是不是有什么问题

    Reply
    1. tlanyantlanyan Post author

      我对.net的运行方式不清楚,但我想你的系统应该缺少.net程序运行的必要组件

      Reply
      1. 头像alex romance

        我试过你发的官方版那个dotnet4.0的,那个是不需要提示下载framework3.5包括2.0,本机是win10 1809的,所以应该默认使用的是dotnet4.0的组件的。而且我查看您的打包好的,3个exe文件大小是一样的。。。但是那个官方版本的dotnet2.0 和 dotnet4.0版本的两个exe是文件大小不一样的

        Reply
      2. 头像alex romance

        本机是win10 1809的,所以默认应该是用的dotnet4.0的组件,使用那个官方版本的dotnet4.0就没提示需要下载组件,而且您打包的dotnet2.0和dotnet4.0的两个exe文件大小是一致的,但是官方版本的两个exe文件大小是不一致的

        Reply
      3. 头像alex romance

        本机win10 1809,所以默认使用的应该是dotnet4.0的吧,麻烦大佬告知一下目前官方库的地址。

        Reply
        1. tlanyantlanyan Post author

          Shadowsocks官方仓库:https://github.com/shadowsocks/shadowsocks-windows
          ShadowsocksR官方仓库:https://github.com/shadowsocksrr/shadowsocksr-csharp。提示:SSR官方已经停止开发。

          根据SS官方的issue,大量pacjsworker.exe的bug在即将发布的新版中会自动消失,似乎没有修复的必要,SS官方开发hold住了我的pull,等待新版发布并确认。

          你反馈的SSR编译文件问题,有空我会查看,谢谢。

          Reply
          1. 头像alex romance

            不好意思啊。之前可能是网络有问题,以为没回复到,所以回复了很多遍,实在是不好意思啊,麻烦您把多余的删掉即可。谢谢

发表评论

电子邮件地址不会被公开。 必填项已用*标注