Skip to content

Commit

Permalink
Merge pull request #4600 from sysown/v2.x_proxy
Browse files Browse the repository at this point in the history
Implementation of PROXY protocol V1
  • Loading branch information
renecannao authored Sep 2, 2024
2 parents cf9d5fe + 94b0da1 commit 3835029
Show file tree
Hide file tree
Showing 10 changed files with 787 additions and 46 deletions.
2 changes: 2 additions & 0 deletions include/MySQL_Data_Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "cpp.h"

#include "MySQL_Protocol.h"
#include "proxy_protocol_info.h"

#ifndef uchar
typedef unsigned char uchar;
Expand Down Expand Up @@ -140,6 +141,7 @@ class MySQL_Data_Stream
char *addr;
int port;
} proxy_addr;
ProxyProtocolInfo * PROXY_info;

unsigned int connect_tries;
int query_retries_on_failure;
Expand Down
1 change: 1 addition & 0 deletions include/MySQL_Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ class MySQL_Threads_Handler
char *server_version;
char *keep_multiplexing_variables;
char *default_authentication_plugin;
char *proxy_protocol_networks;
//unsigned int default_charset; // removed in 2.0.13 . Obsoleted previously using MySQL_Variables instead
int handle_unknown_charset;
int default_authentication_plugin_int;
Expand Down
51 changes: 51 additions & 0 deletions include/proxy_protocol_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef PROXY_PROTOCOL_INFO_H
#define PROXY_PROTOCOL_INFO_H

#include <string.h>
#include <netinet/in.h>
#include <string>
#include <arpa/inet.h>


class ProxyProtocolInfo {
public:
char source_address[INET6_ADDRSTRLEN+1];
char destination_address[INET6_ADDRSTRLEN+1];
char proxy_address[INET6_ADDRSTRLEN+1];
uint16_t source_port;
uint16_t destination_port;
uint16_t proxy_port;

// Constructor (initializes to zeros)
ProxyProtocolInfo() {
memset(this, 0, sizeof(ProxyProtocolInfo));
}

// Copy constructor
ProxyProtocolInfo(const ProxyProtocolInfo& other) {
memcpy(this, &other, sizeof(ProxyProtocolInfo));
}

// Function to parse the PROXY protocol header (declared)
bool parseProxyProtocolHeader(const char* packet, size_t packet_length);

bool is_in_network(const struct sockaddr* client_addr, const std::string& subnet_mask);
bool is_client_in_any_subnet(const struct sockaddr* client_addr, const char* subnet_list);

// Copy method
ProxyProtocolInfo& copy(const ProxyProtocolInfo& other) {
if (this != &other) {
memcpy(this, &other, sizeof(ProxyProtocolInfo));
}
return *this;
}
#ifdef DEBUG
sockaddr_in create_ipv4_addr(const std::string& ip);
sockaddr_in6 create_ipv6_addr(const std::string& ip);
void run_tests();
#endif // DEBUG
bool is_valid_subnet_list(const char* subnet_list);
bool is_valid_subnet(const char* subnet);
};

