From a0786a435fd729b9fb1d91c42577d670e0d5195b Mon Sep 17 00:00:00 2001 From: Student Main Date: Thu, 28 Nov 2019 20:14:41 +0800 Subject: [PATCH 1/4] Use MD5 hash instead of timestamp for PAC URL --- shadowsocks-csharp/Controller/Service/PACServer.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index d5813f0d9..3444039cc 100644 --- a/shadowsocks-csharp/Controller/Service/PACServer.cs +++ b/shadowsocks-csharp/Controller/Service/PACServer.cs @@ -44,13 +44,18 @@ public void UpdatePACURL(Configuration config) PacSecret = ""; } - PacUrl = $"http://{config.localHost}:{config.localPort}/{RESOURCE_NAME}?t={GetTimestamp(DateTime.Now)}{PacSecret}"; + PacUrl = $"http://{config.localHost}:{config.localPort}/{RESOURCE_NAME}?hash={GetHash(_pacDaemon.GetPACContent())}{PacSecret}"; } - 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 BitConverter.ToString(md5Bytes).Replace("-", ""); + }; } public override bool Handle(byte[] firstPacket, int length, Socket socket, object state) @@ -165,7 +170,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 From 84f849151362e2aff2bd0225029379ee7080983f Mon Sep 17 00:00:00 2001 From: Student Main Date: Mon, 2 Dec 2019 14:12:34 +0800 Subject: [PATCH 2/4] generate PacSecret only once. --- .../Controller/Service/PACServer.cs | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/shadowsocks-csharp/Controller/Service/PACServer.cs b/shadowsocks-csharp/Controller/Service/PACServer.cs index 3444039cc..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,30 +44,20 @@ 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}?hash={GetHash(_pacDaemon.GetPACContent())}{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 GetHash(string content) { var contentBytes = Encoding.ASCII.GetBytes(content); using (var md5 = System.Security.Cryptography.MD5.Create()) { var md5Bytes = md5.ComputeHash(contentBytes); - return BitConverter.ToString(md5Bytes).Replace("-", ""); + return HttpServerUtility.UrlTokenEncode(md5Bytes); }; } @@ -79,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 { From fb4f7ea2eb351208a635f1e1c51ba212f2ccc822 Mon Sep 17 00:00:00 2001 From: Student Main Date: Mon, 2 Dec 2019 14:36:07 +0800 Subject: [PATCH 3/4] change PAC URL only when SystemProxy.Update --- shadowsocks-csharp/Controller/ShadowsocksController.cs | 1 - shadowsocks-csharp/Controller/System/SystemProxy.cs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 0056e20b8..c94cbe393 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -482,7 +482,6 @@ protected void Reload() _pacServer = new PACServer(_pacDaemon); } - _pacServer.UpdatePACURL(_config); if (gfwListUpdater == null) { gfwListUpdater = new GFWListUpdater(); 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); From fb369a1e1ed77fdf985937931058dbcff0064c47 Mon Sep 17 00:00:00 2001 From: Student Main Date: Mon, 2 Dec 2019 14:43:03 +0800 Subject: [PATCH 4/4] Use new grammar in Controller.Reload for readability --- .../Controller/ShadowsocksController.cs | 42 +++++-------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index c94cbe393..79ff929d1 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -465,37 +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); - } - - 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() @@ -506,10 +488,7 @@ protected void Reload() try { var strategy = GetCurrentStrategy(); - if (strategy != null) - { - strategy.ReloadServers(); - } + strategy?.ReloadServers(); StartPlugin(); privoxyRunner.Start(_config); @@ -546,7 +525,6 @@ protected void Reload() } ConfigChanged?.Invoke(this, new EventArgs()); - UpdateSystemProxy(); Utils.ReleaseMemory(true); }