进程的组成,进程和程序

尾翰音

最近有用户反馈Win10系统每次开机后,打开进程管理,都会看到有很多的HTTP Auto Proxy Detection Process 进程,有非常多,几十个,那么遇到这样的问题该如何解决呢?

原因分析:

首先这是正常现象(不是木马也不是病毒),产生的原因是你的小飞机造成的,每次关闭一次,再打开就会有一个新进程,这是Windows自动处理PAC的进程,因为小飞机每次启用的时候,使用了一个随机字符串生成PAC,所以每一个新的PAC都对应一个新的HTTP XXXX的进程,重启一次电脑(而不是关机再开机)可减少这个进程。

解决方法一:

等待官方更新

解决方法二:

    HTTP Auto Proxy Detection Worker Process进程的程序文件是C:WindowsSystem32pacjsworker.exe,由WPAD服务启动;这些进程不能手工杀死,重启系统才能解决,用户退出(logout)再登录也不行;WPAD服务(Win HTTP Web Proxy Auto Discovery Service)的属性不能修改,通过重启WPAD服务杀死进程的路也不通;1809版本才会出现,在这之前版本的系统上运行正常;情况复现:

    打开SS客户端,选择PAC模式,勾选启用系统代理;然后按电源键(或其他方式)让电脑进入休眠;接着唤醒电脑进入桌面,任务管理器中就多了一个HTTP Auto Proxy Detection Worker Process进程;如此反复进入休眠又启动,每次都会出现一个新进程;后来发现不需要休眠也能复现情况:

    打开SS客户端,选择PAC模式,打开任务管理器;然后不断禁用/启用系统代理,在任务管理器窗口中可实时看到每次启用系统代理后都会多一个进程;最新版的SS客户端依然有这个问题;每次SS启动系统代理后的PAC地址均不同;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设置中。

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

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

我的解决方案是重新编译SS客户端,做了两个方案的客户端:

    方案一:

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

    pre// 文件:

    shadowsocks-csharpControllerServicePACServer.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};

}

/pre

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

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

    pre// 文件

    shadowsocks-csharpControllerShadowsocksController.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();

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文件我都编译好了,需要请自取:

方案一 方案二