El servidor responde con un paquete vacío durante la negociación de la sesión, lo que da como resultado que el cliente presente un error de paquete con formato incorrecto

14

Estoy intentando conectarme a un servidor mysql remoto. Esto sucede el 100% del tiempo.

cliente: mysql Ver 14.14 Distrib 5.7.12, para el
servidor Win32 (AMD64) : 5.0.95

Este es el error que obtengo:

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

mismo error con 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'

Así que tomé un pcap, solo para tener una idea de cómo era esa conversación.

Protocolo de enlace 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

Negociación de conexión 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

Entonces, el cliente se conecta a nivel TCP, el servidor nos saluda con opciones y estado compatibles:

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)

El cliente solicita un inicio de sesión:

.... .... .... ...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

El servidor reconoce, luego envía una respuesta, que está esencialmente vacía ...

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

Y eso inmediatamente hace que el cliente FIN y cierre el zócalo:

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

Entonces, al cliente de conexión no le gustó el paquete vacío que envió el servidor.

No obtengo esto contra otro servidor mysql de la misma versión del mismo cliente. Aquí está el paquete de respuesta a la solicitud de inicio de sesión del servidor 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

Yo mismo no administro esta base de datos, pero si tiene sugerencias para buscar en los registros, puedo solicitar esa información.

¿Alguna idea de por qué recibo un paquete vacío del servidor?

MaQleod
fuente

Respuestas:

13

El paquete que pensé que estaba vacío en realidad no lo era, era una Solicitud de cambio de autenticación antigua :

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

El 1, 2, 254 analizado por wirehark es en realidad 01 00 00 02 fe si nos fijamos en las cadenas de bytes reales.

Por lo tanto, no es que haya un malentendido, el servidor comprende completamente y responde correctamente y el cliente termina correctamente porque no puede negociar. El protocolo no es demasiado antiguo, ya que se modificó en 4.1, por lo que 5.0 y 5.7 se entienden perfectamente. Este debería ser un mensaje de error más claro.

El cliente es demasiado nuevo para usar --skip-secure-auth ( referencia ). Quitaron deliberadamente la capacidad de negociar antes de 5.7.

Entonces, mis opciones son permitir nuevas contraseñas en el servidor (que es una configuración específica del usuario, no una opción de servidor global) o usar un binario más antiguo.

El problema de configuración específico se basa en el nombre de usuario que me dieron. En algún momento en el pasado, alguien que usaba este nombre de usuario estaba usando un cliente anterior y cambiaron el método de contraseña :

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');
MaQleod
fuente
2

Recibí este error al intentar conectarme a un servidor MySQL anterior con @@old_passwordshabilitado. Estoy usando mysql-client v5.7.19 y la versión del servidor: 5.1.73.

Solucioné el problema creando manualmente un hash de contraseña SHA1 de MySQL (usando un programa que escribí para ese propósito) y luego ejecuté este comando en el servidor:

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

(¿Dónde xxxxestaba realmente el hash?)

Alastair Irvine
fuente