Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.
Ostrzeżenie
Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.
Procesy uruchomione na tym samym komputerze można zaprojektować tak, aby komunikowały się ze sobą. Systemy operacyjne zapewniają technologie umożliwiające szybką i wydajną komunikację między procesami (IPC). Popularnymi przykładami technologii IPC są gniazda domeny Unix i potoki nazwane.
Platforma .NET zapewnia obsługę komunikacji między procesami przy użyciu biblioteki gRPC.
Wbudowana obsługa nazwanych potoków w programie ASP.NET Core wymaga platformy .NET 8 lub nowszej.
Wprowadzenie
Wywołania IPC są wysyłane z klienta do serwera. Aby komunikować się między aplikacjami na maszynie z usługą gRPC, co najmniej jedna aplikacja musi hostować serwer gRPC ASP.NET Core.
Serwer gRPC platformy ASP.NET Core jest zwykle tworzony na podstawie szablonu gRPC. Plik projektu utworzony przez szablon używa zestawu SDK Microsoft.NET.SDK.Web:
<Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.47.0" />
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
</Project>
Microsoft.NET.SDK.Web Wartość zestawu SDK automatycznie dodaje odwołanie do platformy ASP.NET Core. Referencja umożliwia aplikacji korzystanie z typów ASP.NET Core wymaganych do hostowania serwera.
Istnieje również możliwość dodania serwera do istniejących projektów non-ASP.NET Core, takich jak usługi systemu Windows, aplikacje WPF lub aplikacje WinForms. Zobacz Obsługa gRPC w projektach innych niż ASP.NET Core, aby uzyskać więcej informacji.
Transporty komunikacji między procesami (IPC)
Wywołania gRPC między klientem a serwerem na różnych maszynach są zwykle wysyłane za pośrednictwem gniazd TCP. Protokół TCP to dobry wybór do komunikacji między siecią lub Internetem. Jednak transporty IPC oferują zalety podczas komunikacji między procesami na tym samym komputerze:
- Mniejsze obciążenie i większe prędkości transferu.
- Integracja z funkcjami zabezpieczeń systemu operacyjnego.
- Nie używa portów TCP, które są ograniczonym zasobem.
Platforma .NET obsługuje wiele transportów IPC:
- Gniazda domeny systemu Unix (UDS) to powszechnie obsługiwana technologia IPC. Usługa UDS jest najlepszym wyborem do tworzenia aplikacji międzyplatformowych i można jej używać w systemach Linux, macOS i Windows 10/Windows Server 2019 lub nowszych.
- Potoki nazwane są obsługiwane przez wszystkie wersje systemu Windows. Nazwane potoki dobrze integrują się z zabezpieczeniami systemu Windows, które mogą kontrolować dostęp klienta do potoku.
- Dodatkowe transporty IPC dzięki implementacji IConnectionListenerFactory i zarejestrowaniu jej przy uruchamianiu aplikacji.
W zależności od systemu operacyjnego aplikacje międzyplatformowe mogą wybierać różne transporty IPC. Aplikacja może sprawdzić system operacyjny podczas uruchamiania i wybrać odpowiedni transport dla tej platformy:
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;
});
});
Zagadnienia dotyczące zabezpieczeń
Aplikacje IPC wysyłają i odbierają wywołania RPC. Komunikacja zewnętrzna jest potencjalnym wektorem ataku dla aplikacji IPC i musi być odpowiednio zabezpieczona.
Zabezpieczanie aplikacji serwera IPC względem nieoczekiwanych wywołań
Aplikacja serwera IPC udostępnia usługi RPC, które mogą być wywoływane przez inne aplikacje. Osoby wywołujące przychodzące powinny być uwierzytelniane, aby uniemożliwić niezaufanym klientom wykonywanie wywołań RPC do serwera.
Zabezpieczenia transportu to jedna z opcji zabezpieczania serwera. Transporty IPC, takie jak gniazda domeny systemu Unix i nazwane potoki, obsługują ograniczanie dostępu na podstawie uprawnień systemu operacyjnego:
- Potoki nazwane umożliwiają zabezpieczenie potoku za pomocą modelu kontroli dostępu systemu Windows. Prawa dostępu można skonfigurować na platformie .NET, gdy serwer jest uruchamiany przy użyciu PipeSecurity klasy .
- Gniazda domeny systemu Unix obsługują zabezpieczanie gniazda z uprawnieniami do plików.
Inną opcją zabezpieczania serwera IPC jest użycie uwierzytelniania i autoryzacji wbudowanej w ASP.NET Core. Na przykład serwer można skonfigurować tak, aby wymagał uwierzytelniania certyfikatu. Wywołania RPC wykonywane przez aplikacje klienckie bez wymaganego certyfikatu kończą się niepowodzeniem z nieautoryzowaną odpowiedzią.
Weryfikowanie serwera w aplikacji klienckiej IPC
Ważne jest, aby aplikacja kliencka weryfikowała tożsamość wywoływanego serwera. Weryfikacja jest niezbędna, aby zapobiec sytuacji, w której atakujący zatrzyma zaufany serwer, uruchomi własny i będzie przyjmować dane od klientów.
Potoki nazwane umożliwiają uzyskanie konta, pod którym działa serwer. Klient może zweryfikować, czy serwer został uruchomiony przez oczekiwane konto:
internal static bool CheckPipeConnectionOwnership(
NamedPipeClientStream pipeStream, SecurityIdentifier expectedOwner)
{
var remotePipeSecurity = pipeStream.GetAccessControl();
var remoteOwner = remotePipeSecurity.GetOwner(typeof(SecurityIdentifier));
return expectedOwner.Equals(remoteOwner);
}
Inną opcją weryfikacji serwera jest zabezpieczenie punktów końcowych za pomocą protokołu HTTPS wewnątrz ASP.NET Core. Klient może skonfigurować SocketsHttpHandler w celu zweryfikowania, czy serwer używa oczekiwanego certyfikatu podczas nawiązywania połączenia.
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.
}
}
};
Ochrona przed podwyższeniem uprawnień nazwanych potoków
Nazwane potoki obsługują funkcję o nazwie personifikacja. Przy użyciu personifikacji nazwany serwer potoków może wykonywać kod z uprawnieniami użytkownika klienta. Jest to zaawansowana funkcja, ale może umożliwić serwerowi z niskimi uprawnieniami personifikację obiektu wywołującego wysoki poziom uprawnień, a następnie uruchomić złośliwy kod.
Klient może chronić się przed tym atakiem, nie zezwalając na personifikację podczas nawiązywania połączenia z serwerem. O ile serwer nie wymaga inaczej, podczas tworzenia połączenia klienckiego należy użyć wartości TokenImpersonationLevel równej None lub Anonymous:
using var pipeClient = new NamedPipeClientStream(
serverName: ".", pipeName: "testpipe", PipeDirection.In, PipeOptions.None, TokenImpersonationLevel.None);
await pipeClient.ConnectAsync();
TokenImpersonationLevel.None jest wartością domyślną w NamedPipeClientStream konstruktorach, które nie mają parametru impersonationLevel .
Konfigurowanie klienta i serwera
Klient i serwer muszą być skonfigurowane do korzystania z transportu komunikacji między procesami (IPC). Aby uzyskać więcej informacji na temat konfigurowania Kestrel i SocketsHttpHandler do korzystania z IPC:
- Komunikacja między procesami przy użyciu gniazd domeny gRPC i Unix
- Komunikacja międzyprocesowa za pomocą gRPC i potoków nazwanych
Uwaga
Wbudowana obsługa nazwanych potoków w programie ASP.NET Core wymaga platformy .NET 8 lub nowszej.
Ostrzeżenie
Mechanizm transportu IPC, taki jak gniazda domeny Unix lub potoki nazwane, wymaga skonfigurowania SocketsHttpHandler.ConnectCallback w celu nawiązania połączenia z niestandardowym punktem końcowym. Kanał korzystający z elementu ConnectCallback nie obsługuje równoważenia obciążenia po stronie klienta ani śledzenia stanu łączności, a następujące funkcje nie są dostępne:
- Równoważenie obciążenia po stronie klienta skonfigurowane za pomocą polecenia
ServiceConfig.LoadBalancingConfigs. - Śledzenie stanu łączności za pomocą funkcji
GrpcChannel.StateiGrpcChannel.WaitForStateChangedAsync.
Próba użycia tych funkcji w kanale skonfigurowanym dla protokołu IPC zgłasza wyjątek:
System.InvalidOperationException: Channel is configured with an HTTP transport doesn't support client-side load balancing or connectivity state tracking. The underlying HTTP transport must be a SocketsHttpHandler with no SocketsHttpHandler.ConnectCallback configured. The HTTP transport must be configured on the channel using GrpcChannelOptions.HttpHandler.
Procesy uruchomione na tym samym komputerze można zaprojektować tak, aby komunikowały się ze sobą. Systemy operacyjne zapewniają technologie umożliwiające szybką i wydajną komunikację między procesami (IPC). Popularnymi przykładami technologii IPC są gniazda domeny Unix i potoki nazwane.
Platforma .NET zapewnia obsługę komunikacji między procesami przy użyciu biblioteki gRPC.
Uwaga
Wbudowana obsługa nazwanych potoków w programie ASP.NET Core wymaga platformy .NET 8 lub nowszej.
Aby uzyskać więcej informacji, zobacz platformę .NET 8 lub nowszą wersję tego tematu
Wprowadzenie
Wywołania gRPC są wysyłane z klienta do serwera. Aby komunikować się między aplikacjami na maszynie z usługą gRPC, co najmniej jedna aplikacja musi hostować serwer gRPC ASP.NET Core.
ASP.NET Core i gRPC można hostować w dowolnej aplikacji korzystającej z platformy .NET Core 3.1 lub nowszej przez dodanie do projektu składnika Microsoft.AspNetCore.App.
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Grpc.AspNetCore" Version="2.47.0" />
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
</Project>
Poprzedni plik projektu:
- Dodaje odwołanie do struktury do
Microsoft.AspNetCore.App. Dokumentacja platformy umożliwia korzystanie z aplikacji non-ASP.NET Core, takich jak usługi systemu Windows, aplikacje WPF lub aplikacje WinForms do korzystania z platformy ASP.NET Core i hostowanie serwera ASP.NET Core. - Dodaje odwołanie do pakietu NuGet do
Grpc.AspNetCore. - Dodaje plik
.proto.
Konfigurowanie gniazd domeny systemu Unix
Wywołania gRPC między klientem a serwerem na różnych maszynach są zwykle wysyłane za pośrednictwem gniazd TCP. Protokół TCP został zaprojektowany pod kątem komunikacji między siecią. Gniazda domeny systemu Unix (UDS) to powszechnie obsługiwana technologia IPC, która jest wydajniejsza niż TCP, gdy klient i serwer znajdują się na tej samej maszynie. Platforma .NET zapewnia wbudowaną obsługę usługi UDS w aplikacjach klienta i serwera.
Wymagania:
- .NET 5 lub nowszy
- Linux, macOS lub Windows 10/Windows Server 2019 lub nowszy
Konfiguracja serwera
Gniazda domeny Unix (UDS) są obsługiwane przez Kestrel, który jest skonfigurowany w Program.cs:
public static readonly string SocketPath = Path.Combine(Path.GetTempPath(), "socket.tmp");
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel(options =>
{
if (File.Exists(SocketPath))
{
File.Delete(SocketPath);
}
options.ListenUnixSocket(SocketPath, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
});
});
Powyższy przykład:
- Konfiguruje punkty końcowe Kestrel w
ConfigureKestrel. - Wywołania ListenUnixSocket do nasłuchiwania usługi UDS z określoną ścieżką.
- Tworzy punkt końcowy usługi UDS, który nie jest skonfigurowany do używania protokołu HTTPS. Aby uzyskać informacje na temat włączania protokołu HTTPS, zobacz Kestrel Konfiguracja punktu końcowego HTTPS.
Konfiguracja klientów
GrpcChannel obsługuje wykonywanie wywołań gRPC za pośrednictwem niestandardowych mechanizmów transportu. Po utworzeniu kanału można go skonfigurować z elementem SocketsHttpHandler, który ma niestandardowy element ConnectCallback. Wywołanie zwrotne umożliwia klientowi nawiązywanie połączeń za pośrednictwem transportu niestandardowego, a następnie wysyłanie żądań HTTP za pośrednictwem tego transportu.
Przykład fabryki połączeń gniazd domeny systemu Unix:
public class UnixDomainSocketConnectionFactory
{
private readonly EndPoint _endPoint;
public UnixDomainSocketConnectionFactory(EndPoint endPoint)
{
_endPoint = endPoint;
}
public async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext _,
CancellationToken cancellationToken = default)
{
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
try
{
await socket.ConnectAsync(_endPoint, cancellationToken).ConfigureAwait(false);
return new NetworkStream(socket, true);
}
catch
{
socket.Dispose();
throw;
}
}
}
Tworzenie kanału przy użyciu niestandardowej fabryki połączeń:
public static readonly string SocketPath = Path.Combine(Path.GetTempPath(), "socket.tmp");
public static GrpcChannel CreateChannel()
{
var udsEndPoint = new UnixDomainSocketEndPoint(SocketPath);
var connectionFactory = new UnixDomainSocketConnectionFactory(udsEndPoint);
var socketsHttpHandler = new SocketsHttpHandler
{
ConnectCallback = connectionFactory.ConnectAsync
};
return GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
{
HttpHandler = socketsHttpHandler
});
}
Kanały utworzone przy użyciu poprzedniego kodu wysyłają wywołania gRPC za pośrednictwem gniazd domeny systemu Unix. Obsługa innych technologii IPC może być zaimplementowana dzięki mechanizmom rozszerzeń w Kestrel i SocketsHttpHandler.