1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +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

@ -37,6 +37,7 @@
#include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL
#include "sql_callback.h"
#include "wsrep_mysqld.h"
#include "proxy_protocol.h"
HASH global_user_stats, global_client_stats, global_table_stats;
HASH global_index_stats;
@ -836,6 +837,89 @@ bool init_new_connection_handler_thread()
return 0;
}
int thd_set_peer_addr(THD *thd, sockaddr_storage *addr, const char *ip,uint port, bool check_proxy_networks)
{
uint connect_errors;
thd->peer_port = port;
char ip_string[128];
if (!ip)
{
void *addr_data;
if (addr->ss_family == AF_UNIX)
{
/* local connection */
my_free((void *)thd->main_security_ctx.ip);
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host = my_localhost;
thd->main_security_ctx.ip= 0;
return 0;
}
else if (addr->ss_family == AF_INET)
addr_data= &((struct sockaddr_in *)addr)->sin_addr;
else
addr_data= &((struct sockaddr_in6 *)addr)->sin6_addr;
if (!inet_ntop(addr->ss_family,addr_data, ip_string, sizeof(ip_string)))
{
DBUG_ASSERT(0);
return 1;
}
ip= ip_string;
}
my_free((void *)thd->main_security_ctx.ip);
if (!(thd->main_security_ctx.ip = my_strdup(ip, MYF(MY_WME))))
{
/*
No error accounting per IP in host_cache,
this is treated as a global server OOM error.
TODO: remove the need for my_strdup.
*/
statistic_increment(aborted_connects, &LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
return 1; /* The error is set by my_strdup(). */
}
thd->main_security_ctx.host_or_ip = thd->main_security_ctx.ip;
if (!(specialflag & SPECIAL_NO_RESOLVE))
{
int rc;
rc = ip_to_hostname(addr,
thd->main_security_ctx.ip,
&thd->main_security_ctx.host,
&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
if (thd->main_security_ctx.host)
{
if (thd->main_security_ctx.host != my_localhost)
((char*)thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host),
HOSTNAME_LENGTH)] = 0;
thd->main_security_ctx.host_or_ip = thd->main_security_ctx.host;
}
if (rc == RC_BLOCKED_HOST)
{
/* HOST_CACHE stats updated by ip_to_hostname(). */
my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
}
DBUG_PRINT("info", ("Host: %s ip: %s",
(thd->main_security_ctx.host ?
thd->main_security_ctx.host : "unknown host"),
(thd->main_security_ctx.ip ?
thd->main_security_ctx.ip : "unknown ip")));
if ((!check_proxy_networks || !is_proxy_protocol_allowed((struct sockaddr *) addr))
&& acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
{
/* HOST_CACHE stats updated by acl_check_host(). */
my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
thd->main_security_ctx.host_or_ip);
return 1;
}
return 0;
}
/*
Perform handshake, authorize client and update thd ACL variables.
@ -865,8 +949,9 @@ static int check_connection(THD *thd)
{
my_bool peer_rc;
char ip[NI_MAXHOST];
uint16 peer_port;
peer_rc= vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST);
peer_rc= vio_peer_addr(net->vio, ip, &peer_port, NI_MAXHOST);
/*
===========================================================================
@ -941,55 +1026,9 @@ static int check_connection(THD *thd)
my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
{
/*
No error accounting per IP in host_cache,
this is treated as a global server OOM error.
TODO: remove the need for my_strdup.
*/
statistic_increment(aborted_connects,&LOCK_status);
statistic_increment(connection_errors_internal, &LOCK_status);
return 1; /* The error is set by my_strdup(). */
}
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
if (!(specialflag & SPECIAL_NO_RESOLVE))
{
int rc;
rc= ip_to_hostname(&net->vio->remote,
thd->main_security_ctx.ip,
&thd->main_security_ctx.host,
&connect_errors);
/* Cut very long hostnames to avoid possible overflows */
if (thd->main_security_ctx.host)
{
if (thd->main_security_ctx.host != my_localhost)
((char*) thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host),
HOSTNAME_LENGTH)]= 0;
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
}
if (rc == RC_BLOCKED_HOST)
{
/* HOST_CACHE stats updated by ip_to_hostname(). */
my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
}
DBUG_PRINT("info",("Host: %s ip: %s",
(thd->main_security_ctx.host ?
thd->main_security_ctx.host : "unknown host"),
(thd->main_security_ctx.ip ?
thd->main_security_ctx.ip : "unknown ip")));
if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
{
/* HOST_CACHE stats updated by acl_check_host(). */
my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
thd->main_security_ctx.host_or_ip);
if (thd_set_peer_addr(thd, &net->vio->remote, ip, peer_port, true))
return 1;
}
}
else /* Hostname given means that the connection was on a socket */
{