Proxy protocol setting error detection + documentation

The setting parsing is now similar to the other server settings.
The header is printed if log_info is on.
Changed the setting name to simply "proxy_protocol".
Updated documentation.
This commit is contained in:
Esa Korhonen
2017-08-02 13:57:59 +03:00
parent 75b17151f3
commit 8e9c943d48
5 changed files with 54 additions and 21 deletions

View File

@ -1073,23 +1073,36 @@ closed.
For more information about persistent connections, please read the
[Administration Tutorial](../Tutorials/Administration-Tutorial.md).
#### `use_proxy_protocol`
#### `proxy_protocol`
If `use_proxy_protocol` is set to `yes`, MaxScale will send a proxy protocol
If `proxy_protocol` is set to `on`, MaxScale will send a
[PROXY protocol](http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
header when connecting client sessions to the server. The header contains the
original client IP address and port, as seen by MaxScale. The server will then
read the header and perform authentication as if the connection originated from
this address instead of the MaxScale IP address. With this feature, the user
this address instead of MaxScale's IP address. With this feature, the user
accounts on the backend server can be simplified to only contain the actual
client hosts and not the MaxScale host.
Currently, using this feature is unpractical due to the restrictiveness of the
proxy protocol. The protocol requires that *all* connections from proxy enabled
addresses must send a valid proxy header. MaxScale has other connections to the
servers in addition to client sessions, e.g. monitors, and the server will
refuse these due to the lack of the header. To bypass this restriction, the
server monitor needs to be disabled and the service listener needs to be
PROXY protocol will be supported by MariaDB 10.3, which this feature has been
tested with. To use it, enable the PROXY protocol in MaxScale for every
compatible server and configure the MariaDB servers themselves to accept the
protocol headers from MaxScale's IP address. On the server side, the protocol
should be enabled only for trusted IPs, as it allows the sender to spoof the
connection origin. If a proxy header is sent to a server not expecting it, the
connection will fail. Usually PROXY protocol should be enabled for every
server in a cluster, as they typically have similar grants.
Other SQL-servers may support PROXY protocol as well, but the implementation may
be highly restricting. Strict adherence to the protocol requires that the
backend server does not allow mixing of un-proxied and proxied connections from
a given IP. MaxScale requires normal connections to backends for monitoring and
authentication data queries, which would be blocked. To bypass this restriction,
the server monitor needs to be disabled and the service listener needs to be
configured to disregard authentication errors (`skip_authentication=true`).
Server states also need to be set manually in MaxAdmin. These steps are *not*
required for MariaDB 10.3, since its implementation is more flexible and allows
both PROXY-headered and headerless connections from a proxy-enabled IP.
#### `authenticator`

View File

@ -39,7 +39,7 @@ extern const char CN_MONITORPW[];
extern const char CN_MONITORUSER[];
extern const char CN_PERSISTMAXTIME[];
extern const char CN_PERSISTPOOLMAX[];
extern const char CN_USE_PROXY_PROTOCOL[];
extern const char CN_PROXY_PROTOCOL[];
/**
* The server parameters used for weighting routing decissions
@ -133,7 +133,7 @@ typedef struct server
uint8_t charset; /**< Default server character set */
bool is_active; /**< Server is active and has not been "destroyed" */
bool created_online; /**< Whether this server was created after startup */
bool use_proxy_protocol; /**< Send proxy-protocol header when connecting client sessions. */
bool proxy_protocol; /**< Send proxy-protocol header to backend when connecting client sessions. */
#if defined(SS_DEBUG)
skygw_chk_t server_chk_tail;
#endif

View File

@ -269,7 +269,7 @@ const char *server_params[] =
CN_SSL_KEY,
CN_SSL_VERSION,
CN_SSL_CERT_VERIFY_DEPTH,
CN_USE_PROXY_PROTOCOL,
CN_PROXY_PROTOCOL,
NULL
};
@ -2953,7 +2953,25 @@ int create_new_server(CONFIG_CONTEXT *obj)
}
}
server->use_proxy_protocol = config_get_bool(obj->parameters, CN_USE_PROXY_PROTOCOL);
const char* proxy_protocol = config_get_value_string(obj->parameters, CN_PROXY_PROTOCOL);
if (*proxy_protocol)
{
int truth_value = config_truth_value(proxy_protocol);
if (truth_value == 1)
{
server->proxy_protocol = true;
}
else if (truth_value == 0)
{
server->proxy_protocol = false;
}
else
{
MXS_ERROR("Invalid value for '%s' for server %s: %s",
CN_PROXY_PROTOCOL, server->unique_name, proxy_protocol);
error_count++;
}
}
MXS_CONFIG_PARAMETER *params = obj->parameters;

