Le serveur répond avec un paquet vide pendant la négociation de session, ce qui entraîne une erreur de paquet mal formée par le client


14

J'essaie de me connecter à un serveur mysql distant. Cela se produit à 100% du temps.

client: mysql Ver 14.14 Distrib 5.7.12, pour
serveur Win32 (AMD64) : 5.0.95

Voici l'erreur que j'obtiens:

C:\>mysql -h example.com -P 3306 -D prod_rcadb -u username -p
Enter password: **********
ERROR 2027 (HY000): Malformed packet

même erreur avec mysqladmin:

C:\>mysqladmin -h example.com -P 3306 -u username -p version
Enter password: **********
mysqladmin: connect to server at '10.106.24.79' failed
error: 'Malformed packet'

J'ai donc pris un pcap, juste pour avoir une idée de ce à quoi ressemblait cette conversation.

Prise de contact TCP:

1              2016-04-14 11:18:48.910690         0.000000              137.69.150.80                     10.106.24.79       TCP        66                511573306 [SYN] Seq=0 Win=8192 Len=0 MSS=1428 WS=256 SACK_PERM=1   8192
2              2016-04-14 11:18:49.019893         0.109203              10.106.24.79                       137.69.150.80     TCP        66                330651157 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1460 SACK_PERM=1 WS=256           5840
3              2016-04-14 11:18:49.019893         0.000000              137.69.150.80                     10.106.24.79       TCP        54                511573306 [ACK] Seq=1 Ack=1 Win=65536 Len=0          256

Négociation de connexion Mysql:

4              2016-04-14 11:18:49.144696         0.124803              10.106.24.79                       137.69.150.80     MySQL  110        Server Greeting proto=10 version=5.0.95            23
5              2016-04-14 11:18:49.144696         0.000000              137.69.150.80                     10.106.24.79       MySQL  119         Login Request user=bigdata   256<br>
6              2016-04-14 11:18:49.144696         0.000000              10.106.24.79                       137.69.150.80     TCP        60                330651157 [ACK] Seq=57 Ack=66 Win=5888 Len=0        23
7              2016-04-14 11:18:49.316301         0.171605              10.106.24.79                       137.69.150.80     MySQL  60           Response                23

Ainsi, le client se connecte au niveau TCP, le serveur nous accueille avec les options et l'état pris en charge:

Server Capabilities: 0xa22c
.... .... .... ...0 = Long Password: Not set
.... .... .... ..0. = Found Rows: Not set
.... .... .... .1.. = Long Column Flags: Set
.... .... .... 1... = Connect With Database: Set
.... .... ...0 .... = Don't Allow database.table.column: Not set
.... .... ..1. .... = Can use compression protocol: Set
.... .... .0.. .... = ODBC Client: Not set
.... .... 0... .... = Can Use LOAD DATA LOCAL: Not set
.... ...0 .... .... = Ignore Spaces before '(': Not set
.... ..1. .... .... = Speaks 4.1 protocol (new flag): Set
.... .0.. .... .... = Interactive Client: Not set
.... 0... .... .... = Switch to SSL after handshake: Not set
...0 .... .... .... = Ignore sigpipes: Not set
..1. .... .... .... = Knows about transactions: Set
.0.. .... .... .... = Speaks 4.1 protocol (old flag): Not set
1... .... .... .... = Can do 4.1 authentication: Set
Server Language: latin1 COLLATE latin1_swedish_ci (8)

Le client demande une connexion:

.... .... .... ...1 = Long Password: Set
.... .... .... ..0. = Found Rows: Not set
.... .... .... .1.. = Long Column Flags: Set
.... .... .... 0... = Connect With Database: Not set
.... .... ...0 .... = Don't Allow database.table.column: Not set
.... .... ..0. .... = Can use compression protocol: Not set
.... .... .0.. .... = ODBC Client: Not set
.... .... 1... .... = Can Use LOAD DATA LOCAL: Set
.... ...0 .... .... = Ignore Spaces before '(': Not set
.... ..1. .... .... = Speaks 4.1 protocol (new flag): Set
.... .0.. .... .... = Interactive Client: Not set
.... 0... .... .... = Switch to SSL after handshake: Not set
...0 .... .... .... = Ignore sigpipes: Not set
..1. .... .... .... = Knows about transactions: Set
.0.. .... .... .... = Speaks 4.1 protocol (old flag): Not set
1... .... .... .... = Can do 4.1 authentication: Set
Extended Client Capabilities: 0x81be
.... .... .... ...0 = Multiple statements: Not set
.... .... .... ..1. = Multiple results: Set
.... .... .... .1.. = PS Multiple results: Set
.... .... .... 1... = Plugin Auth: Set
.... .... ...1 .... = Connect attrs: Set
.... .... ..1. .... = Plugin Auth LENENC Client Data: Set
.... .... 1... .... = Session variable tracking: Set
1000 0001 .0.. .... = Unused: 0x0204

Le serveur acquitte, puis envoie une réponse, qui est essentiellement vide…

Packet Length: 1
Packet Number: 2
EOF marker: 254

