FreeTDS ne parvient pas à se connecter à SQL Server après des correctifs Windows récents et TLS1 étant désactivé

J'ai un problème bizarre avec FreeTDS (MacOS 10.11.5) ne pas se connecter à SQL Server 2014 fonctionnant sous Windows Server 2012 r2 auquel j'avais pu me connecter auparavant (il y a environ une semaine environ). Le server de la dernière semaine a été durci par la security (les correctifs r2 2012 les plus récents, plus d'autres choses * que je suppose être le coupable, mais ma machine de développement locale (et seulement FreeTDS sur ma machine) semble être le Seul problème après les patchs.

Je soupçonne que ce qui cause le problème se trouve quelque part dans les chiffrements RC4 et SSL 2.0 et TLS 1.0 étant désactivés, mais je ne sais pas comment corriger cela.

Pour être clair, contrairement à d'autres questions similaires – je ne peux pas connecter freetds à DB01, mais je peux connecter d'autres pilotes à DB01 (mais je développe une application python et besoin de freetds dans cette instance) et d'autres machines peuvent se connecter à DB01 .

L'erreur de base est:

$ tsql -S DB01 -U db_user Password: **************** locale is "en_US.UTF-8" locale charset is "UTF-8" using default charset "UTF-8" Error 20002 (severity 9): Adaptive Server connection failed There was a problem connecting to the server 

Pas super utile – J'ai fait le dépannage normal, y compris essayer différentes versions de TDS, utiliser différents commutateurs sur la command line, etc.

Le journal indique également la possibilité d'un problème SSL – par exemple, tls.c logging "handshake failed" , le package contenant la string "SSL_Self_Signed_Fallback" (sinon les packages sont illisibles):

 net.c:216:Connecting to 000.000.000.000 port 1433 (TDS version 7.4) net.c:242:tds_open_socket: connect(2) returned "Operation now in progress" net.c:343:tds_open_socket() succeeded packet.c:741:Sending packet [blah blah] login.c:1185:detected flag 0 tls.c:116:in tds_push_func_login tls.c:86:in tds_pull_func_login packet.c:741:Sending packet [blah blah] packet.c:639:Received packet [blah blah... what? xxx |..0.SSL_.Se| xxx |lf_.S. igne| xxx |d._.Fa llba| xxx |c.k0...1 blahblah| tls.c:116:in tds_push_func_login packet.c:741:Sending packet 0000 12 01 00 0f 00 00 00 00-15 03 00 00 02 02 28 |........ ......(| tls.c:923:handshake failed login.c:530:login packet rejected query.c:3796:tds_disconnect() util.c:165:Changed query state from IDLE to DEAD util.c:322:tdserror(0x7fef2b403aa0, 0x7fef2b403ba0, 20002, 0) util.c:352:tdserror: client library returned TDS_INT_CANCEL(2) util.c:375:tdserror: returning TDS_INT_CANCEL(2) mem.c:644:tds_free_all_results() 

Quand je me connecte à d'autres servers et regarde freetds.log je peux lire les packages (sorte de), par exemple:

 xxx |.Chan .ged | xxx |.data .base| xxx |. .con .text| xxx |. .to .'.mas| xxx |.ter' 

contrairement à DB01 où les packages sont des lignes et des lignes de }.???G?? .?T???٠ }.???G?? .?T???٠

Voici les parameters de compilation de freetds – ai-je besoin de GnuTLS = yes ?:

 $ tsql -C Comstack-time settings (established with the "configure" script) Version: freetds v1.00.9 freetds.conf directory: /usr/local/Cellar/freetds/1.00.9/etc MS db-lib source compatibility: no Sybase binary compatibility: no Thread safety: yes iconv library: yes TDS version: 7.3 iODBC: no unixodbc: yes SSPI "trusted" logins: no Kerberos: no OpenSSL: yes GnuTLS: no MARS: no 

voici mon file freetds.conf:

 [global] # TDS protocol version tds version = auto dump file = /tmp/freetds.log debug flags = 4FFF text size = 64512 [DB01] host = db01.mydomain.tld port = 1433 tds version = 7.4 database = DB_NAME # I added this in case it was a cert issue, see below check certificatee hostname = no 

Quelques autres points de données de dépannage rapide:

  • En utilisant TCPVew sur le server, je peux voir que mes connections sont acceptées (mais le journal le confirme également)

  • Nous avons un server Windows qui sert des pages PHP (connection à DB01 via ODBC) et nous n'avons eu aucun problème avec ce server se connectant à DB01

  • Je peux utiliser jTDS (via IntelliJ et Pycharm) pour se connecter à l'amende db01, cela aurait été la fin de l'enquête si je pouvais connecter jTDS dans une application django.

  • Le pilote JDBC de Microsoft ne se connectera pas à db01 (c'est aussi nouveau), ce pilote donne cette erreur:

     [08S01] The driver could not establish a secure connection to SQL Server 

    en utilisant le chiffrement SSL (Secure Sockets Layer). Erreur: "Le server a choisi SSLv3, mais cette version de protocole n'est pas activée ou n'est pas supscope par le client." … java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: Le server a choisi SSLv3, mais cette version du protocole n'est pas activée ou n'est pas supscope par le client.

Quelqu'un d'autre a-t-il vu cela? Existe-t-il un moyen de spécifier TLS 1.2, etc. lors de la connection avec freetds? (Je n'ai pas pu find de document à ce sujet)

METTRE À JOUR:

J'ai pensé à regarder dans l'observateur d'events Windows pour toutes les erreurs, et voici ce qu'il y a dedans:

  DB01 17836 Error MSSQLSERVER Application 7/20/2016 2:52:18 PM The login packet used to open the connection is structurally invalid; the connection has been closed. Please contact the vendor of the client library. [CLIENT: [my ip address]] [and also] Length specified in network packet payload did not match number of bytes read; the connection has been closed. Please contact the vendor of the client library. [CLIENT: [my ip address]] 

Nous avons eu cette erreur par intermittence après l'application de correctifs Linux et MS. Nous pourrions toujours nous connecter de Linux au server MSSQL mais notre connection se terminerait randomment avec l'erreur EOF … même au milieu d'une requête. J'ai allumé le journal de freetds et j'ai vu un échec de poignée de main de encryption comme ceci:

  net.c:1366:handshake failed: A TLS packet with unexpected length was received. login.c:466:login packet rejected util.c:331:tdserror(0x1e752b0, 0x2c27f40, 20002, 0) 

Après beaucoup de dépannage, nous avons annulé KB3172605 sur le server MS Windows Server 2008 R2 qui exécute notre database MS SQL Server … il a résolu le problème. (KB 3172605 remplace KB 3161639.)

TLDR; J'avais besoin de ré-installer freetds avec le support de gnutls au lieu de openssl.

Après beaucoup (pas, vraiment beaucoup) d'essais et d'erreurs j'ai finalement trouvé une solution à freetds sur le mac ne se connectant pas.

J'ai encore besoin de câbler le rest pour que pyodbc fonctionne, etc. mais voici la solution de base:

brew edit freetds

Remplacer la formule freetds avec ce https://gist.github.com/hanleybrand/dfb7b9004aae250fabd01cd2466251c4

En bref, il ajoute l'option --with-gnutls à l'installation de armsage et s'assure que si elle existe elle se produit avant --with-openssl . Je ne l'ai pas examiné beaucoup, mais je soupçonne que openssl / gnutls est soit / ou et et non et / ou.

brew rm freetds && brew install freetds --with-gnutls --with-unixodbc

Après cela, tsql a bien fonctionné – comme je l'ai mentionné plus haut, je dois encore configurer le rest (unixodbc, pyodbc), mais je suis assez confiant que si tsql fonctionne, le rest le sera également, bien que je ne sois pas entièrement sûr.

Cela peut être lié à des sets de chiffrement dans les deux packages (openssl agains gnutls) comme le souligne @FlipperPA

J'ai fait beaucoup de tests avec ceci, et notre solution était de restaurer ce patch:

https://support.microsoft.com/en-us/kb/3161639

Apparemment, la suite de chiffrement affecte plus que Edge et IE. 🙂 J'ai ouvert une affaire avec Microsoft et ils sont conscients des problèmes que cela a causés. De la bouche du cheval:

Étant donné que le problème ne se produit plus après la désinstallation de cette mise à jour de la base de connaissances, j'ai effectué une search rapide sur cette mise à jour pour les cas antérieurs. À ce jour, il y a eu 21 cas de problèmes avec cette mise à jour depuis le mois dernier. Si vous n'êtes pas au courant de mes searchs, KB 3161639 ajoute des keys de chiffrement supplémentaires qui utilisent le protocole TLS 1.2 introduit dans la mise à jour KB 3161608. Les chiffrements suivants sont probablement ceux qui provoquent le problème:

TLS_DHE_RSA_WITH_AES_128_CBC_SHA

TLS_DHE_RSA_WITH_AES_256_CBC_SHA

Je soupçonne que votre server Unix / Linux et / ou FreeTDS ODBC ne supporte pas ces suites de chiffrement ou n'est pas configuré pour cela.
Cela dit, vous avez quelques options:

  1. Utilisez la solution de contournement de ne pas avoir la mise à jour KB 3161639 installée
  2. Réinstallez la mise à jour KB 3161639. Configurer votre ordre de chiffrement pour vous assurer que les nouvelles suites de chiffrement ne sont pas choisies.

Nous sums allés avec l'option 1, et nous l'avons déployée sur notre réseau, et nous n'avons constaté aucun effet néfaste. J'espère que ça aide.

Je voyais le même comportement sous FreeTDS (version 0.91) après les récents correctifs de Microsoft.

En résumé, la mise à jour de FreeTDS sur l'instantané nocturne disponible sur http://www.freetds.org/ ( 1.00.24 partir de ce post) a résolu le problème pour moi. J'ai compilé la source et mis à jour la ligne de pilote FreeTDS dans le file de configuration odbcinst.ini pour pointer vers le nouveau file object partagé ( <path>/libtdsodbc.so ), par exemple:

 [TDS] Description = FreeTDS Driver Driver = /usr/local/lib/libtdsodbc.so 

Au début de septembre 2016, il y a eu des validations liées à OpenSSL sur FreeTDS, y compris cette validation , qui fait reference à une incompatibilité de correctif Microsoft:

Mettre à jour la list de chiffrement OpenSSL

Cela augmente la security et corrige également une incompatibilité récente entre OpenSSL et SChannel (les versions de SChannel ont été corrigées dans quelques mois).

Basé sur d'autres commentaires ici qui pointent vers un problème de compatibilité de la suite de chiffrement, cela peut avoir été le commit qui a arrangé les choses. Cependant, à partir de ce post, il n'y a pas encore eu de version officielle de FreeTDS incluant ce commit (la dernière version officielle était la version 1.0 en mai 2016).

Références aux correctifs Microsoft mentionnés dans d'autres commentaires:

  • KB3161639 à partir de juin 2016 correctifs cumulatifs.

    Cet article décrit une mise à jour dans laquelle les nouvelles suites de chiffrement TLS sont ajoutées et les priorités par défaut de la suite de chiffrement sont modifiées dans Windows RT 8.1, Windows 8.1, Windows Server 2012 R2, Windows 7 ou Windows Server 2008 R2. Ces nouvelles suites de chiffrement améliorent la compatibilité avec les servers qui prennent en charge un set limité de suites de chiffrement.

  • KB3172605 à partir de juillet 2016 patchs rollups (et re-publié en septembre 2016). Description de ce correctif de l'article de l' historique des mises à jour de Windows Server 2008 R2 SP1 :

    21 juillet 2016 – KB3172605 Cette mise à jour inclut des améliorations de la qualité. Aucune nouvelle fonctionnalité du operating system n'est introduite et aucune nouvelle mise à jour de security n'est incluse. Les principaux changements include:

    • Prise en charge améliorée dans l'interface de programmation d'applications cryptocharts Microsoft (CryptoAPI) pour aider à identifier les sites Web qui utilisent l'algorithm de hachage sécurisé 1 (SHA-1).
    • Problème résolu dans Microsoft Secure Channel (SChannel) qui provoque parfois l'échec des connections TLS (Transport Layer Security) 1.2 selon que le certificate racine est configuré comme faisant partie de la string de certificates pour l'authentification du server.

Après des essais et des erreurs, j'ai eu l'expérience contraire de Peter Hanley qui est documentée dans l'un des messages ci-dessus, bien que, comme Peter le fait remarquer, l'erreur est un peu différente. Je rencontre l'erreur EOF mentionnée par Scott qui est enracinée dans un code d'erreur TLS 20 (MAC_logging incorrect). Du côté MS, il est signalé comme une erreur SChannel.

Comme je me déployais sur plusieurs servers et que je voulais un RPM, j'ai édité le file freetds.spec pour supprimer le –with-gnutls et l'ai remplacé par –with-openssl = yes, puis j'ai reconstruit les RPM avec rpmbuild, en vérifiant que rpmbuild fait utilisé la directive que j'ai ajouté et ne contient pas –with-gnutls.

Pour tester, j'ai écrit un petit utilitaire Perl qui se connecte à la database / déconnecte en succession rapide.

J'ai vérifié plusieurs fois que lorsque –with-gnutls est utilisé, l'erreur TLS / SChannel / EOF est rencontrée entre 0,5% et 1% du time.

Lorsque seule la directive –with-openssl = yes est utilisée et sans –with-gnutls présent, je ne reçois aucune erreur. Ces tests ont été effectués à quelques minutes d'intervalle et ont impliqué 5000 tentatives de connection en succession rapide (environ 10 connections ouvertes et fermées par seconde). Aucune autre option de configuration de freetds n'a été modifiée. La seule différence entre les deux tests sont les directives énumérées ci-dessus. La construction et l'installation du RPM, les files de configuration freetds, etc. étaient tous automatisés et ne changeaient pas entre les tests.

Lorsque l'erreur se produit, elle est signalée du côté client comme suit:

DBI connect ('MYDBNAME', 'mydomain \ myusername', …) a échoué:
[unixODBC] [FreeTDS] [SQL Server] Impossible de se connecter à la source de données (SQL-08001) [l'état était 08001 maintenant 01000]
[UnixODBC] [FreeTDS] [SQL Server] La connection à Adaptive Server a échoué (SQL-01000)
[unixODBC] [FreeTDS] [SQL Server] EOF inattendu du server (SQL-01000) à ./dbconnectiontestlots.pl ligne 18

Ce test utilisait freetds-1.00.24-1.x86_64, téléchargé directement à partir de freetds.org, construit sur RHEL6 . Les RPM suivants ont été installés à partir du dossier / root / rpmbuild / RPMS / pour ce test après avoir exécuté rpmbuild à chaque fois:

386996 5 janvier 14:28 freetds-1.00.24-1.x86_64.rpm
187560 5 janv. 14:28 freetds-unixodbc-1.00.24-1.x86_64.rpm

UnixODBC x86_64 2.2.14-14.el6 a également été installé directement via yum.

Mise à jour: bien que cette solution fonctionne sur les systèmes RHEL6 32 bits et 64 bits, elle ne fonctionne pas sur les systèmes RHEL5 32 bits