Nguon: Microsoft Learn · .NET 8.0

Giao tiếp liên tiến trình với gRPC

Nguồn: Inter-process communication with 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:

xml
<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:

.NET hỗ trợ nhiều IPC transports:

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 đó:

csharp
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:

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:

cs
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.

cs
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ị TokenImpersonationLevelNone hoặc Anonymous nên được sử dụng khi tạo kết nối client:

cs
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:

Hỗ trợ tích hợp cho Named pipes trong ASP.NET Core yêu cầu .NET 8 trở lên.