1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-11159 Server proxy protocol support

accept proxy protocol header from client connections.
The new server variable 'proxy_protocol_networks' contains list
of networks from which proxy header is accepted.
This commit is contained in:
Vladislav Vaintroub
2017-08-22 21:08:38 +02:00
parent d258a2bd1f
commit 58cd69fc80
24 changed files with 903 additions and 57 deletions

View File

@ -45,12 +45,9 @@
#include <violite.h>
#include <signal.h>
#include "probes_mysql.h"
#ifdef EMBEDDED_LIBRARY
#undef MYSQL_SERVER
#undef MYSQL_CLIENT
#define MYSQL_CLIENT
#endif /*EMBEDDED_LIBRARY */
#include "proxy_protocol.h"
#include <sql_class.h>
#include <sql_connect.h>
/*
to reduce the number of ifdef's in the code
@ -118,7 +115,6 @@ extern my_bool thd_net_is_killed();
#define thd_net_is_killed() 0
#endif
#define TEST_BLOCKING 8
static my_bool net_write_buff(NET *, const uchar *, ulong);
@ -828,6 +824,57 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
#endif /* NO_ALARM */
/**
Try to parse and process proxy protocol header.
This function is called in case MySQL packet header cannot be parsed.
It checks if proxy header was sent, and that it was send from allowed remote
host, as defined by proxy-protocol-networks parameter.
If proxy header is parsed, then THD and ACL structures and changed to indicate
the new peer address and port.
Note, that proxy header can only be sent either when the connection is established,
or as the client reply packet to
*/
static int handle_proxy_header(NET *net)
{
proxy_peer_info peer_info;
THD *thd= (THD *)net->thd;
if (!thd || !thd->net.vio)
{
DBUG_ASSERT(0);
return 1;
}
if (!is_proxy_protocol_allowed((sockaddr *)&(thd->net.vio->remote)))
{
/* proxy-protocol-networks variable needs to be set to allow this remote address */
my_printf_error(ER_HOST_NOT_PRIVILEGED, "Proxy header is not accepted from %s",
MYF(0), thd->main_security_ctx.ip);
return 1;
}
if (parse_proxy_protocol_header(net, &peer_info))
{
/* Failed to parse proxy header*/
my_printf_error(ER_UNKNOWN_ERROR, "Failed to parse proxy header", MYF(0));
return 1;
}
if (peer_info.is_local_command)
/* proxy header indicates LOCAL connection, no action necessary */
return 0;
#ifdef EMBEDDED_LIBRARY
DBUG_ASSERT(0);
return 1;
#else
/* Change peer address in THD and ACL structures.*/
return thd_set_peer_addr(thd, &(peer_info.peer_addr), NULL, peer_info.port, false);
#endif
}
/**
Reads one packet to net->buff + net->where_b.
Long packets are handled by my_net_read().
@ -850,6 +897,9 @@ my_real_read(NET *net, size_t *complen,
#ifndef NO_ALARM
ALARM alarm_buff;
#endif
retry:
my_bool net_blocking=vio_is_blocking(net->vio);
uint32 remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
NET_HEADER_SIZE);
@ -1081,6 +1131,22 @@ end:
packets_out_of_order:
{
if (has_proxy_protocol_header(net)
&& net->thd &&
((THD *)net->thd)->get_command() == COM_CONNECT)
{
/* Proxy information found in the first 4 bytes received so far.
Read and parse proxy header , change peer ip address and port in THD.
*/
if (handle_proxy_header(net))
{
/* error happened, message is already written. */
len= packet_error;
goto end;
}
goto retry;
}
DBUG_PRINT("error",
("Packets out of order (Found: %d, expected %u)",
(int) net->buff[net->where_b + 3],
@ -1171,6 +1237,7 @@ my_net_read_packet_reallen(NET *net, my_bool read_from_server, ulong* reallen)
len+= total_length;
net->where_b = save_pos;
}
net->read_pos = net->buff + net->where_b;
if (len != packet_error)
{