View File

@ -56,7 +56,7 @@ const char CN_MONITORPW[] = "monitorpw";
const char CN_MONITORUSER[] = "monitoruser";
const char CN_PERSISTMAXTIME[] = "persistmaxtime";
const char CN_PERSISTPOOLMAX[] = "persistpoolmax";
const char CN_USE_PROXY_PROTOCOL[] = "use_proxy_protocol";
const char CN_PROXY_PROTOCOL[] = "proxy_protocol";
static SPINLOCK server_spin = SPINLOCK_INIT;
static SERVER *allServers = NULL;
@ -141,7 +141,7 @@ SERVER* server_alloc(const char *name, const char *address, unsigned short port,
server->is_active = true;
server->created_online = false;
server->charset = SERVER_DEFAULT_CHARSET;
server->use_proxy_protocol = false;
server->proxy_protocol = false;
spinlock_acquire(&server_spin);
server->next = allServers;
@ -570,9 +570,9 @@ dprintServer(DCB *dcb, const SERVER *server)
dcb_printf(dcb, "\tSSL CA certificate: %s\n",
l->ssl_ca_cert ? l->ssl_ca_cert : "null");
}
if (server->use_proxy_protocol)
if (server->proxy_protocol)
{
dcb_printf(dcb, "\tProxy protocol enabled.\n");
dcb_printf(dcb, "\tPROXY protocol: on.\n");
}
}
@ -1173,9 +1173,9 @@ static bool create_server_config(const SERVER *server, const char *filename)
dprintf(file, "%s=%ld\n", CN_PERSISTMAXTIME, server->persistmaxtime);
}
if (server->use_proxy_protocol)
if (server->proxy_protocol)
{
dprintf(file, "%s=yes\n", CN_USE_PROXY_PROTOCOL);
dprintf(file, "%s=on\n", CN_PROXY_PROTOCOL);
}
for (SERVER_PARAM *p = server->parameters; p; p = p->next)

View File

@ -198,7 +198,7 @@ static int gw_create_backend_connection(DCB *backend_dcb,
protocol->fd,
session->client_dcb->fd);
if (server->use_proxy_protocol)
if (server->proxy_protocol)
{
gw_send_proxy_protocol_header(backend_dcb);
}
@ -919,7 +919,7 @@ static int gw_write_backend_event(DCB *dcb)
if (backend_protocol->protocol_auth_state == MXS_AUTH_STATE_PENDING_CONNECT)
{
backend_protocol->protocol_auth_state = MXS_AUTH_STATE_CONNECTED;
if (dcb->server->use_proxy_protocol)
if (dcb->server->proxy_protocol)
{
gw_send_proxy_protocol_header(dcb);
}
@ -1906,6 +1906,8 @@ static void gw_send_proxy_protocol_header(DCB *backend_dcb)
GWBUF *headerbuf = gwbuf_alloc_and_load(strlen(proxy_header), proxy_header);
if (headerbuf)
{
MXS_INFO("Sending proxy-protocol header '%s' to backend %s.", proxy_header,
backend_dcb->server->unique_name);
if (!dcb_write(backend_dcb, headerbuf))
{
gwbuf_free(headerbuf);