mirror of
https://github.com/boostorg/mysql.git
synced 2025-05-12 14:11:41 +00:00
292 lines
10 KiB
Plaintext
292 lines
10 KiB
Plaintext
[/
|
|
Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
]
|
|
|
|
[section:connection_establishment Connection establishment and termination]
|
|
[nochunk]
|
|
|
|
This section discusses several aspects regarding the creation,
|
|
establishment and termination of client connections.
|
|
|
|
|
|
|
|
|
|
|
|
[section Authentication]
|
|
|
|
[refmem connect_params username] and [refmem connect_params password]
|
|
contain the credentials used during authentication.
|
|
The password is sent to the server either hashed or over a secure
|
|
channel such as TLS, as mandated by the protocol.
|
|
|
|
MySQL implements several authentication plugins that can be used
|
|
to authenticate a user (see the [mysqllink pluggable-authentication.html
|
|
pluggable authentication MySQL docs]).
|
|
Each MySQL user is associated to a single authentication
|
|
plugin, specified during using creation.
|
|
Additionally, servers define a default authentication plugin
|
|
(see [mysqllink server-system-variables.html#sysvar_authentication_policy `authentication_policy`] and
|
|
[mysqllink server-system-variables.html#sysvar_default_authentication_plugin
|
|
`default_authentication_plugin`]). The default plugin will
|
|
be used for newly created users, and may affect how the handshake works.
|
|
|
|
This library implements the two most common authentication plugins:
|
|
|
|
* [mysqllink native-pluggable-authentication.html `mysql_native_password`].
|
|
Unless otherwise configured, this is the default plugin for
|
|
MySQL 5.7 and MariaDB. It can be used over both TLS and plaintext
|
|
connections. It sends the password hashed, salted by a nonce.
|
|
* [mysqllink caching-sha2-pluggable-authentication.html
|
|
`caching_sha2_password`]. This is the default plugin for
|
|
MySQL 8.0+. It can only be used over secure transports,
|
|
like TCP with TLS or UNIX sockets.
|
|
|
|
|
|
Multi-factor authentication is not yet supported.
|
|
If you require support for a plugin not listed above or for MFA,
|
|
please file a feature request against the GitHub repository.
|
|
|
|
[note
|
|
Servers configured with a default authentication plugin
|
|
not implemented in Boost.MySQL are not supported, regardless
|
|
of the actual plugin the concrete user employs. This limitation
|
|
may be lifted in the future.
|
|
]
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
[section Connect with database]
|
|
|
|
[refmem connect_params database] contains the database name
|
|
to connect to. If you specify it, your connection will default to
|
|
use that database, as if you had issued a __USE__ statement.
|
|
You can leave it blank to select no database.
|
|
You can always issue a __USE__ statement using [refmemunq any_connection async_execute]
|
|
to select a different database after establishing the connection.
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
|
|
[section:tls TLS support]
|
|
|
|
TLS encrypted connections are fully supported by Boost.MySQL.
|
|
TCP connections established using [reflink any_connection] use TLS by default.
|
|
|
|
[heading TLS handshake and termination]
|
|
|
|
The TLS handshake is performed by [refmem any_connection async_connect].
|
|
This contrasts with libraries like __Beast__, where the TLS handshake
|
|
must be explicitly invoked by the user.
|
|
We selected this approach because the TLS handshake is part of the MySQL protocol's handshake:
|
|
the client and server exchange several unencrypted messages, then perform the TLS handshake
|
|
and continue exchanging encrypted messages, until the connection either succeeds or fails.
|
|
This scheme enables the TLS negotiation feature (see below for more info).
|
|
|
|
If the TLS handshake fails, the entire [refmemunq any_connection async_connect]
|
|
operation will also fail.
|
|
|
|
TLS shutdown is performed by [refmem any_connection async_close].
|
|
MySQL doesn't always close TLS connections
|
|
gracefully, so errors generated by the TLS shutdown are ignored.
|
|
|
|
|
|
[heading:negotiation TLS negotiation]
|
|
|
|
During connection establishment, client and server negotiate whether to use TLS or not.
|
|
Boost.MySQL supports such negotiation using [refmem connect_params ssl]. This is
|
|
a [reflink ssl_mode] enum with the following options:
|
|
|
|
* `ssl_mode::enable` will make the connection use TLS if the server supports it,
|
|
falling back to a plaintext connection otherwise. [*This is the default]
|
|
for [reflink any_connection] when using TCP.
|
|
* `ssl_mode::require` ensures that the connection uses TLS.
|
|
If the server does not support it, [refmemunq any_connection async_connect] fails.
|
|
* `ssl_mode::disable` unconditionally disables TLS.
|
|
|
|
[*UNIX sockets] are considered secure channels and [*never use TLS].
|
|
When connecting using a UNIX socket, [refmem connect_params ssl] is ignored.
|
|
|
|
After a successful connection establishment, you can use
|
|
[refmem any_connection uses_ssl] to query whether the connection is encrypted or not.
|
|
|
|
|
|
[heading Disabling TLS]
|
|
|
|
As mentioned above, setting [refmem connect_params ssl] to `ssl_mode::disable`
|
|
disables TLS:
|
|
|
|
[section_connection_establishment_disable_tls]
|
|
|
|
See the [link mysql.examples.disable_tls full example here].
|
|
|
|
|
|
|
|
[heading:options Certificate validation and other TLS options]
|
|
|
|
You can pass an optional __ssl_context__ to [reflink any_connection]
|
|
constructor. You can set many TLS parameters doing this, including
|
|
trusted CAs, certificate validation callbacks and TLS extensions.
|
|
|
|
[reflink any_connection_params] contains a [refmemunq any_connection_params ssl_context]
|
|
member that can be used for this. For example, TLS certificate validation
|
|
is disabled by default. To enable it:
|
|
|
|
[section_connection_establishment_tls_options]
|
|
|
|
You can safely share a single __ssl_context__ among several connections.
|
|
|
|
If no `ssl::context` is passed, one will be internally created by the
|
|
connection when required. The default context doesn't perform certificate validation.
|
|
|
|
The full source code for the above example is [link mysql.examples.tls_certificate_verification here].
|
|
|
|
|
|
|
|
[heading TLS in connection_pool]
|
|
|
|
Since [reflink connection_pool] creates [reflink any_connection] instances,
|
|
the mechanics for TLS are similar. TLS-related parameters are specified
|
|
during pool construction, as members of [reflink pool_params]:
|
|
|
|
* [refmem pool_params ssl] controls TLS negotiation.
|
|
It's a [reflink ssl_mode] value, with the semantics explained
|
|
[link mysql.connection_establishment.tls.negotiation above].
|
|
* [refmem pool_params ssl_ctx] is a __ssl_context__
|
|
that is passed to connections created by the pool.
|
|
It can be used to configure
|
|
[link mysql.connection_establishment.tls.options TLS options]
|
|
like certificate verification. The pool takes ownership
|
|
of the passed `ssl::context`, as opposed to `any_connection`.
|
|
|
|
[endsect] [/ TLS ]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[section:unix UNIX sockets]
|
|
|
|
[refmem connect_params server_address] is an [reflink any_address],
|
|
a variant-like type that can hold a (hostname, port) pair or a UNIX socket path.
|
|
To connect to MySQL using a UNIX socket, set `server_address`
|
|
to a UNIX domain path:
|
|
|
|
[section_connection_establishment_unix_socket]
|
|
|
|
Note that UNIX sockets never use TLS, regardless of the value of
|
|
[refmem connect_params ssl].
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
|
|
|
|
[section Changing the network buffer size limit]
|
|
|
|
[reflink any_connection] owns an internal network buffer
|
|
used to store messages that are to be written or have been read
|
|
from the server. Its initial size is given by [refmem any_connection_params initial_buffer_size].
|
|
Every protocol message needs to fit in memory, so the buffer is expanded as required.
|
|
When reading data, every row is sent as an individual message.
|
|
|
|
The buffer never resizes past [refmem any_connection_params max_buffer_size].
|
|
If an operation requires a bigger buffer, it will fail with the
|
|
`client_errc::max_buffer_size_exceeded` error code. The default size
|
|
is 64MB.
|
|
|
|
If you need to read or write individual rows bigger than the default limit,
|
|
you can increase it when constructing the connection:
|
|
|
|
[section_connection_establishment_max_buffer_size]
|
|
|
|
Note that reading datasets bigger than 64MB [*does not require increasing the limit]
|
|
as long as individual rows are smaller than the aforementioned limit.
|
|
|
|
Tweaking [refmem any_connection_params initial_buffer_size] may affect
|
|
[refmem any_connection async_read_some_rows] performance, as explained
|
|
in [link mysql.multi_function.read_some_rows this section].
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
|
|
[section Enabling multi-queries]
|
|
|
|
You can run several several semicolon-separated queries at once using
|
|
[refmem any_connection async_execute]. This is a protocol feature that
|
|
is disabled by default. You can enable it by setting
|
|
[refmem connect_params multi_queries] to true before connecting:
|
|
|
|
[section_connection_establishment_multi_queries]
|
|
|
|
As explained [link mysql.tutorial_updates_transactions in the tutorial],
|
|
multi-separated queries are useful in a number of cases,
|
|
like when using transactions.
|
|
[link mysql.multi_resultset.multi_queries This section] contains more
|
|
info on how to use multi-queries.
|
|
|
|
This protocol feature is disabled by default as a security hardening
|
|
measure. If your application contains a SQL injection vulnerability,
|
|
this feature can make exploiting it easier. Applications that don't
|
|
need this feature should leave it off as a best practice.
|
|
|
|
[note
|
|
Using multi-queries correctly is secure. Just make sure to use
|
|
the adequate client-side SQL formatting tools to generate queries securely.
|
|
]
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
[section Closing a connection]
|
|
|
|
You can cleanly close a connection by calling [refmem any_connection async_close].
|
|
This sends a ['quit packet] to the server, notifying that we're about to end
|
|
the connection, performs TLS shutdown, and closes the underlying transport.
|
|
A clean close involves I/O and can thus fail.
|
|
|
|
[*Destroying the connection] without performing a clean close
|
|
will just close the underlying transport. [*It won't leak any resource],
|
|
but you might see warnings in the server log. Try to close connections
|
|
cleanly when possible.
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
[section Reconnection and long-lived connections]
|
|
|
|
[reflink any_connection] doesn't perform any re-connection on its own.
|
|
If a fatal error (like a network error) is encountered during an operation,
|
|
you need to re-establish the connection explicitly.
|
|
|
|
By design, [refmem any_connection async_connect] can [*always be used]
|
|
to re-establish connections. It works even after the connection encountered
|
|
a network error or a cancellation. To achieve this, `async_connect`
|
|
will wipe any previous connection state before proceeding.
|
|
|
|
If you need reliable, long-lived connections, consider
|
|
[link mysql.connection_pool using a connection pool]
|
|
instead of rolling out your own strategy. `connection_pool`
|
|
takes care of re-connecting and re-using connections for you.
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
|
|
[endsect] [/ connparams]
|