WL#12715: Support multiple addresses for the --mysqlx-bind-address command option
Motivation
Network configuration of a server that run MySQL Server, may consist of multiple network interfaces which may serve different propose, for example
Host:
- eth0 - intra-site network (business network)
- eth1 - inter-site network (business network)
- eth2 - public network
While the DBA may configure MySQL Server to listen on one of those interfaces or on all, still if He doesn't have a possibility of listening only on "business network" (two interfaces), where listening on public interface might be unwanted or even be a security issue.
MySQL Server introduced binding to multiple addresses under WL#11652. X Plugin should be aligned to those changes.
The MySQL server can be configured to listen to one (and only one) IPv4 and one (and only one) IPv6 interface, or all interfaces that are configured on a server. See https://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_bind- address
If at OS level, the server has multiple networks addresses, there is a need to configure the MySQL server to listen to a set of addresses, to also be able to restrict an address the server should not listen to.
Goal
Currently X Plugin accepts single bind address in configuration variable:
Mysqlx_bind_address
. The default value (which is *
) makes X Plugin to listen
on all IPv6 and IPv4 interfaces. This worklog must give:
Allow user to configure X Plugin bind address with multiple IP address (interfaces) where he can skip unwanted interfaces of his host machine.
X Plugin must be in align with MySQL server, thus it must implement feature same as WL#11652.
Functional requirements
Existing Behaviour
SI: Single "hostname", selects specific interface
- SI1
- User must be able to specify single address to listen on
- SI2
- User must be able to specify single address with a network-namespace to listen
- SI3
- User must be able to specify local "hostname" to listen on
- SI4
- When user specified wrong "hostname" (that can't be bound) the server must start. The server must be accessible through X UNIX socket or classic protocol
MI: Single "hostname", selects multiple interfaces
- MI1
- User must be able to specify single address to listen on all interfaces
- MI2
- User must be able to specify single address to listen on all IPv4 interfaces
- MI3
- User must be able to specify single address to listen on all IPv6 interfaces
OB: Observability
- OB1
- User should be able to check on which interface X Plugin listens.
- OB2
- User should be able to check error log on information on ignored addresses (ERROR LEVEL).
- OB4
- User should be able to check error log on information that X Plugin is inaccessible, because all interfaces addresses were skipped and UNIX socket file name was invalid (ERROR LEVEL).
New requirements
MA: Multiple "hostnames", selects multiple interfaces
- MA1
- User must be able to specify multiple addresses that fulfill any requirement from 'SI' group.
- MA2
- User must be able to specify multiple addresses, where all invalid should be ignored.
NOB: Observability
- NOB1
- User should be able to check on which interfaces X Plugin listens.
Configuration
X Plugin already allows to configure the network interface on which its going to accept incoming connections. Still the value is limited to string describing just one network interfaces or all:
hostname, for example:
localhost
IPv4 interface address, for example:
127.0.0.1
10.0.0.1
IPv6 interface address, for example:
::1
2606:b400:840:40::8b2c:141c
fe80::1%lo0
address/IP interface address with network namespace
127.0.0.1/some_ns1
127.0.0.1/some_ns2
10.0.0.1/some_ns2
2606:b400:840:40::8b2c:141c/some_ns2
address selecting all IPv4 interfaces
0.0.0.0
address selecting all IPv6 interfaces
::
address selecting all interfaces
*
The implementation of this worklog must extend Mysqlx_bind_address
to accept
values with multiple addresses. The new value format must be the same as defined
by WL#11652 for bind_address
.
Multiple addresses must be separated by comma, where when there are more than
one address in the value, then "wildcards" are not allowed ("*", "::",
"0.0.0.0"). Thus following EBNF syntax, describes possible values for
Mysqlx_bind_address
:
wildcards = "::" | "0.0.0.0" | "*"
net_namespace = "/", name
interface = (IPv4 | IPv6 | hostname) [net_namespace]
more_interface = "," , interface
interfaces = interface, [{more_interface}]
bind_address = wildcards | interfaces
X Plugin must parse the configuration string at startup, and allocate listening socket for each entry. In case when user put an invalid address then it must be skipped and an error information must be sent to error-log.
If all entries were invalid (with UNIX socket), then X Plugin must send an error to error-log, that user won't be able to connect through X Protocol.
Note
Plugin API doesn't allow a plugin to fail startup of the server, this means that in case of invalid configuration of interfaces on which the plugin, it is not able to fail the startup because of that X Plugin must skip invalid configuration and create a note in error-log.
There is other possibility, to change XPlugin to "mandatory" plugin, still in that case, user won't be able to turn off the plugin. This option can be introduced in X Plugin in future still as separate worklog.
Instrumentation
Mysqlx_address - this variable already exist, only thing that changes is is that instead a single address on which X Plugin is accepting connection, it will report multiple addresses (only those that X Plugin was able to bind). The list of addresses must be separated with "comma", for example:
ADDR1, ADDR_WITH_NS_2, ADDR3
Summary:
Property | Value |
---|---|
Variable name | Mysqlx_address |
Variable type | string |
Allowed values | UNDEFINED - all addresses were invalid |
"" - Waiting for X Plugin startup | |
"ADDR([,ADDR...])+" list of addresses |
Error and Warnings
Following error-log message already exists and must be reused. It is reported in case when X Plugin doesn't have a interface to accept incoming connections:
ER_XPLUGIN_FAILED_TO_PREPARE_IO_INTERFACES
eng "Preparation of I/O interfaces failed, X Protocol won't be accessible"
Following error-log message must be logged in case when parsing of one of the addresses failed:
ER_XPLUGIN_FAILED_TO_PARSE_ADDRESS
eng "Value \"%s\" set to `Mysqlx_bind_address`, can't be parsed. Skipping this value."
Following error-log message must be logged in case when binding of one of the addresses failed:
ER_XPLUGIN_FAILED_TO_BIND_INTERFACE_ADDRESS
eng "Value \"%s\" set to `Mysqlx_bind_address`, X Plugin can't bind to it. Skipping this value."
Before ER_XPLUGIN_FAILED_TO_BIND_INTERFACE_ADDRESS
, the plugin should print an error-log message
containing error-number and error description of the failure.
Note
Those error messages are only suggestions, and in the final solution the message might be different, for example having more context or information.
General
Currently Socket_acceptors_task
class is responsible for creating both listeners (UNIX socket, TCP) and Server_builder
parses the Mysqlx_bind_address
string. The dependency between all relevant classes can be represented by following UML diagram:
Server_builder o-- Socket_acceptors_task
Socket_acceptors_task "1" *-- "0..2" Listener
Where Listener
class represents an concrete bind address to which server is bound, also potential unix-socket listener.
Goal
Socket_acceptors_task
must handle multiple TCP bind addresses, thus it must handle multiple listeners. This "Multiplicity" between Socket_acceptors_task
and Listener
is going to be changed:
Server_builder o-- Socket_acceptors_task
Socket_acceptors_task "1" *-- "0..*" Listener
Thus Server_builder
be able to divide Mysqlx_bind_address
to multiple addresses and pass them to Server_acceptors_task
to create the sockets.