引入源码方式引用 dotnetCampus.Ipc 并增强进程校验

- 用 ProjectReference 替换 NuGet 包方式引用 dotnetCampus.Ipc,并调整解决方案和项目文件
- IPC 服务实现中增加命名管道连接进程校验,确保仅允许自身或特定模块连接
- 新增 TryGetProcessById、CheckBePid、ValidateNamedPipeClientConnection 等方法用于进程和连接安全校验
- 启动流程中增加主进程 PID 合法性校验,失败时返回新错误码 MainProcessIdIncorrect(4043)
- 日志增加调试信息,便于追踪进程校验流程
- WattToolkit.slnx 新增 dotnetCampus.Ipc 项目引用路径
- 更新 dotnetCampus.Ipc 子模块提交引用
This commit is contained in:
LY
2026-08-22 00:53:04 +08:00
parent 9374231e9f
commit 8f16d3aa66
9 changed files with 126 additions and 16 deletions
+4
View File
@@ -111,6 +111,10 @@
<Project Path="ref/Common/src/BD.Common.Settings/BD.Common.Settings.csproj" />
<Project Path="ref/Common/src/BD.Common/BD.Common.csproj" />
</Folder>
<Folder Name="/2.Reference/Ipc/">
<Project Path="ref/dotnetCampus.Ipc/src/dotnetCampus.Ipc.Analyzers/dotnetCampus.Ipc.Analyzers.csproj" />
<Project Path="ref/dotnetCampus.Ipc/src/dotnetCampus.Ipc/dotnetCampus.Ipc.csproj" />
</Folder>
<Folder Name="/2.Reference/Steam/">
<Project Path="ref/ArchiSteamFarm/ArchiSteamFarm/ArchiSteamFarm.csproj" />
<Project Path="ref/Facepunch.Steamworks/Facepunch.Steamworks/Facepunch.Steamworks.Posix.csproj" />
@@ -49,7 +49,8 @@
<ItemGroup>
<!-- PackageReference -->
<ProjectReference Include="..\..\ref\Common\src\BD.Common\BD.Common.csproj" />
<PackageReference Include="dotnetCampus.Ipc" />
<ProjectReference Include="..\..\ref\dotnetCampus.Ipc\src\dotnetCampus.Ipc.Analyzers\dotnetCampus.Ipc.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\ref\dotnetCampus.Ipc\src\dotnetCampus.Ipc\dotnetCampus.Ipc.csproj" />
<PackageReference Include="NLog" />
<PackageReference Include="NLog.Extensions.Logging" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
@@ -46,16 +46,95 @@ public sealed class IPCSubProcessServiceImpl : IPCSubProcessService
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool TryGetProcessById(int pid, [NotNullWhen(true)] out Process? process)
{
try
{
process = Process.GetProcessById(pid);
return true;
}
catch
{
// 异常不记录日志
process = null;
return false;
}
}
internal static bool CheckBePid(Process proc)
{
var procPath = Environment.ProcessPath;
ArgumentNullException.ThrowIfNullOrWhiteSpace(procPath);
procPath = Path.GetFullPath(procPath);
var fn = proc.TryGetMainModule()?.FileName;
var fnPath = fn == null ? null : Path.GetFullPath(fn);
if (procPath == fnPath)
{
return true;
}
var accProPath = Path.GetFullPath(Path.Combine(procPath, "..", "modules", "Accelerator",
#if WINDOWS
"Steam++.Accelerator.exe"
#else
"Steam++.Accelerator"
#endif
));
if (procPath == accProPath)
{
return true;
}
return false;
}
internal static bool CheckBePid(int pid)
{
if (!TryGetProcessById(pid, out var proc))
{
return false;
}
return CheckBePid(proc);
}
internal static void ValidateNamedPipeClientConnection(object? s, NamedPipeClientConnectingEventArgs e)
{
#if WINDOWS
#if DEBUG
Log.Info(nameof(IPCSubProcessServiceImpl), "服务端正在校验命名管道客户端进程,{ClientProcessId}", e.ClientProcessId);
#endif
try
{
// 验证连接的客户端进程必须是自己的程序
if (!e.ClientProcessId.HasValue ||
!CheckBePid(e.ClientProcessId.Value))
{
e.AllowConnection = false;
return;
}
}
catch (Exception ex)
{
Log.Error(nameof(IPCSubProcessServiceImpl), ex, "IpcConfiguration.NamedPipeClientConnecting fail");
e.AllowConnection = false;
}
#endif
}
public async Task RunAsync(string moduleName, TaskCompletionSource tcs, string pipeName,
Action<IpcProvider>? configureIpcProvider = null)
{
this.tcs = tcs;
ipcProvider = new IpcProvider(
IPCSubProcessModuleService.Constants.GetClientPipeName(moduleName, pipeName),
new IpcConfiguration
{
IpcLoggerProvider = _ => new IpcLogger_(loggerFactory, nameof(IPCSubProcessServiceImpl)),
});
var ipcCfg = new IpcConfiguration
{
IpcLoggerProvider = _ => new IpcLogger_(loggerFactory, nameof(IPCSubProcessServiceImpl)),
};
ipcCfg.NamedPipeClientConnecting += ValidateNamedPipeClientConnection;
ipcProvider = new IpcProvider(IPCSubProcessModuleService.Constants.GetClientPipeName(moduleName, pipeName), ipcCfg);
ipcProvider.CreateIpcJoint<IPCSubProcessModuleService>(new IPCSubProcessModuleServiceImpl(this));
configureIpcProvider?.Invoke(ipcProvider);
ipcProvider.StartServer();
@@ -89,6 +89,14 @@ public interface IPCSubProcessService : IDisposable
if (!TryGetProcessById(pid, out var mainProcess))
return (int)CommandExitCode.NotFoundMainProcessId;
#if DEBUG
Log.Info(nameof(IPCSubProcessServiceImpl), "客户端正在校验服务端进程,{pid}", pid);
#endif
// 验证要连接的服务端进程是否为自己的程序
var ckPid = IPCSubProcessServiceImpl.CheckBePid(mainProcess);
if (!ckPid)
return (int)CommandExitCode.MainProcessIdIncorrect;
#if LIB_CLIENT_IPC
var nativeLibraryPath = Environment.GetEnvironmentVariable(EnvKey_NativeLibraryPath);
if (!string.IsNullOrWhiteSpace(nativeLibraryPath))
+2 -1
View File
@@ -126,7 +126,6 @@
<PackageReference Include="System.Linq.Async" />
<!--<PackageReference Include="Portable.BouncyCastle" />-->
<PackageReference Include="ReactiveUI.Fody" />
<PackageReference Include="dotnetCampus.Ipc" />
<PackageReference Include="fusillade" />
<PackageReference Include="Splat.Drawing" />
<PackageReference Include="System.Drawing.Common" />
@@ -140,6 +139,8 @@
<PackageReference Include="BD.Any.AppCenter.Analytics" />-->
<ProjectReference Include="..\..\ref\appcenter-sdk-dotnet\SDK\AppCenterAnalytics\BD.AppCenter.Analytics.Any\BD.AppCenter.Analytics.Any.csproj" />
<ProjectReference Include="..\..\ref\appcenter-sdk-dotnet\SDK\AppCenter\BD.AppCenter.Any\BD.AppCenter.Any.csproj" />
<ProjectReference Include="..\..\ref\dotnetCampus.Ipc\src\dotnetCampus.Ipc.Analyzers\dotnetCampus.Ipc.Analyzers.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\ref\dotnetCampus.Ipc\src\dotnetCampus.Ipc\dotnetCampus.Ipc.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != 'windows'">
@@ -57,5 +57,10 @@ public enum CommandExitCode
/// </summary>
GetSubProcessBootConfigurationFail = 4042,
/// <summary>
/// 主进程 Id 不正确
/// </summary>
MainProcessIdIncorrect = 4043,
#endregion
}
@@ -241,13 +241,13 @@ public sealed partial class IPCMainProcessServiceImpl : IPCMainProcessService
{
var tickCount64 = Environment.TickCount64;
var pid = Environment.ProcessId;
ipcProvider = new IpcProvider(
$"ipc_{_()}{tickCount64}{pid / 3}{pid % 3}",
new IpcConfiguration
{
AutoReconnectPeers = true, // 允许重连
IpcLoggerProvider = _ => new IpcLogger_(loggerFactory, nameof(IPCMainProcessServiceImpl)),
});
var ipcCfg = new IpcConfiguration
{
AutoReconnectPeers = true, // 允许重连
IpcLoggerProvider = _ => new IpcLogger_(loggerFactory, nameof(IPCMainProcessServiceImpl)),
};
ipcCfg.NamedPipeClientConnecting += IPCSubProcessServiceImpl.ValidateNamedPipeClientConnection;
ipcProvider = new IpcProvider($"ipc_{_()}{tickCount64}{pid / 3}{pid % 3}", ipcCfg);
ConfigureServices();
ipcProvider.StartServer();
ipcProvider.PeerConnected += IpcProvider_PeerConnected;
@@ -449,6 +449,18 @@ partial class Startup // 自定义控制台命令参数
if (ModuleName != IPlatformService.IPCRoot.moduleName)
return 402;
if (!int.TryParse(p, out var pid) || pid <= 0)
return (int)CommandExitCode.NotFoundMainProcessId;
#if DEBUG
Log.Info(nameof(IPCSubProcessServiceImpl), "客户端正在校验服务端进程,{pid}", pid);
#endif
// 验证要连接的服务端进程是否为自己的程序
var ckPid = IPCSubProcessServiceImpl.CheckBePid(pid);
if (!ckPid)
return (int)CommandExitCode.MainProcessIdIncorrect;
RunUIApplication(AppServicesLevel.IPCRoot | AppServicesLevel.Hosts);
await WaitConfiguredServices;