diff --git a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs index a31001ac..8e95d9fc 100644 --- a/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs +++ b/shadowsocks-csharp/Controller/Service/GeositeUpdater.cs @@ -34,8 +34,7 @@ namespace Shadowsocks.Controller private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); - // temporary workaround - private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/releases/download/202005010407/dlc.dat"; + private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat"; public static readonly Dictionary> Geosites = new Dictionary>(); @@ -66,13 +65,21 @@ namespace Shadowsocks.Controller public static void UpdatePACFromGeosite(Configuration config) { - string gfwListUrl = GEOSITE_URL; - if (!string.IsNullOrWhiteSpace(config.gfwListUrl)) + string geositeUrl = GEOSITE_URL; + string group = "geolocation-!cn"; + bool blacklist = true; + if (!string.IsNullOrWhiteSpace(config.geositeGroup)) { - logger.Info("Found custom GFWListURL in config file"); - gfwListUrl = config.gfwListUrl; + group = config.geositeGroup; + blacklist = config.geositeBlacklistMode; } - logger.Info($"Checking GFWList from {gfwListUrl}"); + + if (!string.IsNullOrWhiteSpace(config.geositeUrl)) + { + logger.Info("Found custom Geosite URL in config file"); + geositeUrl = config.geositeUrl; + } + logger.Info($"Checking Geosite from {geositeUrl}"); WebClient http = new WebClient(); if (config.enabled) { @@ -89,7 +96,7 @@ namespace Shadowsocks.Controller File.WriteAllBytes(DATABASE_PATH, e.Result); LoadGeositeList(); - bool pacFileChanged = MergeAndWritePACFile(); + bool pacFileChanged = MergeAndWritePACFile(group, blacklist); UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); } catch (Exception ex) @@ -97,18 +104,13 @@ namespace Shadowsocks.Controller Error?.Invoke(null, new ErrorEventArgs(ex)); } }; - http.DownloadDataAsync(new Uri(gfwListUrl)); - } - - - public static bool MergeAndWritePACFile() - { - return MergeAndWritePACFile(Geosites["cn"]); + http.DownloadDataAsync(new Uri(geositeUrl)); } - private static bool MergeAndWritePACFile(IList domains) + public static bool MergeAndWritePACFile(string group, bool blacklist) { - string abpContent = MergePACFile(domains); + IList domains = Geosites[group]; + string abpContent = MergePACFile(domains, blacklist); if (File.Exists(PACDaemon.PAC_FILE)) { string original = FileManager.NonExclusiveReadAllText(PACDaemon.PAC_FILE, Encoding.UTF8); @@ -121,7 +123,7 @@ namespace Shadowsocks.Controller return true; } - private static string MergePACFile(IList domains) + private static string MergePACFile(IList domains, bool blacklist) { string abpContent; if (File.Exists(PACDaemon.USER_ABP_FILE)) @@ -137,10 +139,10 @@ namespace Shadowsocks.Controller if (File.Exists(PACDaemon.USER_RULE_FILE)) { string userrulesString = FileManager.NonExclusiveReadAllText(PACDaemon.USER_RULE_FILE, Encoding.UTF8); - userruleLines = ParseToValidList(userrulesString); + userruleLines = PreProcessGFWList(userrulesString); } - List gfwLines = ParseToValidList(domains); + List gfwLines = GeositeToGFWList(domains, blacklist); abpContent = $@"var __USERRULES__ = {JsonConvert.SerializeObject(userruleLines, Formatting.Indented)}; var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; @@ -150,7 +152,7 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; private static readonly IEnumerable IgnoredLineBegins = new[] { '!', '[' }; - private static List ParseToValidList(string content) + private static List PreProcessGFWList(string content) { List valid_lines = new List(); using (var sr = new StringReader(content)) @@ -165,12 +167,15 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; return valid_lines; } - private static List ParseToValidList(IList domains) + private static List GeositeToGFWList(IList domains, bool blacklist) { - List ret = new List(domains.Count + 100)// 100 overhead - { - "/.*/" // match any domain, so all non-cn domain go through proxy - }; + return blacklist ? GeositeToGFWListBlack(domains) : GeositeToGFWListWhite(domains); + + } + + private static List GeositeToGFWListBlack(IList domains) + { + List ret = new List(domains.Count + 100);// 100 overhead foreach (var d in domains) { string domain = d.Value; @@ -178,22 +183,29 @@ var __RULES__ = {JsonConvert.SerializeObject(gfwLines, Formatting.Indented)}; switch (d.Type) { case DomainObject.Types.Type.Plain: - ret.Add($"@@{domain}"); + ret.Add(domain); break; case DomainObject.Types.Type.Regex: - ret.Add($"@@/{domain}/"); + ret.Add($"/{domain}/"); break; case DomainObject.Types.Type.Domain: - ret.Add($"@@||{domain}"); + ret.Add($"||{domain}"); break; case DomainObject.Types.Type.Full: - ret.Add($"@@|http://{domain}"); - ret.Add($"@@|https://{domain}"); + ret.Add($"|http://{domain}"); + ret.Add($"|https://{domain}"); break; } } - return ret; } + + private static List GeositeToGFWListWhite(IList domains) + { + return GeositeToGFWListBlack(domains) + .Select(r => $"@@{r}") // convert to whitelist + .Prepend("/.*/") // blacklist all other site + .ToList(); + } } } diff --git a/shadowsocks-csharp/Controller/Service/PACDaemon.cs b/shadowsocks-csharp/Controller/Service/PACDaemon.cs index 5ced121a..04051e7c 100644 --- a/shadowsocks-csharp/Controller/Service/PACDaemon.cs +++ b/shadowsocks-csharp/Controller/Service/PACDaemon.cs @@ -1,4 +1,5 @@ using NLog; +using Shadowsocks.Model; using Shadowsocks.Properties; using Shadowsocks.Util; using System; @@ -21,6 +22,7 @@ namespace Shadowsocks.Controller public const string PAC_FILE = "pac.txt"; public const string USER_RULE_FILE = "user-rule.txt"; public const string USER_ABP_FILE = "abp.txt"; + private Configuration config; FileSystemWatcher PACFileWatcher; FileSystemWatcher UserRuleFileWatcher; @@ -28,8 +30,9 @@ namespace Shadowsocks.Controller public event EventHandler PACFileChanged; public event EventHandler UserRuleFileChanged; - public PACDaemon() + public PACDaemon(Configuration config) { + this.config = config; TouchPACFile(); TouchUserRuleFile(); @@ -42,7 +45,7 @@ namespace Shadowsocks.Controller { if (!File.Exists(PAC_FILE)) { - GeositeUpdater.MergeAndWritePACFile(); + GeositeUpdater.MergeAndWritePACFile(config.geositeGroup, config.geositeBlacklistMode); } return PAC_FILE; } @@ -60,7 +63,7 @@ namespace Shadowsocks.Controller { if (!File.Exists(PAC_FILE)) { - GeositeUpdater.MergeAndWritePACFile(); + GeositeUpdater.MergeAndWritePACFile(config.geositeGroup, config.geositeBlacklistMode); } return File.ReadAllText(PAC_FILE, Encoding.UTF8); } diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index c1c000d6..d3260706 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -524,7 +524,7 @@ namespace Shadowsocks.Controller privoxyRunner = privoxyRunner ?? new PrivoxyRunner(); - _pacDaemon = _pacDaemon ?? new PACDaemon(); + _pacDaemon = _pacDaemon ?? new PACDaemon(_config); _pacDaemon.PACFileChanged += PacDaemon_PACFileChanged; _pacDaemon.UserRuleFileChanged += PacDaemon_UserRuleFileChanged; _pacServer = _pacServer ?? new PACServer(_pacDaemon); @@ -622,7 +622,7 @@ namespace Shadowsocks.Controller private static readonly IEnumerable IgnoredLineBegins = new[] { '!', '[' }; private void PacDaemon_UserRuleFileChanged(object sender, EventArgs e) { - GeositeUpdater.MergeAndWritePACFile(); + GeositeUpdater.MergeAndWritePACFile(_config.geositeGroup, _config.geositeBlacklistMode); UpdateSystemProxy(); } diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index d7d596a7..01339041 100644 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -29,7 +29,10 @@ namespace Shadowsocks.Model public bool portableMode = true; public bool showPluginOutput; public string pacUrl; - public string gfwListUrl; + public string geositeUrl; + public string geositeGroup; + public bool geositeBlacklistMode; + public bool useOnlinePac; public bool secureLocalPac = true; public bool availabilityStatistics;