#endif // PROXY_PROTOCOL_INFO_H
2 changes: 2 additions & 0 deletions include/proxysql_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ __thread char *mysql_thread___default_schema;
__thread char *mysql_thread___server_version;
__thread char *mysql_thread___keep_multiplexing_variables;
__thread char *mysql_thread___default_authentication_plugin;
__thread char *mysql_thread___proxy_protocol_networks;
__thread char *mysql_thread___init_connect;
__thread char *mysql_thread___ldap_user_variable;
__thread char *mysql_thread___default_session_track_gtids;
Expand Down Expand Up @@ -954,6 +955,7 @@ extern __thread char *mysql_thread___default_schema;
extern __thread char *mysql_thread___server_version;
extern __thread char *mysql_thread___keep_multiplexing_variables;
extern __thread char *mysql_thread___default_authentication_plugin;
extern __thread char *mysql_thread___proxy_protocol_networks;
extern __thread char *mysql_thread___init_connect;
extern __thread char *mysql_thread___ldap_user_variable;
extern __thread char *mysql_thread___default_session_track_gtids;
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ _OBJ_CXX := ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo
QP_rule_text.oo QP_query_digest_stats.oo \
GTID_Server_Data.oo MyHGC.oo MySrvConnList.oo MySrvList.oo MySrvC.oo \
MySQL_encode.oo MySQL_ResultSet.oo \
proxy_protocol_info.oo \
proxysql_find_charset.oo ProxySQL_Poll.oo
OBJ_CXX := $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
HEADERS := ../include/*.h ../include/*.hpp
Expand Down
131 changes: 85 additions & 46 deletions lib/MySQL_Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ static char * mysql_thread_variables_names[]= {
(char *)"data_packets_history_size",
(char *)"handle_warnings",
(char *)"evaluate_replication_lag_on_servers_load",
(char *)"proxy_protocol_networks",
NULL
};

Expand Down Expand Up @@ -1119,6 +1120,7 @@ MySQL_Threads_Handler::MySQL_Threads_Handler() {
variables.ssl_p2s_crl=NULL;
variables.ssl_p2s_crlpath=NULL;
variables.keep_multiplexing_variables=strdup((char *)"tx_isolation,transaction_isolation,version");
variables.proxy_protocol_networks = strdup((char *)"");
variables.default_authentication_plugin=strdup((char *)"mysql_native_password");
variables.default_authentication_plugin_int = 0; // mysql_native_password
#ifdef DEBUG
Expand Down Expand Up @@ -1350,6 +1352,7 @@ char * MySQL_Threads_Handler::get_variable_string(char *name) {
if (!strcmp(name,"interfaces")) return strdup(variables.interfaces);
if (!strcmp(name,"keep_multiplexing_variables")) return strdup(variables.keep_multiplexing_variables);
if (!strcmp(name,"default_authentication_plugin")) return strdup(variables.default_authentication_plugin);
if (!strcmp(name,"proxy_protocol_networks")) return strdup(variables.proxy_protocol_networks);
// LCOV_EXCL_START
proxy_error("Not existing variable: %s\n", name); assert(0);
return NULL;
Expand Down Expand Up @@ -1505,6 +1508,7 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f
if (!strcasecmp(name,"default_schema")) return strdup(variables.default_schema);
if (!strcasecmp(name,"keep_multiplexing_variables")) return strdup(variables.keep_multiplexing_variables);
if (!strcasecmp(name,"default_authentication_plugin")) return strdup(variables.default_authentication_plugin);
if (!strcasecmp(name,"proxy_protocol_networks")) return strdup(variables.proxy_protocol_networks);
if (!strcasecmp(name,"interfaces")) return strdup(variables.interfaces);
if (!strcasecmp(name,"server_capabilities")) {
// FIXME : make it human readable
Expand Down Expand Up @@ -1878,6 +1882,28 @@ bool MySQL_Threads_Handler::set_variable(char *name, const char *value) { // thi
return false;
}
}
if (!strcasecmp(name,"proxy_protocol_networks")) {
bool ret = false;
if (vallen == 0) {
// accept empty string
ret = true;
} else if ( (vallen == 1) && strcmp(value,"*")==0) {
// accept `*`
ret = true;
} else {
ProxyProtocolInfo ppi;
if (ppi.is_valid_subnet_list(value) == true) {
ret = true;
}
}
if (ret == true) {
free(variables.proxy_protocol_networks);
variables.proxy_protocol_networks=strdup(value);
return true;
} else {
return true;
}
}
// SSL proxy to server variables
if (!strcasecmp(name,"ssl_p2s_ca")) {
if (variables.ssl_p2s_ca) free(variables.ssl_p2s_ca);
Expand Down Expand Up @@ -2707,6 +2733,7 @@ MySQL_Threads_Handler::~MySQL_Threads_Handler() {
if (variables.server_version) free(variables.server_version);
if (variables.keep_multiplexing_variables) free(variables.keep_multiplexing_variables);
if (variables.default_authentication_plugin) free(variables.default_authentication_plugin);
if (variables.proxy_protocol_networks) free(variables.proxy_protocol_networks);
if (variables.firewall_whitelist_errormsg) free(variables.firewall_whitelist_errormsg);
if (variables.init_connect) free(variables.init_connect);
if (variables.ldap_user_variable) free(variables.ldap_user_variable);
Expand Down Expand Up @@ -2838,6 +2865,7 @@ MySQL_Thread::~MySQL_Thread() {
if (mysql_thread___server_version) { free(mysql_thread___server_version); mysql_thread___server_version=NULL; }
if (mysql_thread___keep_multiplexing_variables) { free(mysql_thread___keep_multiplexing_variables); mysql_thread___keep_multiplexing_variables=NULL; }
if (mysql_thread___default_authentication_plugin) { free(mysql_thread___default_authentication_plugin); mysql_thread___default_authentication_plugin=NULL; }
if (mysql_thread___proxy_protocol_networks) { free(mysql_thread___proxy_protocol_networks); mysql_thread___proxy_protocol_networks=NULL; }
if (mysql_thread___firewall_whitelist_errormsg) { free(mysql_thread___firewall_whitelist_errormsg); mysql_thread___firewall_whitelist_errormsg=NULL; }
if (mysql_thread___init_connect) { free(mysql_thread___init_connect); mysql_thread___init_connect=NULL; }
if (mysql_thread___ldap_user_variable) { free(mysql_thread___ldap_user_variable); mysql_thread___ldap_user_variable=NULL; }
Expand Down Expand Up @@ -4381,6 +4409,7 @@ void MySQL_Thread::refresh_variables() {
GloMyLogger->audit_set_base_filename(); // both filename and filesize are set here
REFRESH_VARIABLE_CHAR(default_schema);
REFRESH_VARIABLE_CHAR(keep_multiplexing_variables);
REFRESH_VARIABLE_CHAR(proxy_protocol_networks);
REFRESH_VARIABLE_CHAR(default_authentication_plugin);
mysql_thread___default_authentication_plugin_int = GloMTH->variables.default_authentication_plugin_int;
mysql_thread___server_capabilities=GloMTH->get_variable_uint16((char *)"server_capabilities");
Expand Down Expand Up @@ -5087,30 +5116,40 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() {
}
}

if (sess->mirror==false) {
switch (sess->client_myds->client_addr->sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)sess->client_myds->client_addr;
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN);
pta[4] = strdup(buf);
sprintf(port, "%d", ntohs(ipv4->sin_port));
pta[5] = strdup(port);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)sess->client_myds->client_addr;
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN);
pta[4] = strdup(buf);
sprintf(port, "%d", ntohs(ipv6->sin6_port));
pta[5] = strdup(port);
break;
}
default:
pta[4] = strdup("localhost");
pta[5] = NULL;
break;
}
} else {
if (sess->mirror==false) {
switch (sess->client_myds->client_addr->sa_family) {
case AF_INET:
if (sess->client_myds->addr.addr != NULL) {
pta[4] = strdup(sess->client_myds->addr.addr);
sprintf(port, "%d", sess->client_myds->addr.port);
pta[5] = strdup(port);
} else {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)sess->client_myds->client_addr;
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN);
pta[4] = strdup(buf);
sprintf(port, "%d", ntohs(ipv4->sin_port));
pta[5] = strdup(port);
}
break;
case AF_INET6:
if (sess->client_myds->addr.addr != NULL) {
pta[4] = strdup(sess->client_myds->addr.addr);
sprintf(port, "%d", sess->client_myds->addr.port);
pta[5] = strdup(port);
} else {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)sess->client_myds->client_addr;
inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN);
pta[4] = strdup(buf);
sprintf(port, "%d", ntohs(ipv6->sin6_port));
pta[5] = strdup(port);
}
break;
default:
pta[4] = strdup("localhost");
pta[5] = NULL;
break;
}
} else {
pta[4] = strdup("mirror_internal");
pta[5] = NULL;
}
Expand All @@ -5126,28 +5165,28 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() {
int rc;
rc=getsockname(mc->fd, &addr, &addr_len);
if (rc==0) {
switch (addr.sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)&addr;
inet_ntop(addr.sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN);
pta[7] = strdup(buf);
sprintf(port, "%d", ntohs(ipv4->sin_port));
pta[8] = strdup(port);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&addr;
inet_ntop(addr.sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN);
pta[7] = strdup(buf);
sprintf(port, "%d", ntohs(ipv6->sin6_port));
pta[8] = strdup(port);
break;
}
default:
pta[7] = strdup("localhost");
pta[8] = NULL;
break;
}
switch (addr.sa_family) {
case AF_INET: {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)&addr;
inet_ntop(addr.sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN);
pta[7] = strdup(buf);
sprintf(port, "%d", ntohs(ipv4->sin_port));
pta[8] = strdup(port);
break;
}
case AF_INET6: {
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&addr;
inet_ntop(addr.sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN);
pta[7] = strdup(buf);
sprintf(port, "%d", ntohs(ipv6->sin6_port));
pta[8] = strdup(port);
break;
}
default:
pta[7] = strdup("localhost");
pta[8] = NULL;
break;
}
} else {
pta[7]=NULL;
pta[8]=NULL;
Expand Down
Loading

0 comments on commit 3835029

Please sign in to comment.