原因分析:
首先這是正常現(xiàn)象(不是木馬也不是病毒),產(chǎn)生的原因是你的小飛機(jī)造成的,每次關(guān)閉一次,再打開就會(huì)有一個(gè)新進(jìn)程,這是Windows自動(dòng)處理PAC的進(jìn)程,因?yàn)樾★w機(jī)每次啟用的時(shí)候,使用了一個(gè)隨機(jī)字符串生成PAC,所以每一個(gè)新的PAC都對(duì)應(yīng)一個(gè)新的HTTP XXXX的進(jìn)程,重啟一次電腦(而不是關(guān)機(jī)再開機(jī))可減少這個(gè)進(jìn)程。
解決方法一:等待官方更新
解決方法二:
- HTTP Auto Proxy Detection Worker Process進(jìn)程的程序文件是"C:WindowsSystem32pacjsworker.exe",由WPAD服務(wù)啟動(dòng);
- 這些進(jìn)程不能手工殺死,重啟系統(tǒng)才能解決,用戶退出(logout)再登錄也不行;
- WPAD服務(wù)(Win HTTP Web Proxy Auto Discovery Service)的屬性不能修改,通過重啟WPAD服務(wù)殺死進(jìn)程的路也不通;
- 1809版本才會(huì)出現(xiàn),在這之前版本的系統(tǒng)上運(yùn)行正常;
- 情況復(fù)現(xiàn):打開SS客戶端,選擇PAC模式,勾選啟用系統(tǒng)代理;然后按電源鍵(或其他方式)讓電腦進(jìn)入休眠;接著喚醒電腦進(jìn)入桌面,任務(wù)管理器中就多了一個(gè)HTTP Auto Proxy Detection Worker Process進(jìn)程;如此反復(fù)進(jìn)入休眠又啟動(dòng),每次都會(huì)出現(xiàn)一個(gè)新進(jìn)程;
- 后來發(fā)現(xiàn)不需要休眠也能復(fù)現(xiàn)情況:打開SS客戶端,選擇PAC模式,打開任務(wù)管理器;然后不斷禁用/啟用系統(tǒng)代理,在任務(wù)管理器窗口中可實(shí)時(shí)看到每次啟用系統(tǒng)代理后都會(huì)多一個(gè)進(jìn)程;
- 最新版的SS客戶端依然有這個(gè)問題;
- 每次SS啟動(dòng)系統(tǒng)代理后的PAC地址均不同;
- PAC地址中的secret參數(shù)僅在勾選“保護(hù)本地PAC(secure local PAC)”選項(xiàng)時(shí)才會(huì)出現(xiàn),但t參數(shù)一直都在。
根據(jù)網(wǎng)上知識(shí),加上個(gè)人實(shí)驗(yàn)和思考,對(duì)問題原因的理解為:WPAD是系統(tǒng)關(guān)鍵服務(wù),用戶不能更改;以PAC模式啟動(dòng)SS時(shí),SS會(huì)在LAN配置中設(shè)置一個(gè)新的PAC腳本地址;WPAD檢測到有新的PAC腳本地址,喚醒一個(gè)新的pacjsworker.exe進(jìn)程監(jiān)聽該地址;PAC地址失效后,監(jiān)聽進(jìn)程不退出,于是進(jìn)程堆積,慢慢出現(xiàn)幾十上百個(gè)進(jìn)程的壯觀場景。
總結(jié)問題根源:1. Windows 10的進(jìn)程不自動(dòng)退出;2. 每次從休眠過來后,SS客戶端生成不同的PAC地址并將其配置到LAN設(shè)置中。
把問題搞清楚了,解決方案基本上章口就萊:
- 使用全局模式;全局模式不會(huì)設(shè)置PAC配置腳本,WPAD服務(wù)也就不會(huì)拉起新的進(jìn)程;
- 等待巨硬修復(fù)問題;去年下半年就爆出問題,到現(xiàn)在問題依舊,應(yīng)該有得等(本人最近才更新1809版本,故而發(fā)現(xiàn)得遲);另外我不認(rèn)為這是巨硬的鍋,他們未必會(huì)修復(fù);
- 重新編譯SS客戶端,生成相同的PAC(至少未重啟SS客戶端前PAC地址應(yīng)一致)。
我的解決方案是重新編譯SS客戶端,做了兩個(gè)方案的客戶端:
- 方案一:總是生成相同的PAC地址,除非人工編輯"pac-secret.txt"文件。改動(dòng)代碼如下:
<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>
這個(gè)方案保證不管系統(tǒng)休眠重啟,還是退出SS客戶端再打開,都只會(huì)有一個(gè)HTTP Auto Proxy Detection Worker Process進(jìn)程。
- 僅當(dāng)系統(tǒng)中無PAC進(jìn)程運(yùn)行時(shí)才生成新的PAC地址并設(shè)置到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; }
這個(gè)方案保證不退出SS客戶端情況下只有一個(gè)pacjsworker.exe進(jìn)程。缺點(diǎn)是如果頻繁退出并重啟SS客戶端,同樣會(huì)出現(xiàn)有大量進(jìn)程的現(xiàn)象。
根據(jù)源代碼思路,我認(rèn)為第二種方案更合理,是原作者想要的。當(dāng)然你應(yīng)該想得到,我是先根據(jù)網(wǎng)上提示實(shí)現(xiàn)方案一,測試達(dá)到效果后繼續(xù)思考才做出的方案二。從這個(gè)角度也是方案二更合理。
兩個(gè)方案的exe文件我都編譯好了,需要請(qǐng)自取:方案一 方案二