mysql/doc/qbk/05_connection_establishment.qbk
2025-02-11 20:42:41 +01:00

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]