С помощью С# я могу сделать SSL-соединение с помощью Server Name Indicication (SNI)?
В настоящее время у меня есть этот код, который делает SSL-соединение с сервером:
using (client = new TcpClient())
{
client.Connect(Hostname, Port);
var callback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
using (stream = new SslStream(client.GetStream(), false, callback))
{
stream.AuthenticateAsClient(Hostname);
}
}
Однако я не думаю, что он поддерживает SNI, потому что неправильный сертификат возвращается с сервера, настроенного SNI. Есть ли способ сделать SSL-соединение с использованием SNI?
Я использую .NET 2 (желаю обновить, если необходимо). Я использую Windows 7, но хотел бы, чтобы программное обеспечение работало на других платформах, таких как Windows 2008, если это возможно.
Ответы
Ответ 1
Итак, в заключение кажется, что ответ: Нет, вы не можете использовать SNMP-соединение для использования SNI: - (
Я не смог найти код примера С#, создающий TLS-соединение с SNI. Теоретически, однако, должно быть возможно создать это вручную, т.е. Согласно Как реализовать идентификацию имени сервера (SNI)
однако попытка здесь потерпела неудачу: TLS SNI с С#
Ответ 2
Ответ кажется "да", так как существует реализация С#, которая поддерживает SNI. В этом отчете об ошибке упоминается версия mono, которая поддерживает HTTPS-запросы с SNI.
Ответ 3
Мы столкнулись с подобной проблемой, пытаясь подключиться к бизнес-API, используя общий SSL. Стандартные библиотеки .NET не работают. Вы можете использовать стороннюю библиотеку http://curl.haxx.se/libcurl/ как одно из возможных решений.
libcurl - бесплатная и простая в использовании клиентская библиотека для передачи URL-адресов, поддерживающая DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet и TFTP. libcurl поддерживает SSL-сертификаты, HTTP POST, HTTP PUT, FTP-загрузку, загрузку на основе HTTP-форм, прокси-серверы, файлы cookie, аутентификацию пользователя и пароля (Basic, Digest, NTLM, Negotiate, Kerberos), возобновление передачи файлов, туннелирование HTTP-прокси и многое другое.
Библиотека .NET может быть загружена из http://sourceforge.net/projects/libcurl-net/
Когда вы загружаете его, замените libcurl.dll на самую последнюю версию (она должна быть 7.18.1 или новее). В текущем пакете libcurl-nel он старше, чем необходимо.
public string HTTPGet(string URL, string Proxy, string certName = null, string certPassword = null)
{
Easy easy = new Easy();
SockBuff = "";
try
{
Easy.WriteFunction wf = new Easy.WriteFunction(OnWriteData);
easy.SetOpt(CURLoption.CURLOPT_URL, URL);
easy.SetOpt(CURLoption.CURLOPT_TIMEOUT, "60");
easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, wf);
easy.SetOpt(CURLoption.CURLOPT_USERAGENT, UserAgent);
easy.SetOpt(CURLoption.CURLOPT_COOKIEFILE, CookieFile);
easy.SetOpt(CURLoption.CURLOPT_COOKIEJAR, CookieFile);
easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, true);
if (!string.IsNullOrEmpty(certName))
{
easy.SetOpt(CURLoption.CURLOPT_SSLCERT, certName);
if (!string.IsNullOrEmpty(certPassword))
{
easy.SetOpt(CURLoption.CURLOPT_SSLCERTPASSWD, certPassword);
}
}
if (URL.Contains("https"))
{
easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYHOST, 1);
easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, 0);
}
if (!string.IsNullOrEmpty(Proxy))
{
easy.SetOpt(CURLoption.CURLOPT_PROXY, Proxy);
easy.SetOpt(CURLoption.CURLOPT_PROXYTYPE, CURLproxyType.CURLPROXY_HTTP);
}
var code = easy.Perform();
easy.Cleanup();
Console.WriteLine(code);
}
catch
{
Console.WriteLine("Get Request Error");
}
return SockBuff;
}
public static Int32 OnWriteData(Byte[] buf, Int32 size, Int32 nmemb, Object extraData)
{
// Console.Write(System.Text.Encoding.UTF8.GetString(buf));
SockBuff = SockBuff + System.Text.Encoding.UTF8.GetString(buf);
return size * nmemb;
}
Ответ 4
Я знаю, что это более старая должность, но мне недавно нужно было то же самое. У меня есть приложение на С#, которое я использовал для динамического создания сайтов на С#. Мне нужно, чтобы привязки сайтов устанавливали флаг "имя сервера" при создании, потому что мы пытаемся использовать несколько сайтов SSL на одном и том же IP-адресе.
Как оказалось, теперь вы можете сделать это на С#. Вы можете передать флаг, который включит опцию SNI. Надеюсь, это поможет любому, у кого есть эта проблема. Вот пример:
// Create site using server manager
ServerManager sm = new ServerManager();
Site mySite = sm.Sites.Add("example.com", "C:\Test Website\", 443);
// Creating binding object to store SSL cert
var ibind = mySite.Bindings.CreateElement();
ibind.Protocol = "https";
ibind.BindingInformation = "*:443:" + domain;
ibind.CertificateHash = certificate.GetCertHash();
// This option will turn on SNI (server name indication)
ibind.SetAttributeValue("sslFlags", 1);
// Add the binding to the site
mySite.Bindings.Add(ibind);