ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

HelloNetcode 安全连接实战:Unity Netcode for Entities 的 TLS 证书与自定义网络驱动接入

HelloNetcode 安全连接实战:Unity Netcode for Entities 的 TLS 证书与自定义网络驱动接入 HelloNetcode 安全连接实战Unity Netcode for Entities 的 TLS 证书与自定义网络驱动接入【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples本文基于 EntityComponentSystemSamples 仓库中 HelloNetcode 系列的08_SecureConnection示例文档编写。该示例演示了如何使用自定义 bootstrapper引导器为 Unity Netcode for Entities 的客户端-服务端世界client/server worlds启用 TLS 加密连接通过一个实现INetworkStreamDriverConstructor的自定义驱动构造函数把客户端 CA 证书、服务端证书与私钥注入到网络驱动中。读完本文你可以完整理解三个源文件证书参数、引导器扩展、驱动构造函数的分工与启用机制掌握 OpenSSL 生成密钥/证书后在代码中的落地方式并了解为何该特性必须通过编译宏在全局强制启用。前置条件仅依赖 BootstrapAndFrontend 示例原文档SecureConnection.md明确列出本示例的唯一前置依赖Only needs the bootstrap to set-up client and server world. * BootstrapAndFrontend也就是说只要项目中存在 HelloNetcode 基础篇的01_BootstrapAndFrontend示例所定义的自定义 Bootstrap就可以叠加本示例。该 Bootstrap 位于 FrontendBootstrap.cs其核心约定包括必须继承ClientServerBootstrap且整个项目中只能有一个继承它的类源码注释原文“The bootstrap needs to extendClientServerBootstrap, there can only be one class extending it in the project”需要打上[UnityEngine.Scripting.Preserve]特性防止 il2cpp 构建在开启裁剪时把 bootstrap 类剥离掉Initialize(string defaultWorldName)是 Entities 用来创建默认 world 的入口方法。在 FrontendBootstrap.cs 中Initialize负责根据启动方式决定创建 Local World前端菜单、按需创建 client/server world还是直接CreateDefaultClientServerWorlds()建立 client/server world 并启用 auto-connect默认端口 7979可用命令行-port 8000覆盖。安全连接示例正是建立在这套 world 创建流程之上只是替换了驱动层的默认实现。需要说明的一点NetCode 包本身的连接建立、client/server world 分离、网络连接与 Secure Connection 等详细指南以官方文档为准原文档给出了对应的手册链接Getting Started 的 Establish a connection 一节、Client Server Worlds、Network Connection、以及 Transport 包的 Secure Client and Server 与 Generate Required Keys and Certificate 小节本文只聚焦仓库内示例代码本身的实现。示例总体结构无场景、纯代码修改原文档 Sample description 部分强调了两点关键特性本示例不包含任何场景——启用安全连接不需要往场景中添加任何东西This sample contains no scene as nothing needs to be added to the scene to enable this feature必须在 bootstrap 阶段替换默认驱动——要在网络驱动上配置安全连接参数就需要一个 custom/manual driver以便向它传入不同的网络参数。而自定义驱动构造函数必须在 bootstrap 中足够早地注册早于 world 创建这样才能替换默认驱动。目录 NetcodeSamples/Assets/Samples/HelloNetcode/2_Intermediate/08_SecureConnection/ 下恰好只有三个 C# 文件分别承担三个职责文件职责NetworkParams.cs存放本示例已生成的 TLS 证书、服务端证书与私钥PEM 格式静态字符串SecureBootstrapExtension.cs继承自FrontendBootstrap的扩展类在Initialize中把安全驱动构造函数挂到NetworkStreamReceiveSystemSecureDriverConstructor.cs实现INetworkStreamDriverConstructor把证书参数传给网络驱动三个文件全部被同一个编译宏ENABLE_NETCODE_SAMPLE_SECURE包裹。每个文件的第 1 行都写着被注释掉的宏定义//#define ENABLE_NETCODE_SAMPLE_SECURE原文档解释了启用方式把ENABLE_NETCODE_SAMPLE_SECURE这一行在三个文件中同时取消注释即可。注释中还给出了重要原因——一旦启用它就全局地作用于整个项目since enabling it means its enforced globally through the whole project。这与项目中只能有一个 bootstrap的约束直接相关SecureBootStrapExtension继承自FrontendBootstrap如果它与主 bootstrap 同时生效项目中就出现了两个继承ClientServerBootstrap的类。因此该宏实际上是以本示例的 bootstrap 替换主 bootstrap的全局开关。生成安全参数NetworkParams.cs 中的证书与私钥原文档 Generating secure parameters 一节说明在NetworkParams.cs中可以看到一组静态变量里面是本示例自己生成的证书你自己的游戏需要自行生成方法参考 Transport 文档中 Generate Required Keys and Certificate 的 OpenSSL 流程。对应源码 NetworkParams.cs 中的SecureParameters静态类包含四个字段全部在#if ENABLE_NETCODE_SAMPLE_SECURE条件编译内部ServerCommonNameFixedString512Bytes值为hello_netcode_secure即用于定义服务端证书的 Common NameCN。客户端在握手时会用这个名字来校验服务端身份GameClientCAFixedString4096Bytes游戏客户端信任的 CA 证书PEM 文本-----BEGIN CERTIFICATE-----…-----END CERTIFICATE-----GameServerCertificateFixedString4096Bytes服务端证书同样 PEM 文本GameServerPrivateFixedString4096Bytes服务端 RSA 私钥-----BEGIN RSA PRIVATE KEY-----…-----END RSA PRIVATE KEY-----。从源码结构看这里选用FixedString512Bytes/FixedString4096Bytes这类Unity.Collections的定长字符串类型来承载 PEM 文本是为了在 Burst/Jobified 友好的原生内存中传递证书数据避免在驱动创建路径上额外分配托管字符串。该文件开头的 XML 注释原样重申了原文档最重要的安全告警DO NOT SHIP GENERATED PRIVATE KEYS AS PART OF YOUR GAME!原文档SecureConnection.md中的完整 NOTE 是发布游戏时不要把你的生成密钥和证书随包发布——即使代码经过混淆恶意用户也很容易反编译出密钥。仓库中还有一处呼应SecureBootstrapExtension.cs 的Initialize开头在非编辑器构建!UNITY_EDITOR下会输出SAMPLE CODE: dont ship the certificates as a part of your build的警告/错误日志其中在定义了NETCODE_DEBUG时用LogWarning否则用LogError作为运行时再提醒。实际项目中应改为服务端签发/下发证书而不是把私钥硬编码在客户端代码里。注册驱动构造函数SecureBootstrapExtension.csSecureBootstrapExtension.cs 全文如下去除条件编译与注释后的核心逻辑[UnityEngine.Scripting.Preserve] public class SecureBootStrapExtension : FrontendBootstrap { public override bool Initialize(string defaultWorldName) { // 在 world 创建之前把自定义驱动构造函数挂上去 NetworkStreamReceiveSystem.DriverConstructor new SecureDriverConstructor(); return base.Initialize(defaultWorldName); } }源码注释解释了为什么写在这里Netcode bootstrap 已经定义在 01 主连接示例中而一个项目里只能有一个 bootstrap所以这里只是在现有NetCodeBootstrap类的基础上叠加这一行normally a project would only have the boostrap defined in one place。关键调用链是Initialize被 Entities 引导流程调用见 FrontendBootstrap.cs 中的注释 The initialize method is what Entities calls to create the default worlds在base.Initialize内部真正创建 client/server world 之前先把NetworkStreamReceiveSystem.DriverConstructor静态字段替换为SecureDriverConstructor实例之后 world 创建路径读取该构造函数时拿到的就是带 TLS 参数的驱动注册逻辑。NetworkStreamReceiveSystem.DriverConstructor是一个可全局替换的静态挂载点。仓库中其他示例也依赖同一机制来切换驱动实现例如RelayDriverConstructor.csRelay 支持示例HostMigrationHelper.cs 中MigrateDataToNewServerWorld会先保存旧构造函数、临时替换、再恢复var oldConstructor NetworkStreamReceiveSystem.DriverConstructor;…说明该字段是当前生效驱动构造函数的单一入口。这可以推断出一个实用技巧DriverConstructor支持运行时临时替换与还原但安全连接示例选择的是bootstrap 阶段一次性全局替换这种最简方式。传递安全参数SecureDriverConstructor.cs原文档 Passing secure parameters 一节说生成的证书在SecureDriverConstructor.cs中被传入网络驱动这里使用了一个 helper function 来为网络设置填充默认值你也可以改为手动构造网络驱动实例或通过相应的 override 传入自己的网络设置。对应源码 SecureDriverConstructor.cs/// summary /// Register client and server using TLS configuration. /// The configuration is retrieved from see crefSecureParameters/. /// /summary public struct SecureDriverConstructor : INetworkStreamDriverConstructor { public void CreateClientDriver(World world, ref NetworkDriverStore driverStore, NetDebug netDebug) { DefaultDriverBuilder.RegisterClientDriver( world, ref driverStore, netDebug, caCertificate: ref SecureParameters.GameClientCA, serverName: ref SecureParameters.ServerCommonName); } public void CreateServerDriver(World world, ref NetworkDriverStore driverStore, NetDebug netDebug) { DefaultDriverBuilder.RegisterServerDriver( world, ref driverStore, netDebug, certificate: ref SecureParameters.GameServerCertificate, privateKey: ref SecureParameters.GameServerPrivate); } }要点INetworkStreamDriverConstructor接口有两个必须实现的方法CreateClientDriver与CreateServerDriver分别负责为指定World注册客户端/服务端网络驱动客户端侧通过DefaultDriverBuilder.RegisterClientDriver的可选参数caCertificateCA 证书与serverName即ServerCommonName用于证书 CN 校验启用 TLS 客户端驱动服务端侧通过DefaultDriverBuilder.RegisterServerDriver的可选参数certificate服务端证书与privateKey私钥启用 TLS 服务端驱动DefaultDriverBuilder正是原文档所说的 helper function to set up default values on the network settings它在内部按平台/运行模式组装默认的NetworkSettings并注册对应传输IPC/UDP/WebSocket 等。对比仓库中不启用 TLS 的自定义构造函数实现可以更清楚地看出安全连接示例的增量所在CustomHandlers.cs 中的CustomDriverConstructor手动GetNetworkSettings()后按平台分派到RegisterClientIpcDriver/RegisterClientUdpDriver/RegisterClientWebSocketDriver服务端同理RelayDriverConstructor.cs 则按 IPC编辑器本地与 UDP/WebSocketRelay 路径组合注册ConnectionMonitorSystem.cs 的DriverConstructor演示了根据模拟器管线需求选择CreateClientSimulatorPipelines/CreateClientPipelines/CreateServerPipelines。而SecureDriverConstructor选择直接调用RegisterClientDriver/RegisterServerDriver这两个高层入口只在参数上追加证书信息是最简的 TLS 接入写法。若你需要自定义 MTU、传输类型、QoS 等更多网络参数原文档给出的方向是manually construct the network driver instance, or pass in your own network settings using the appropriate override即参考上述示例中GetNetworkSettings() 分平台Register*Driver的做法把证书参数与自定义设置合并。启用步骤与注意事项汇总结合原文档与源码完整启用流程与约束如下确认前置项目使用01_BootstrapAndFrontend示例的FrontendBootstrap或其等价自定义 bootstrap。本示例不新增场景不需要任何编辑器操作生成你自己的证书按 Transport 文档用 OpenSSL 生成 CA、服务端证书与私钥本仓库示例已内置一份生成好的仅用于演示填入参数把 PEM 文本与 CN 写入NetworkParams.cs的SecureParameters四个字段客户端 CA、服务端证书、服务端私钥、ServerCommonName开启编译宏在NetworkParams.cs、SecureBootstrapExtension.cs、SecureDriverConstructor.cs三个文件中把首行//#define ENABLE_NETCODE_SAMPLE_SECURE取消注释。三个文件必须同时开启否则SecureDriverConstructor或SecureParameters会因条件编译被整体裁掉理解全局性该宏是项目级全局生效的SecureBootStrapExtension会作为继承自FrontendBootstrap的第二个 bootstrap 存在——这正是仓库用条件编译而非直接生效的原因发布安全绝不要把生成好的私钥/证书随构建发布防止反编译泄露源码注释与运行时日志均强调此点。适用前提说明本示例基于仓库中当前版本的 Netcode for Entities APIINetworkStreamDriverConstructor、NetworkStreamReceiveSystem.DriverConstructor、DefaultDriverBuilder接口签名以仓库内 SecureDriverConstructor.cs 为准不同版本的 Netcode/Transport 包中这些入口可能有变动迁移时应以所用包版本的手册为准。【免费下载链接】EntityComponentSystemSamples项目地址: https://gitcode.com/GitHub_Trending/en/EntityComponentSystemSamples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表