🔐 Add Sha256sum verification for GeoSite db + other fixes and cleanup
pull/2937/head
@@ -1,15 +0,0 @@ | |||
OpenSSL library guide for VS2017 | |||
# Read NOTES.WIN and NOTES.PERL | |||
# use Visual Studio native tools command prompt | |||
# use activeperl, install NASM assembler | |||
ppm install dmake | |||
# Win32 x86 | |||
set PATH=D:\NASM-32;%PATH% | |||
perl Configure VC-WIN32 --release --prefix=C:\Users\home\Downloads\openssl-1.1.0g\x86-build --openssldir=C:\Users\home\Downloads\openssl-1.1.0g\x86-install | |||
nmake | |||
nmake test | |||
# to rebuild | |||
nmake distclean |
@@ -114,7 +114,7 @@ after_build: | |||
$text += 'SHA-256' + $newLine | |||
$text += (Get-FileHash $file -Algorithm SHA256).Hash + $newLine | |||
$text += 'SHA-512' + $newLine | |||
$text += (Get-FileHash $file -Algorithm SHA512).Hash | |||
$text += (Get-FileHash $file -Algorithm SHA512).Hash + $newLine | |||
return $text | |||
} | |||
@@ -9,6 +9,9 @@ using System.Text; | |||
using Newtonsoft.Json; | |||
using Shadowsocks.Model; | |||
using System.Net; | |||
using System.Net.Http; | |||
using System.Threading.Tasks; | |||
using System.Security.Cryptography; | |||
namespace Shadowsocks.Controller | |||
{ | |||
@@ -32,23 +35,37 @@ namespace Shadowsocks.Controller | |||
private static readonly string DATABASE_PATH = Utils.GetTempPath("dlc.dat"); | |||
private static SocketsHttpHandler socketsHttpHandler; | |||
private static HttpClient httpClient; | |||
private static readonly string GEOSITE_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat"; | |||
private static readonly string GEOSITE_SHA256SUM_URL = "https://github.com/v2ray/domain-list-community/raw/release/dlc.dat.sha256sum"; | |||
private static byte[] geositeDB; | |||
public static readonly Dictionary<string, IList<DomainObject>> Geosites = new Dictionary<string, IList<DomainObject>>(); | |||
static GeositeUpdater() | |||
{ | |||
if (!File.Exists(DATABASE_PATH)) | |||
//socketsHttpHandler = new SocketsHttpHandler(); | |||
//httpClient = new HttpClient(socketsHttpHandler); | |||
if (File.Exists(DATABASE_PATH) && new FileInfo(DATABASE_PATH).Length > 0) | |||
{ | |||
geositeDB = File.ReadAllBytes(DATABASE_PATH); | |||
} | |||
else | |||
{ | |||
geositeDB = Resources.dlc_dat; | |||
File.WriteAllBytes(DATABASE_PATH, Resources.dlc_dat); | |||
} | |||
LoadGeositeList(); | |||
} | |||
static void LoadGeositeList(byte[] data = null) | |||
/// <summary> | |||
/// load new GeoSite data from geositeDB | |||
/// </summary> | |||
static void LoadGeositeList() | |||
{ | |||
data = data ?? File.ReadAllBytes(DATABASE_PATH); | |||
var list = GeositeList.Parser.ParseFrom(data); | |||
var list = GeositeList.Parser.ParseFrom(geositeDB); | |||
foreach (var item in list.Entries) | |||
{ | |||
Geosites[item.GroupName.ToLower()] = item.Domains; | |||
@@ -61,9 +78,12 @@ namespace Shadowsocks.Controller | |||
Error = null; | |||
} | |||
public static void UpdatePACFromGeosite(Configuration config) | |||
public static async Task UpdatePACFromGeosite() | |||
{ | |||
string geositeUrl = GEOSITE_URL; | |||
string geositeSha256sumUrl = GEOSITE_SHA256SUM_URL; | |||
SHA256 mySHA256 = SHA256.Create(); | |||
var config = Program.MainController.GetCurrentConfiguration(); | |||
string group = config.geositeGroup; | |||
bool blacklist = config.geositeBlacklistMode; | |||
@@ -73,31 +93,83 @@ namespace Shadowsocks.Controller | |||
geositeUrl = config.geositeUrl; | |||
} | |||
logger.Info($"Checking Geosite from {geositeUrl}"); | |||
WebClient http = new WebClient(); | |||
// use System.Net.Http.HttpClient to download GeoSite db. | |||
// NASTY workaround: new HttpClient every update | |||
// because we can't change proxy on existing socketsHttpHandler instance | |||
socketsHttpHandler = new SocketsHttpHandler(); | |||
httpClient = new HttpClient(socketsHttpHandler); | |||
if (config.enabled) | |||
{ | |||
http.Proxy = new WebProxy( | |||
socketsHttpHandler.UseProxy = true; | |||
socketsHttpHandler.Proxy = new WebProxy( | |||
config.isIPv6Enabled | |||
? $"[{IPAddress.IPv6Loopback}]" | |||
: IPAddress.Loopback.ToString(), | |||
config.localPort); | |||
} | |||
http.DownloadDataCompleted += (o, e) => | |||
try | |||
{ | |||
try | |||
// download checksum first | |||
var geositeSha256sum = await httpClient.GetStringAsync(geositeSha256sumUrl); | |||
geositeSha256sum = geositeSha256sum.Substring(0, 64).ToUpper(); | |||
logger.Info($"Got Sha256sum: {geositeSha256sum}"); | |||
// compare downloaded checksum with local geositeDB | |||
byte[] localDBHashBytes = mySHA256.ComputeHash(geositeDB); | |||
string localDBHash = BitConverter.ToString(localDBHashBytes).Replace("-", String.Empty); | |||
logger.Info($"Local Sha256sum: {localDBHash}"); | |||
// if already latest | |||
if (geositeSha256sum == localDBHash) | |||
{ | |||
logger.Info("Local GeoSite DB is up to date."); | |||
return; | |||
} | |||
// not latest. download new DB | |||
var downloadedBytes = await httpClient.GetByteArrayAsync(geositeUrl); | |||
// verify sha256sum | |||
byte[] downloadedDBHashBytes = mySHA256.ComputeHash(downloadedBytes); | |||
string downloadedDBHash = BitConverter.ToString(downloadedDBHashBytes).Replace("-", String.Empty); | |||
logger.Info($"Actual Sha256sum: {downloadedDBHash}"); | |||
if (geositeSha256sum != downloadedDBHash) | |||
{ | |||
File.WriteAllBytes(DATABASE_PATH, e.Result); | |||
LoadGeositeList(); | |||
logger.Info("Sha256sum Verification: FAILED. Downloaded GeoSite DB is corrupted. Aborting the update."); | |||
throw new Exception("Sha256sum mismatch"); | |||
} | |||
else | |||
{ | |||
logger.Info("Sha256sum Verification: PASSED. Applying to local GeoSite DB."); | |||
} | |||
bool pacFileChanged = MergeAndWritePACFile(group, blacklist); | |||
UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); | |||
// write to geosite file | |||
using (FileStream geositeFileStream = File.Create(DATABASE_PATH)) | |||
await geositeFileStream.WriteAsync(downloadedBytes, 0, downloadedBytes.Length); | |||
// update stuff | |||
geositeDB = downloadedBytes; | |||
LoadGeositeList(); | |||
bool pacFileChanged = MergeAndWritePACFile(group, blacklist); | |||
UpdateCompleted?.Invoke(null, new GeositeResultEventArgs(pacFileChanged)); | |||
} | |||
catch (Exception ex) | |||
{ | |||
Error?.Invoke(null, new ErrorEventArgs(ex)); | |||
} | |||
finally | |||
{ | |||
if (socketsHttpHandler != null) | |||
{ | |||
socketsHttpHandler.Dispose(); | |||
socketsHttpHandler = null; | |||
} | |||
catch (Exception ex) | |||
if (httpClient != null) | |||
{ | |||
Error?.Invoke(null, new ErrorEventArgs(ex)); | |||
httpClient.Dispose(); | |||
httpClient = null; | |||
} | |||
}; | |||
http.DownloadDataAsync(new Uri(geositeUrl)); | |||
} | |||
} | |||
public static bool MergeAndWritePACFile(string group, bool blacklist) | |||
@@ -411,11 +411,6 @@ namespace Shadowsocks.Controller | |||
return $"ss://{url}{tag}"; | |||
} | |||
public void UpdatePACFromGeosite() | |||
{ | |||
GeositeUpdater.UpdatePACFromGeosite(_config); | |||
} | |||
public void UpdateStatisticsConfiguration(bool enabled) | |||
{ | |||
if (availabilityStatistics != null) | |||
@@ -20,7 +20,6 @@ namespace Shadowsocks.Controller | |||
// see https://stackoverflow.com/questions/12945805/odd-c-sharp-path-issue | |||
private static readonly string ExecutablePath = Assembly.GetEntryAssembly().Location; | |||
// TODO: Elevate when necessary | |||
public static bool Set(bool enabled) | |||
{ | |||
RegistryKey ssURLAssociation = null; | |||
@@ -26,32 +26,17 @@ namespace Shadowsocks | |||
public static MenuViewController MenuController { get; private set; } | |||
public static string[] Args { get; private set; } | |||
[System.Runtime.InteropServices.DllImport("user32.dll")] | |||
private static extern bool SetProcessDPIAware(); | |||
/// <summary> | |||
/// 应用程序的主入口点。 | |||
/// </summary> | |||
/// </summary> | |||
[STAThread] | |||
static void Main(string[] args) | |||
{ | |||
// todo: initialize the NLog configuartion | |||
Model.NLogConfig.TouchAndApplyNLogConfig(); | |||
// .NET Framework 4.7.2 on Win7 compatibility | |||
System.Net.ServicePointManager.SecurityProtocol |= | |||
System.Net.SecurityProtocolType.Tls | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls12; | |||
// store args for further use | |||
Args = args; | |||
// Check OS since we are using dual-mode socket | |||
if (!Utils.IsWinVistaOrHigher()) | |||
{ | |||
MessageBox.Show(I18N.GetString("Unsupported operating system, use Windows Vista at least."), | |||
"Shadowsocks Error", MessageBoxButtons.OK, MessageBoxIcon.Error); | |||
return; | |||
} | |||
string pipename = $"Shadowsocks\\{Application.StartupPath.GetHashCode()}"; | |||
string addedUrl = null; | |||
@@ -125,7 +110,9 @@ namespace Shadowsocks | |||
Application.SetCompatibleTextRenderingDefault(false); | |||
AutoStartup.RegisterForRestart(true); | |||
Directory.SetCurrentDirectory(Application.StartupPath); | |||
// See https://github.com/dotnet/runtime/issues/13051 | |||
// we have to do this for self-contained executables | |||
Directory.SetCurrentDirectory(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)); | |||
#if DEBUG | |||
// truncate privoxy log file while debugging | |||
@@ -0,0 +1,18 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<!-- | |||
https://go.microsoft.com/fwlink/?LinkID=208121. | |||
--> | |||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<Configuration>Release</Configuration> | |||
<Platform>Any CPU</Platform> | |||
<PublishDir>bin\Release\netcoreapp3.1\win-x64\publish\</PublishDir> | |||
<PublishProtocol>FileSystem</PublishProtocol> | |||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||
<RuntimeIdentifier>win-x64</RuntimeIdentifier> | |||
<SelfContained>true</SelfContained> | |||
<PublishSingleFile>True</PublishSingleFile> | |||
<PublishReadyToRun>False</PublishReadyToRun> | |||
<PublishTrimmed>True</PublishTrimmed> | |||
</PropertyGroup> | |||
</Project> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<!-- | |||
https://go.microsoft.com/fwlink/?LinkID=208121. | |||
--> | |||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
</Project> |
@@ -0,0 +1,18 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<!-- | |||
https://go.microsoft.com/fwlink/?LinkID=208121. | |||
--> | |||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<Configuration>Release</Configuration> | |||
<Platform>Any CPU</Platform> | |||
<PublishDir>bin\Release\netcoreapp3.1\win-x86\publish\</PublishDir> | |||
<PublishProtocol>FileSystem</PublishProtocol> | |||
<TargetFramework>netcoreapp3.1</TargetFramework> | |||
<RuntimeIdentifier>win-x86</RuntimeIdentifier> | |||
<SelfContained>true</SelfContained> | |||
<PublishSingleFile>True</PublishSingleFile> | |||
<PublishReadyToRun>False</PublishReadyToRun> | |||
<PublishTrimmed>True</PublishTrimmed> | |||
</PropertyGroup> | |||
</Project> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<!-- | |||
https://go.microsoft.com/fwlink/?LinkID=208121. | |||
--> | |||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
</Project> |
@@ -705,9 +705,9 @@ namespace Shadowsocks.View | |||
controller.TouchPACFile(); | |||
} | |||
private void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) | |||
private async void UpdatePACFromGeositeItem_Click(object sender, EventArgs e) | |||
{ | |||
controller.UpdatePACFromGeosite(); | |||
await GeositeUpdater.UpdatePACFromGeosite(); | |||
} | |||
private void EditUserRuleFileForGeositeItem_Click(object sender, EventArgs e) | |||
@@ -71,20 +71,20 @@ | |||
<PackageReference Include="GlobalHotKeyCore" Version="1.2.0" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.5" /> | |||
<PackageReference Include="BouncyCastle.NetCore" Version="1.8.6" /> | |||
<!--TODO: Remove Fody related stuff, as they're either not actually used or has NET Core built-in alternate--> | |||
<PackageReference Include="Caseless.Fody" Version="1.9.0" /> | |||
<PackageReference Include="Costura.Fody" Version="4.1.0" /> | |||
<PackageReference Include="Fody" Version="6.1.1"> | |||
<PackageReference Include="Fody" Version="6.2.0"> | |||
<PrivateAssets>all</PrivateAssets> | |||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||
</PackageReference> | |||
<PackageReference Include="Google.Protobuf" Version="3.11.4" /> | |||
<PackageReference Include="Google.Protobuf" Version="3.12.3" /> | |||
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" /> | |||
<PackageReference Include="NaCl.Core" Version="1.2.0" /> | |||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> | |||
<PackageReference Include="NLog" Version="4.6.8" /> | |||
<PackageReference Include="NLog" Version="4.7.2" /> | |||
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" /> | |||
<PackageReference Include="ZXing.Net" Version="0.16.5" /> | |||
<PackageReference Include="StringEx.CS" Version="0.3.1"> | |||