using System; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Runtime.ConstrainedExecution; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using DnsClient; ////////////////////////////////// #region __________ INIT __________ using Microsoft.Extensions.Logging.Console; var builder = WebApplication.CreateBuilder(args); //控制台日志格式 builder.Services.AddLogging(opt => { opt.AddSimpleConsole(p => { p.TimestampFormat = "[dd HH:mm:ss] "; p.SingleLine = true; p.ColorBehavior = LoggerColorBehavior.Enabled; }); }); using var host = builder.Build(); builder.WebHost.UseUrls("http://*:0"); await host.StartAsync(); var isRunning = true; var cts = new CancellationTokenSource(); Console.CancelKeyPress += (_, _) => { isRunning = false; cts.Cancel(false); }; var logger = host.Services.GetRequiredService>(); logger.LogInformation("Hello, World!"); //Main try { await RealMain(); } catch (Exception ex) { logger.LogError(ex, "Main"); } finally { logger.LogInformation("Bye!"); await host.StopAsync(); Console.WriteLine(); Console.Write("Press ENTER to exit..."); Console.ReadLine(); } #endregion __________ INIT __________ ////////////////////////////////// async Task RealMain() { const string url = "http://www.example.org/index.html"; const string host = "www.example.org"; const string path = "/index.html"; const string dnsServerName = "reliable-dns-server-in-hosts"; var dnsServerIp = Dns.GetHostEntry(dnsServerName).AddressList.FirstOrDefault(); var lookup = new LookupClient(dnsServerIp); var result = await lookup.QueryAsync(host, QueryType.A); var record = result.Answers.ARecords().FirstOrDefault(); var ip = record?.Address; var tcpClient = new TcpClient(); tcpClient.Connect(new IPEndPoint(ip, 443)); // stuck if was ip gfw-ed var ssl = new SslStream(tcpClient.GetStream()); var sslOptions = new SslClientAuthenticationOptions { TargetHost = string.Empty, // Leave this empty to avoid sending SNI RemoteCertificateValidationCallback = (_, certificate, chain, errs) => { if (errs == SslPolicyErrors.None) return true; if (errs != SslPolicyErrors.RemoteCertificateNameMismatch) return false; if (certificate is not X509Certificate2 cert2) return false; // 比较证书名称和主机名称 var certName = cert2.GetNameInfo(X509NameType.DnsName, false); if (certName.StartsWith("*.")) { if (!host.EndsWith(certName[2..], StringComparison.OrdinalIgnoreCase)) return false; } else if (!certName.Equals(host, StringComparison.OrdinalIgnoreCase)) return false; // 验证证书的有效期 if (DateTime.Now < cert2.NotBefore || DateTime.Now > cert2.NotAfter) return false; // 构建证书链 if (chain == null) return false; chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; //检测吊销耗时太长,忽略 chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 10); chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; var isValidChain = chain.Build(cert2); if (isValidChain) return true; foreach (X509ChainStatus chainStatus in chain.ChainStatus) { // 仅处理会影响安全性的错误状态 if (chainStatus.Status == X509ChainStatusFlags.RevocationStatusUnknown || chainStatus.Status == X509ChainStatusFlags.OfflineRevocation || chainStatus.Status == X509ChainStatusFlags.NoError) { continue; } // 其他任何错误状态都认为证书无效 return false; } return true; } }; await ssl.AuthenticateAsClientAsync(sslOptions, cts.Token); ssl.Write(Encoding.ASCII.GetBytes($"GET {path} HTTP/1.1\r\n")); ssl.Write(Encoding.ASCII.GetBytes($"Host: {host}\r\n")); ssl.Write(Encoding.ASCII.GetBytes($"\r\n")); var reader = new StreamReader(ssl); var lines = new List(); // <- 200 OK , PoC SUCC! do { var line = reader.ReadLine(); if (line == "") break; lines.Add(line); } while (true); int bp = 0; }