diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index d5813f0d9..9a9af528d 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -10,6 +10,7 @@ using Shadowsocks.Properties; using Shadowsocks.Util; using System.Threading.Tasks; +using System.Web; namespace Shadowsocks.Controller { @@ -17,8 +18,20 @@ public class PACServer : Listener.Service { public const string RESOURCE_NAME = "pac"; - private string PacSecret { get; set; } = ""; - + private string PacSecret + { + get + { + if (string.IsNullOrEmpty(_cachedPacSecret)) + { + var rd = new byte[32]; + RNG.GetBytes(rd); + _cachedPacSecret = HttpServerUtility.UrlTokenEncode(rd); + } + return _cachedPacSecret; + } + } + private string _cachedPacSecret = ""; public string PacUrl { get; private set; } = ""; private Configuration _config; @@ -31,26 +44,21 @@ public PACServer(PACDaemon pacDaemon) public void UpdatePACURL(Configuration config) { - this._config = config; - - if (config.secureLocalPac) - { - var rd = new byte[32]; - RNG.GetBytes(rd); - PacSecret = $"&secret={Convert.ToBase64String(rd)}"; - } - else - { - PacSecret = ""; - } - - PacUrl = $"http://{config.localHost}:{config.localPort}/{RESOURCE_NAME}?t={GetTimestamp(DateTime.Now)}{PacSecret}"; + _config = config; + string usedSecret = _config.secureLocalPac ? $"&secret={PacSecret}" : ""; + string contentHash = GetHash(_pacDaemon.GetPACContent()); + PacUrl = $"http://{config.localHost}:{config.localPort}/{RESOURCE_NAME}?hash={contentHash}{usedSecret}"; + Logging.Debug("Set PAC URL:" + PacUrl); } - - private static string GetTimestamp(DateTime value) + private static string GetHash(string content) { - return value.ToString("yyyyMMddHHmmssfff"); + var contentBytes = Encoding.ASCII.GetBytes(content); + using (var md5 = System.Security.Cryptography.MD5.Create()) + { + var md5Bytes = md5.ComputeHash(contentBytes); + return HttpServerUtility.UrlTokenEncode(md5Bytes); + }; } public override bool Handle(byte[] firstPacket, int length, Socket socket, object state) @@ -74,7 +82,7 @@ public override bool Handle(byte[] firstPacket, int length, Socket socket, objec string request = Encoding.UTF8.GetString(firstPacket, 0, length); string[] lines = request.Split('\r', '\n'); bool hostMatch = false, pathMatch = false, useSocks = false; - bool secretMatch = PacSecret.IsNullOrEmpty(); + bool secretMatch = _config.secureLocalPac; if (lines.Length < 2) // need at lease RequestLine + Host { @@ -165,7 +173,7 @@ public void SendResponse(Socket socket, bool useSocks) string proxy = GetPACAddress(localEndPoint, useSocks); string pacContent = $"var __PROXY__ = '{proxy}';\n" + _pacDaemon.GetPACContent(); - string responseHead = + string responseHead = $@"HTTP/1.1 200 OK Server: ShadowsocksWindows/{UpdateChecker.Version} Content-Type: application/x-ns-proxy-autoconfig diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 0056e20b8..79ff929d1 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -465,38 +465,19 @@ protected void Reload() _config = Configuration.Load(); StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); - if (privoxyRunner == null) - { - privoxyRunner = new PrivoxyRunner(); - } + privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); - if (_pacDaemon == null) - { - _pacDaemon = new PACDaemon(); - _pacDaemon.PACFileChanged += PacDaemon_PACFileChanged; - _pacDaemon.UserRuleFileChanged += PacDaemon_UserRuleFileChanged; - } + _pacDaemon = _pacDaemon ?? new PACDaemon(); + _pacDaemon.PACFileChanged += PacDaemon_PACFileChanged; + _pacDaemon.UserRuleFileChanged += PacDaemon_UserRuleFileChanged; + _pacServer = _pacServer ?? new PACServer(_pacDaemon); - if (_pacServer == null) - { - _pacServer = new PACServer(_pacDaemon); - } - - _pacServer.UpdatePACURL(_config); - if (gfwListUpdater == null) - { - gfwListUpdater = new GFWListUpdater(); - gfwListUpdater.UpdateCompleted += PacServer_PACUpdateCompleted; - gfwListUpdater.Error += PacServer_PACUpdateError; - } + gfwListUpdater = gfwListUpdater ?? new GFWListUpdater(); + gfwListUpdater.UpdateCompleted += PacServer_PACUpdateCompleted; + gfwListUpdater.Error += PacServer_PACUpdateError; availabilityStatistics.UpdateConfiguration(this); - - if (_listener != null) - { - _listener.Stop(); - } - + _listener?.Stop(); StopPlugins(); // don't put PrivoxyRunner.Start() before pacServer.Stop() @@ -507,10 +488,7 @@ protected void Reload() try { var strategy = GetCurrentStrategy(); - if (strategy != null) - { - strategy.ReloadServers(); - } + strategy?.ReloadServers(); StartPlugin(); privoxyRunner.Start(_config); @@ -547,7 +525,6 @@ protected void Reload() } ConfigChanged?.Invoke(this, new EventArgs()); - UpdateSystemProxy(); Utils.ReleaseMemory(true); } diff --git a/shadowsocks-csharp/Controller/System/SystemProxy.cs b/shadowsocks-csharp/Controller/System/SystemProxy.cs index f02d3d115..e11342abb 100644 --- a/shadowsocks-csharp/Controller/System/SystemProxy.cs +++ b/shadowsocks-csharp/Controller/System/SystemProxy.cs @@ -39,6 +39,7 @@ public static void Update(Configuration config, bool forceDisable, PACServer pac } else { + pacSrv.UpdatePACURL(config); pacUrl = pacSrv.PacUrl; } Sysproxy.SetIEProxy(true, false, null, pacUrl);