Сначала немного истории ...
Некоторое время назад я провел несколько экспериментов с C # и API домашней автоматизации от AVM (с маршрутизатором Fritz! Box).
Это означает, что я не очень разбираюсь в C # и / или применяемых механизмах безопасности.
Доступ к API можно получить, прочитав документы XML и JSON с URL-адреса маршрутизатора.
Для этого я попытался прочитать XML-документ из Fritz! Box:
try
{
doc = XDocument.Load(uri);
}
catch (Exception e)
{
...
}
uri
содержит "https://" и IP-адрес или имя хоста (" fritz.box ") или внешний адрес myfritz.
К сожалению, сертификаты, предоставляемые маршрутизатором, являются самозаверяющими сертификатами.
Firefox любит их только после добавления исключения для этого сертификата.
Моно тоже не нравится.
Мне удалось решить эту проблему с помощью этих дополнительных строк кода:
static int Main(string[] args)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate (object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true; // ****Always accept
};
...
Поскольку единственным URL-адресом, который когда-либо будет использоваться этой программой, является внутренний IP-адрес или внешний ***. Myfritz.net URL-адрес моей коробки Fritz! Я думаю, что могу согласиться с принятием всех сертификатов.
Программа была разработана на компьютере с Windows 7 и 10 с использованием Visual Studio 2015.
После этого он был скомпилирован для Mono на Малине:
dmcs /r:System.Xml.Linq /r:System.Web.Extensions Fritz_AHA_JSON.cs
И он запускался каждые несколько минут cronjob с помощью этой командной строки:
mono Fritz_AHA_JSON.exe
Это решение работало отлично в течение нескольких лет.
Теперь маршрутизатор был заменен. Вместо Fritz! Box 7390 установлена модель Fritz! Box 7590.
Если я получаю доступ к новому маршрутизатору из Windows 10 с помощью Firefox, все нормально после добавления исключения для сертификата.
Если я получаю доступ к маршрутизатору с помощью того же кода C # из Visual Studio 15 в Windows 10, все снова работает нормально.
Если я запускаю программу C # с Mono на Raspberry Pi, сертификат отклоняется.
Fehlerbeschreibung: System.Net.WebException: Error getting response stream (Write: The authentication or decryption has failed.): SendFailure ---> System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed.
at Mono.Security.Protocol.Tls.RecordProtocol.ProcessAlert (AlertLevel alertLevel, AlertDescription alertDesc) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
at System.Net.HttpWebRequest.GetResponse () [0x00000] in <filename unknown>:0
at System.Xml.XmlUrlResolver.GetEntity (System.Uri absoluteUri, System.String role, System.Type ofObjectToReturn) [0x00000] in <filename unknown>:0
at Mono.Xml2.XmlTextReader.GetStreamFromUrl (System.String url, System.String& absoluteUriString) [0x00000] in <filename unknown>:0
at Mono.Xml2.XmlTextReader..ctor (Boolean dummy, System.Xml.XmlResolver resolver, System.String url, XmlNodeType fragType, System.Xml.XmlParserContext context) [0x00000] in <filename unknown>:0
at System.Xml.XmlTextReader..ctor (Boolean dummy, System.Xml.XmlResolver resolver, System.String url, XmlNodeType fragType, System.Xml.XmlParserContext context) [0x00000] in <filename unknown>:0
at System.Xml.XmlReader.Create (System.String inputUri, System.Xml.XmlReaderSettings settings, System.Xml.XmlParserContext inputContext) [0x00000] in <filename unknown>:0
at System.Xml.XmlReader.Create (System.String inputUri, System.Xml.XmlReaderSettings settings) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Load (System.String uri, LoadOptions options) [0x00000] in <filename unknown>:0
at System.Xml.Linq.XDocument.Load (System.String uri) [0x00000] in <filename unknown>:0
at AVM_AHA.Program.GetSessionId (System.String URL, System.String benutzername, System.String kennwort) [0x00000] in <filename unknown>:0
В поисках решения я обнаружил подсказки для установки того же самого обратного вызова проверки, что и у меня.
Другое решение, которое я нашел, было
mozroots --import --ask-remove
, который не очень хорошо работает:
Mozilla Roots Importer - версия 3.2.8.0 Загрузка и импорт надежны
корневые сертификаты от MXR Mozilla. Copyright 2002, 2003 Motus
Технологии. Copyright 2004-2008 Novell. BSD лицензируется.
Загрузка с
«http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1'...
Не удалось получить файл, используя предоставленную информацию.
Версия Mono, установленная на Raspi:
Mono JIT-компилятор версии 3.2.8 (Debian 3.2.8 + dfsg-4 + rpi1)
Проблема началась со смены роутера. Не было обновлений на Raspberry Pi.
Странно то, что мне кажется, что мой контрольный обратный вызов даже не вызывается.
Я добавил Console.Writeln()
перед возвратом true
, но ничего не вижу на консоли.
В Windows я вижу дополнительные строки.
Для меня это будет означать, что проблема возникает уже до того, как сертификат будет проверен.
Поскольку я не очень хорошо знаком с обработкой сертификатов в Mono, я не знаю, где искать решение.