如何禁用C# HttpClient的Server Name Identification以绕过ISP拦截
禁用C# HttpClient的SNI以绕过ISP站点拦截的方法
要禁用HttpClient的SNI并模拟curl的行为(仅发送Host头、用IP作为SNI标识),可以通过自定义HttpClientHandler修改SSL连接逻辑,具体实现如下:
步骤1:自定义HttpClientHandler
创建继承自HttpClientHandler的类,重写CreateSslStreamAsync方法,清空SNI的ServerName并禁用证书验证:
public class NoSniHttpClientHandler : HttpClientHandler { protected override Task<SslStream> CreateSslStreamAsync( Stream stream, bool leaveStreamOpen, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken) { // 清空ServerName,阻止HttpClient发送域名作为SNI sslOptions.ServerName = string.Empty; // 禁用证书验证,适配IP访问时的证书域名不匹配问题 sslOptions.RemoteCertificateValidationCallback = (_, _, _, _) => true; return base.CreateSslStreamAsync(stream, leaveStreamOpen, sslOptions, cancellationToken); } }
步骤2:使用自定义Handler发起请求
直接请求目标API的IP地址,同时手动设置Host头,模拟curl的请求逻辑:
using var handler = new NoSniHttpClientHandler(); using var client = new HttpClient(handler); // 设置目标API的域名作为Host头 client.DefaultRequestHeaders.Host = "your-target-api-domain.com"; // 用API的IP地址发起请求 var response = await client.GetAsync("https://x.x.x.x/api/weather-endpoint"); var weatherData = await response.Content.ReadAsStringAsync();
关键说明
- 此方法通过清空
SslClientAuthenticationOptions.ServerName,让SNI不再携带域名信息,而是使用请求的IP地址,和curl的行为完全一致。 - 禁用证书验证是必要的:用IP访问HTTPS站点时,证书域名会和IP不匹配,若不关闭验证会触发请求失败。
- 全程在.NET进程内完成请求,避免了调用外部curl进程带来的性能损耗、可靠性问题及ASP.NET Core应用锁死风险。
内容的提问来源于stack exchange,提问作者devishdude
相关产品推荐
相关产品推荐