Et cela amène immédiatement le client à FIN et à fermer le socket:

8              2016-04-14 11:18:49.316301         0.000000              137.69.150.80                     10.106.24.79       TCP        54                511573306 [FIN, ACK] Seq=66 Ack=62 Win=65536 Len=0            256
9              2016-04-14 11:18:49.332901         0.016600              10.106.24.79                       137.69.150.80     TCP        60                330651157 [ACK] Seq=62 Ack=67 Win=5888 Len=0        23
10           2016-04-14 11:18:49.391904         0.059003              10.106.24.79                       137.69.150.80     TCP        60                330651157 [FIN, ACK] Seq=62 Ack=67 Win=5888 Len=0              23
11           2016-04-14 11:18:49.391904         0.000000              137.69.150.80                     10.106.24.79       TCP        54                511573306 [ACK] Seq=67 Ack=63 Win=65536 Len=0     256

Le client qui se connectait n'a donc pas aimé ce paquet vide envoyé par le serveur.

Je n'obtiens pas cela contre un autre serveur mysql de la même version du même client. Voici le paquet de réponse à la demande de connexion du serveur 2:

Packet Length: 7
Packet Number: 2
Affected Rows: 0
Server Status: 0x0002
.... .... .... ...0 = In transaction: Not set
.... .... .... ..1. = AUTO_COMMIT: Set
.... .... .... .0.. = More results: Not set
.... .... .... 0... = Multi query - more resultsets: Not set
.... .... ...0 .... = Bad index used: Not set
.... .... ..0. .... = No index used: Not set
.... .... .0.. .... = Cursor exists: Not set
.... .... 0... .... = Last row sent: Not set
.... ...0 .... .... = database dropped: Not set
.... ..0. .... .... = No backslash escapes: Not set
.... .0.. .... .... = Session state changed: Not set
.... 0... .... .... = Query was slow: Not set
...0 .... .... .... = PS Out Params: Not set

Je ne gère pas cette base de données moi-même, mais si vous avez des suggestions de choses à rechercher dans les journaux, je peux demander ces informations.

Avez-vous des idées sur la raison pour laquelle je reçois un paquet vide du serveur?

Réponses:


13

Le paquet que je pensais vide n'était en fait pas, c'était une ancienne requête de changement d'authentification :

Payload
1     [fe]
Fields
status (1) -- 0xfe
Returns
Protocol::AuthSwitchResponse with old password hash
Example
01 00 00 02 fe

Le 1, 2, 254 que wirehark a analysé est en fait 01 00 00 02 fe si vous regardez les chaînes d'octets réelles.

Ce n'est donc pas qu'il y a un malentendu, le serveur comprend complètement et répond correctement et le client se termine correctement car il ne peut pas négocier. Le protocole n'est pas trop ancien car il a été modifié en 4.1, donc 5.0 et 5.7 se comprennent parfaitement. Cela devrait être un message d'erreur plus clair.

Le client est trop nouveau pour utiliser --skip-secure-auth ( référence ). Ils ont délibérément supprimé la possibilité de négocier avant 5.7.

Donc, mes options sont d'autoriser de nouveaux mots de passe sur le serveur (qui est une configuration spécifique à l'utilisateur, pas une option de serveur globale) ou d'utiliser un ancien binaire.

Le problème de configuration spécifique est basé sur le nom d'utilisateur qui m'a été donné. À un moment donné dans le passé, une personne utilisant ce nom d'utilisateur utilisait un ancien client et a changé la méthode de mot de passe :

B.5.2.4 Client does not support authentication protocol

The current implementation of the authentication protocol uses a password hashing algorithm that is incompatible with that used by older (pre-4.1) clients. Attempts to connect to a 4.1 or newer server with an older client may fail with the following message:

shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

To deal with this problem, the preferred solution is to upgrade all client programs to use a 4.1.1 or newer client library. If that is not possible, use one of the following approaches:

    To connect to the server with a pre-4.1 client program, use an account that still has a pre-4.1-style password.

    Reset the password to pre-4.1 style for each user that needs to use a pre-4.1 client program. This can be done using the SET PASSWORD statement and the OLD_PASSWORD() function. As of MySQL 5.6.6, it is also necessary to first ensure that the authentication plugin for the account is mysql_old_password:

    mysql> UPDATE mysql.user SET plugin = 'mysql_old_password'
    mysql> WHERE User = 'some_user' AND Host = 'some_host';
    mysql> FLUSH PRIVILEGES;
    mysql> SET PASSWORD FOR
        -> 'some_user'@'some_host' = OLD_PASSWORD('new_password');

2

J'ai eu cette erreur en essayant de me connecter à un ancien serveur MySQL avec @@old_passwordsactivé. J'utilise mysql-client v5.7.19 et la version du serveur: 5.1.73.

J'ai résolu le problème en créant manuellement un hachage de mot de passe MySQL SHA1 (en utilisant un programme que j'ai écrit à cet effet), puis j'ai exécuté cette commande sur le serveur:

SET PASSWORD FOR 'nagios'@'10.10.10.201' = 'xxxx';

(Où xxxxétait en fait le hachage.)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.