Giao tiếp liên tiến trình với gRPC
Các tiến trình (processes) chạy trên cùng một máy có thể được thiết kế để giao tiếp với nhau. Hệ điều hành cung cấp các công nghệ cho phép inter-process communication (IPC) (giao tiếp liên tiến trình) nhanh và hiệu quả. Các ví dụ phổ biến về công nghệ IPC là Unix domain sockets và Named pipes.
.NET cung cấp hỗ trợ cho giao tiếp liên tiến trình sử dụng gRPC.
Hỗ trợ tích hợp cho Named pipes trong ASP.NET Core yêu cầu .NET 8 trở lên.
Bắt đầu
Các lần gọi IPC được gửi từ một client đến một server. Để giao tiếp giữa các ứng dụng trên một máy với gRPC, ít nhất một ứng dụng phải host một gRPC server ASP.NET Core.
Một gRPC server ASP.NET Core thường được tạo từ template gRPC. File project được tạo bởi template sử dụng Microsoft.NET.SDK.Web làm SDK:
<Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.47.0" />
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
</Project>Giá trị SDK Microsoft.NET.SDK.Web tự động thêm tham chiếu đến ASP.NET Core framework. Tham chiếu cho phép ứng dụng sử dụng các kiểu ASP.NET Core cần thiết để host một server.
Cũng có thể thêm server vào các project không phải ASP.NET Core hiện có, chẳng hạn như Windows Services, WPF apps hoặc WinForms apps. Xem Host gRPC in non-ASP.NET Core projects để biết thêm thông tin.
IPC transports (vận chuyển IPC)
Các lần gọi gRPC giữa client và server trên các máy khác nhau thường được gửi qua TCP sockets. TCP là lựa chọn tốt để giao tiếp qua mạng hoặc Internet. Tuy nhiên, IPC transports mang lại ưu thế khi giao tiếp giữa các tiến trình trên cùng một máy:
- Ít overhead hơn và tốc độ truyền tải nhanh hơn.
- Tích hợp với các tính năng bảo mật OS.
- Không sử dụng TCP ports (cổng TCP), đây là tài nguyên hạn chế.
.NET hỗ trợ nhiều IPC transports:
- Unix domain sockets (UDS) là công nghệ IPC được hỗ trợ rộng rãi. UDS là lựa chọn tốt nhất để xây dựng các ứng dụng cross-platform (đa nền tảng) và có thể sử dụng trên Linux, macOS và Windows 10/Windows Server 2019 trở lên.
- Named pipes được hỗ trợ bởi tất cả các phiên bản Windows. Named pipes tích hợp tốt với Windows security, có thể kiểm soát quyền truy cập của client vào pipe.
- Các IPC transports bổ sung bằng cách triển khai
IConnectionListenerFactoryvà đăng ký implementation khi khởi động ứng dụng.
Tùy thuộc vào OS, các ứng dụng cross-platform có thể chọn các IPC transports khác nhau. Ứng dụng có thể kiểm tra OS khi khởi động và chọn transport mong muốn cho nền tảng đó:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
if (OperatingSystem.IsWindows())
{
serverOptions.ListenNamedPipe("MyPipeName");
}
else
{
var socketPath = Path.Combine(Path.GetTempPath(), "socket.tmp");
serverOptions.ListenUnixSocket(socketPath);
}
serverOptions.ConfigureEndpointDefaults(listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
});Cân nhắc bảo mật
Các ứng dụng IPC gửi và nhận các lời gọi RPC. Giao tiếp bên ngoài là vector tấn công tiềm năng cho các ứng dụng IPC và phải được bảo mật đúng cách.
Bảo vệ IPC server app khỏi các callers không mong muốn
IPC server app host các RPC services cho các ứng dụng khác gọi. Các callers đến nên được xác thực để ngăn các clients không tin cậy thực hiện các lời gọi RPC đến server.
Transport security (bảo mật truyền tải) là một tùy chọn để bảo mật server. Các IPC transports, chẳng hạn như Unix domain sockets và named pipes, hỗ trợ giới hạn quyền truy cập dựa trên quyền hệ điều hành:
- Named pipes hỗ trợ bảo mật pipe với Windows access control model. Access rights (quyền truy cập) có thể được cấu hình trong .NET khi server được khởi động sử dụng lớp
PipeSecurity. - Unix domain sockets hỗ trợ bảo mật socket với file permissions (quyền file).
Một tùy chọn khác để bảo mật IPC server là sử dụng authentication (xác thực) và authorization (phân quyền) được tích hợp trong ASP.NET Core. Ví dụ: server có thể được cấu hình để yêu cầu certificate authentication. Các lời gọi RPC được thực hiện bởi các ứng dụng client không có chứng chỉ cần thiết sẽ thất bại với phản hồi unauthorized.
Xác thực server trong IPC client app
Điều quan trọng là ứng dụng client xác thực danh tính của server mà nó đang gọi. Việc xác thực là cần thiết để bảo vệ chống lại kẻ tấn công độc hại dừng server đáng tin cậy, chạy server của riêng họ và chấp nhận dữ liệu đến từ clients.
Named pipes cung cấp hỗ trợ lấy account mà server đang chạy dưới đó. Client có thể xác thực rằng server được khởi chạy bởi account dự kiến:
internal static bool CheckPipeConnectionOwnership(
NamedPipeClientStream pipeStream, SecurityIdentifier expectedOwner)
{
var remotePipeSecurity = pipeStream.GetAccessControl();
var remoteOwner = remotePipeSecurity.GetOwner(typeof(SecurityIdentifier));
return expectedOwner.Equals(remoteOwner);
}Một tùy chọn khác để xác thực server là bảo mật các endpoints của nó với HTTPS bên trong ASP.NET Core. Client có thể cấu hình SocketsHttpHandler để xác thực rằng server đang sử dụng chứng chỉ dự kiến khi kết nối được thiết lập.
var socketsHttpHandler = new SocketsHttpHandler()
{
SslOptions = new SslOptions()
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
// Validate server cert thumbprint matches the expected thumbprint.
}
}
};Bảo vệ khỏi named pipe privilege escalation (leo thang đặc quyền)
Named pipes hỗ trợ một tính năng gọi là impersonation (mạo danh). Sử dụng impersonation, named pipes server có thể thực thi code với các privileges (đặc quyền) của user client. Đây là tính năng mạnh mẽ nhưng có thể cho phép một server có ít đặc quyền mạo danh một caller có nhiều đặc quyền và sau đó chạy code độc hại.
Client có thể bảo vệ khỏi cuộc tấn công này bằng cách không cho phép impersonation khi kết nối với server. Trừ khi được yêu cầu bởi server, giá trị TokenImpersonationLevel là None hoặc Anonymous nên được sử dụng khi tạo kết nối client:
using var pipeClient = new NamedPipeClientStream(
serverName: ".", pipeName: "testpipe", PipeDirection.In, PipeOptions.None, TokenImpersonationLevel.None);
await pipeClient.ConnectAsync();TokenImpersonationLevel.None là giá trị mặc định trong các constructors NamedPipeClientStream không có tham số impersonationLevel.
Cấu hình client và server
Client và server phải được cấu hình để sử dụng một IPC transport. Để biết thêm thông tin về việc cấu hình Kestrel và SocketsHttpHandler để sử dụng IPC:
- Inter-process communication với gRPC và Unix domain sockets
- Inter-process communication với gRPC và Named pipes
Hỗ trợ tích hợp cho Named pipes trong ASP.NET Core yêu cầu .NET 8 trở lên.