如何查看传入 API 请求的 TLS 版本 - ASP.NET

How can I see the TLS version of an incoming API request - ASP.NET

提问人:IMSsam 提问时间:11/15/2023 更新时间:11/16/2023 访问量:90

问:

我在 Microsoft Azure 上托管了一个包含 Web API 的 Web 应用。我的目标是 .NET Framework 4.5。

我正在完成所有必需的步骤,以使TLS 1.2成为传入请求所需的最低版本。

在我正式切换到传入请求的 TLS 1.2 最低版本之前,我想知道是否有人当前正在使用较旧的 TLS 版本,因为我们有第三方使用我们的 API。

有没有办法检测在特定 API 请求中协商的 TLS 版本?

例如,我在下面有这个 API 调用。我可以使用 .NET Framework 4.5 编写哪些代码来获取协商的 TLS 版本?

        [HttpGet]
        [Authorize(Roles = "User")]
        public HttpResponseMessage GetFirstName()
        {
            // I would like to add code here to get TLS version negotiated so I can log it

            var email = User.Identity.GetUserName();
            ApplicationUser userFound = GetUserByEmail(email);
            if (userFound == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Error: No such user.");
            }
            var firstName = new { FirstName = userFound.FirstName };

            return Request.CreateResponse(HttpStatusCode.OK, firstName);
        }

我知道我最终需要完全升级 .NET Framework,但我需要在 4.5 上快速解决该问题。

asp.net Azure net-4.5 TLS1.2 WebAPI

评论

0赞 Panagiotis Kanavos 11/15/2023
快速解决方案是升级到受支持的版本,即 4.6.2 及更高版本。4.5 从一开始就不支持 TLS 1.2,没有黑客攻击,所以你看不到发生了什么。你自己的应用程序最多协商 TLS 1.1 的使用。唯一使用 TLS 1.1 的客户端是未修补、不受支持的 Windows 版本。所有其他人都已经支持它了。鉴于 Chrome 和 GMail 等主要浏览器和服务多年来一直需要 TLS 1.2,因此所有客户端在几年前都进行了升级
0赞 Panagiotis Kanavos 11/15/2023
例如,Chrome 早在 2020 年就弃用了 TLS 1.1
0赞 IMSsam 11/16/2023
@PanagiotisKanavos我在 Global.asax 的 Application_Start() 中设置 ServicePointManager.SecurityProtocol = TLS 1.2.cs以便能够使用 TLS 1.2 发出请求。我有第三方使用遗留系统连接到我们的 API,因此我需要能够识别它们并提醒他们传入请求需要即将对 TLS 1.2 进行更改。因此,我希望有一种方法可以至少使用 .NET Framework 4.5 识别传入请求的 TLS 版本,因为目前我支持传入请求的任何 TLS 版本
0赞 Panagiotis Kanavos 11/17/2023
如果使用 TLS 1.2,则已要求使用 TLS 1.2,从而阻止使用 TLS 1.1 或 TLS 1.3 的连接。这意味着所有客户端都已使用 TLS 1.2System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
0赞 Panagiotis Kanavos 11/17/2023
无论如何,真正的解决方案是升级到 4.6.2 并删除所有硬编码的 TLS 版本。这将允许 .NET 使用操作系统提供的最佳选项。在所有受支持的 Windows 版本中,TLS 1.2 都是 TLS 1.2,而在 Windows 11 和 Windows Server 2022 中,你也会获得 TLS 1.3

答:

0赞 Suresh Chikkam 11/15/2023 #1

当然,Panagiotis Kanavos 的观点是有效的。升级到受支持的 .NET Framework 版本(如 4.6.2 或更高版本)可能会有更多帮助。

正如您可以在 MS 文档中查看的那样,如果您使用的是 4.5v,则需要升级到最新版本。enter image description here

我已经尝试了较新版本的 .NET Framework 4.6.1。我可以直接从类中访问 TLS 版本信息。SslStream

using System;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;

namespace YourNamespace.Controllers
{
    public class YourController : ApiController
    {
        [HttpGet]
        public async Task<HttpResponseMessage> Get()
        {
            await LogNegotiatedTLSVersion(Request);

            // Your existing code here

            return new HttpResponseMessage()
            {
                Content = new ObjectContent<string>("Hello, World!", new JsonMediaTypeFormatter()),
            };
        }

        private async Task LogNegotiatedTLSVersion(HttpRequestMessage request)
        {
            object property;
            if (request.Properties.TryGetValue("MS_HttpContext", out property))
            {
                var context = (System.Web.HttpContextWrapper)property;
                var stream = context.Response.Filter as System.Web.HttpBufferedOutputStream;

                if (stream != null)
                {
                    var sslStreamField = stream.GetType().GetField("_sslStream", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                    var sslStream = sslStreamField?.GetValue(stream) as System.Net.Security.SslStream;

                    if (sslStream != null)
                    {
                        // Log the negotiated TLS version
                        Console.WriteLine($"Negotiated TLS version: {sslStream.SslProtocol}");
                    }
                }
            }
        }
    }
}
  • 该属性用于获取协商的 TLS 版本。调用该方法对连接的服务器端进行身份验证。SslStream.SslProtocolAuthenticateAsServer

评论

0赞 IMSsam 11/16/2023
我尝试了您的解决方案,但我被卡住了,因为我的 Request 对象是 HttpRequestMessage,而不是 HttpRequest。您知道利用 HttpRequestMessage 获得相同结果的方法吗?
0赞 Suresh Chikkam 11/16/2023
@IMSsam 您仍然可以提取 TLS 信息,但需要使用 HttpRequestMessage.Properties 字典来访问基础 SslStream 并检索 TLS 版本。请查看我更新的答案。