Как автоматически определить KnownNetworks для приложения ASP.NET Core, работающего в Kubernetes с обратным прокси-сервером в кластере? - PullRequest
0 голосов
/ 09 ноября 2018

Я использую ASP.NET Core API в Kubernetes за обратным прокси, который отправляет заголовки X-Forwarded-For, X-Forwarded-Proto и X-Forwarded-Host.

Я обнаружил, что мне нужно использовать UseForwardedHeaders(), чтобы принять значения от прокси, поэтому я написал следующий код:

var forwardedOptions = new ForwardedHeadersOptions()
{
    ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All
};
forwardedOptions.KnownNetworks.Add(new IPNetwork(IPAddress.Parse(configuration["network:address"]), int.Parse(configuration["network:cidrMask"])));
app.UseForwardedHeaders(forwardedOptions);

Я использую мой API и обратный прокси-сервер в Kubernetes, и API виден только в кластере. Из-за этого я не беспокоюсь о том, что кто-то в кластерной сети подделывает заголовки. Я хотел бы автоматически определить внутреннюю подсеть кластера и добавить ее в список KnownNetworks. Это возможно? Если да, то как?

1 Ответ

0 голосов
/ 09 ноября 2018

Я создал метод, который вычисляет начало в диапазоне и маску подсети CIDR для каждого активного интерфейса:

private static IEnumerable<IPNetwork> GetNetworks(NetworkInterfaceType type)
{

    foreach (var item in NetworkInterface.GetAllNetworkInterfaces()
        .Where(n => n.NetworkInterfaceType == type && n.OperationalStatus == OperationalStatus.Up)  // get all operational networks of a given type
        .Select(n => n.GetIPProperties())   // get the IPs
        .Where(n => n.GatewayAddresses.Any())) // where the IPs have a gateway defined
    {
        var ipInfo = item.UnicastAddresses.FirstOrDefault(i => i.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork); // get the first cluster-facing IP address
        if (ipInfo == null) { continue; }

        // convert the mask to bits
        var maskBytes = ipInfo.IPv4Mask.GetAddressBytes();
        if (!BitConverter.IsLittleEndian)
        {
            Array.Reverse(maskBytes);
        }
        var maskBits = new BitArray(maskBytes);

        // count the number of "true" bits to get the CIDR mask
        var cidrMask = maskBits.Cast<bool>().Count(b => b); 

        // convert my application's ip address to bits
        var ipBytes = ipInfo.Address.GetAddressBytes();
        if (!BitConverter.IsLittleEndian)
        {
            Array.Reverse(maskBytes);
        }
        var ipBits = new BitArray(ipBytes);

        // and the bits with the mask to get the start of the range
        var maskedBits = ipBits.And(maskBits);

        // Convert the masked IP back into an IP address
        var maskedIpBytes = new byte[4];
        maskedBits.CopyTo(maskedIpBytes, 0);
        if (!BitConverter.IsLittleEndian)
        {
            Array.Reverse(maskedIpBytes);
        }
        var rangeStartIp = new IPAddress(maskedIpBytes);

        // return the start IP and CIDR mask
        yield return new IPNetwork(rangeStartIp, cidrMask);
    }
}

Примеры:

  • 192.168.1.33 с маской 255.255.255.252 возвращает 192.168.1.32/30
  • 10.50.28.77 с маской 255.252.0.0 возвращает 10.50.0.0/14

Затем я изменил свой код опций, чтобы он выглядел так:

var forwardedOptions = new ForwardedHeadersOptions()
{
    ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All
};
foreach (var network in GetNetworks(NetworkInterfaceType.Ethernet))
{
    forwardedOptions.KnownNetworks.Add(network);
}
app.UseForwardedHeaders(forwardedOptions);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...