|
| 1 | +# RSA key exchange for `caching_sha2_password` |
| 2 | + |
| 3 | +ProxySQL 3.1 can authenticate MySQL clients that use |
| 4 | +`caching_sha2_password` over a non-TLS frontend connection. When full |
| 5 | +authentication is required, the client can request ProxySQL's RSA public key, |
| 6 | +encrypt its password, and send the ciphertext back to ProxySQL. |
| 7 | + |
| 8 | +TLS remains the recommended configuration. Requesting a public key over an |
| 9 | +unauthenticated connection encrypts the password on the wire, but it does not |
| 10 | +authenticate the ProxySQL server and is vulnerable to public-key substitution |
| 11 | +by an active network attacker. Use TLS when server identity and transport |
| 12 | +integrity are required. |
| 13 | + |
| 14 | +## Configuration |
| 15 | + |
| 16 | +The following MySQL variables are available in ProxySQL 3.1 and later: |
| 17 | + |
| 18 | +| Variable | Default | Description | |
| 19 | +| --- | --- | --- | |
| 20 | +| `mysql-caching_sha2_password_auto_generate_rsa_keys` | `true` | Generate a 2048-bit RSA pair when both configured files are absent. | |
| 21 | +| `mysql-caching_sha2_password_private_key_path` | `proxysql-caching-sha2-private-key.pem` | Private-key path. A relative path is resolved below ProxySQL's data directory. | |
| 22 | +| `mysql-caching_sha2_password_public_key_path` | `proxysql-caching-sha2-public-key.pem` | Public-key path. A relative path is resolved below ProxySQL's data directory. | |
| 23 | + |
| 24 | +Apply changes with: |
| 25 | + |
| 26 | +```sql |
| 27 | +LOAD MYSQL VARIABLES TO RUNTIME; |
| 28 | +``` |
| 29 | + |
| 30 | +The three variables form one configuration unit. ProxySQL validates or |
| 31 | +generates the complete pair before publishing it to frontend sessions. If a |
| 32 | +reload fails, all three runtime values and the previously loaded key snapshot |
| 33 | +remain unchanged. |
| 34 | + |
| 35 | +Relative paths must stay beneath ProxySQL's data directory. Empty, `.` and |
| 36 | +`..` components are rejected, and every parent directory is opened without |
| 37 | +following symbolic links. Absolute paths are allowed when keys are managed in |
| 38 | +another operator-controlled directory. |
| 39 | + |
| 40 | +## Key formats and permissions |
| 41 | + |
| 42 | +The private key must be an unencrypted PKCS#8 PEM RSA private key (the PEM |
| 43 | +header is `BEGIN PRIVATE KEY`). Traditional PKCS#1 (`BEGIN RSA PRIVATE KEY`) |
| 44 | +and encrypted private keys are rejected. The public key must be a PEM |
| 45 | +SubjectPublicKeyInfo public key. The two files must contain a structurally |
| 46 | +valid matching RSA pair of at least 2048 bits. |
| 47 | + |
| 48 | +The private file must be a regular file and must not grant any group or other |
| 49 | +permissions. Generated files use these modes: |
| 50 | + |
| 51 | +- private key: `0600` |
| 52 | +- public key: `0644` |
| 53 | + |
| 54 | +Encrypted private keys are not supported because ProxySQL has no runtime |
| 55 | +passphrase input for this feature. |
| 56 | + |
| 57 | +If the compiled default pair is unusable during initial runtime loading and |
| 58 | +cannot be regenerated safely, ProxySQL records an explicit TLS-only state |
| 59 | +(automatic generation off and both paths empty). TLS authentication remains |
| 60 | +available, while RSA public-key authentication stays disabled until a valid |
| 61 | +pair is loaded. |
| 62 | + |
| 63 | +Automatic generation occurs only when both paths are absent. If exactly one |
| 64 | +file exists, ProxySQL reports a configuration error and does not overwrite or |
| 65 | +replace either path. Generation uses temporary files and no-overwrite |
| 66 | +publication so concurrent ProxySQL processes cannot publish a mixed pair. |
| 67 | + |
| 68 | +## Reload and cluster behavior |
| 69 | + |
| 70 | +Each authentication exchange retains the same immutable key snapshot from the |
| 71 | +public-key response through RSA decryption. A concurrent |
| 72 | +`LOAD MYSQL VARIABLES TO RUNTIME` can therefore rotate keys without breaking |
| 73 | +an exchange already in progress. |
| 74 | + |
| 75 | +Cluster synchronization transfers the variable values, not private-key |
| 76 | +contents. Every ProxySQL node must be able to read its configured local pair, |
| 77 | +or generate its own pair when automatic generation is enabled. Do not store |
| 78 | +private-key contents in the ProxySQL configuration database. |
| 79 | + |
| 80 | +## Client behavior and failures |
| 81 | + |
| 82 | +The client must use `caching_sha2_password`, disable TLS only when intended, |
| 83 | +and enable its server-public-key request option. For Oracle's MySQL CLI: |
| 84 | + |
| 85 | +```bash |
| 86 | +mysql --default-auth=caching_sha2_password \ |
| 87 | + --ssl-mode=DISABLED --get-server-public-key \ |
| 88 | + --host=127.0.0.1 --port=6033 --user=app --password |
| 89 | +``` |
| 90 | + |
| 91 | +ProxySQL implements the MySQL protocol's RSA OAEP exchange, including the |
| 92 | +protocol-defined SHA-1 OAEP and MGF1 digests and password/scramble XOR step. |
| 93 | +Malformed ciphertext, malformed plaintext, and an incorrect password all |
| 94 | +produce the normal `1045` / `28000` access-denied response. If no valid RSA key |
| 95 | +pair is available, the same error code and SQLSTATE are returned with a message |
| 96 | +that identifies the unavailable RSA key exchange and suggests TLS or key |
| 97 | +configuration. |
0 commit comments