MXS-2414: Send error when host is blocked
If a connection attempt is not accepted due to the host being blocked, the protocol can now return an error message that is sent to the client. Only mariadb_client implements this as it is the only one who calls the auth failure methods in the first place.
This commit is contained in:
parent
db0e491ace
commit
6caa8e55b0
@ -295,6 +295,16 @@ private:
|
||||
*/
|
||||
void accept_connections();
|
||||
|
||||
/**
|
||||
* Reject a client connection
|
||||
*
|
||||
* Writes an error message to the fd if the protocol supports it and then closes it.
|
||||
*
|
||||
* @param fd The file descriptor to close
|
||||
* @param host The host where the connection originated from
|
||||
*/
|
||||
void reject_connection(int fd, const char* host);
|
||||
|
||||
/**
|
||||
* The file descriptor for accepting new connections
|
||||
*
|
||||
|
@ -167,7 +167,18 @@ struct MXS_PROTOCOL
|
||||
*
|
||||
* @return JSON representation of the DCB
|
||||
*/
|
||||
json_t* (*diagnostics_json)(DCB * dcb);
|
||||
json_t* (* diagnostics_json)(DCB* dcb);
|
||||
|
||||
/**
|
||||
* Get rejection message
|
||||
*
|
||||
* The protocol should return an error indicating that access to MaxScale has been temporarily suspended.
|
||||
*
|
||||
* @param host The host that is blocked
|
||||
*
|
||||
* @return A buffer containing the error message
|
||||
*/
|
||||
GWBUF* (* reject)(const char* host);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -175,7 +186,7 @@ struct MXS_PROTOCOL
|
||||
* the MXS_PROTOCOL structure is changed. See the rules defined in modinfo.h
|
||||
* that define how these numbers should change.
|
||||
*/
|
||||
#define MXS_PROTOCOL_VERSION {2, 0, 0}
|
||||
#define MXS_PROTOCOL_VERSION {2, 1, 0}
|
||||
|
||||
/**
|
||||
* Specifies capabilities specific for protocol.
|
||||
|
@ -1022,12 +1022,6 @@ static ClientConn accept_one_connection(int fd)
|
||||
}
|
||||
|
||||
configure_network_socket(conn.fd, conn.addr.ss_family);
|
||||
|
||||
if (rate_limit.is_blocked(conn.host))
|
||||
{
|
||||
close(conn.fd);
|
||||
conn.fd = -1;
|
||||
}
|
||||
}
|
||||
else if (errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
@ -1211,11 +1205,33 @@ uint32_t Listener::poll_handler(MXB_POLL_DATA* data, MXB_WORKER* worker, uint32_
|
||||
return MXB_POLL_ACCEPT;
|
||||
}
|
||||
|
||||
void Listener::reject_connection(int fd, const char* host)
|
||||
{
|
||||
if (m_proto_func.reject)
|
||||
{
|
||||
if (GWBUF* buf = m_proto_func.reject(host))
|
||||
{
|
||||
for (auto b = buf; b; b = b->next)
|
||||
{
|
||||
write(fd, GWBUF_DATA(b), GWBUF_LENGTH(b));
|
||||
}
|
||||
gwbuf_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void Listener::accept_connections()
|
||||
{
|
||||
for (ClientConn conn = accept_one_connection(fd()); conn.fd != -1; conn = accept_one_connection(fd()))
|
||||
{
|
||||
if (type() == Type::UNIQUE_TCP)
|
||||
|
||||
if (rate_limit.is_blocked(conn.host))
|
||||
{
|
||||
reject_connection(conn.fd, conn.host);
|
||||
}
|
||||
else if (type() == Type::UNIQUE_TCP)
|
||||
{
|
||||
if (DCB* dcb = accept_one_dcb(conn.fd, &conn.addr, conn.host))
|
||||
{
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/authenticator.hh>
|
||||
@ -78,8 +79,10 @@ static spec_com_res_t handle_query_kill(DCB* dcb,
|
||||
spec_com_res_t current,
|
||||
bool is_complete,
|
||||
unsigned int packet_len);
|
||||
static bool parse_kill_query(char* query, uint64_t* thread_id_out, kill_type_t* kt_out, std::string* user);
|
||||
static void parse_and_set_trx_state(MXS_SESSION* ses, GWBUF* data);
|
||||
static bool parse_kill_query(char* query, uint64_t* thread_id_out, kill_type_t* kt_out, std::string* user);
|
||||
static void parse_and_set_trx_state(MXS_SESSION* ses, GWBUF* data);
|
||||
static GWBUF* gw_reject_connection(const char* host);
|
||||
|
||||
/**
|
||||
* The module entry point routine. It is this routine that
|
||||
* must populate the structure that is referred to as the
|
||||
@ -88,49 +91,45 @@ static void parse_and_set_trx_state(MXS_SESSION* ses, GWBUF* data);
|
||||
*
|
||||
* @return The module object
|
||||
*/
|
||||
|
||||
extern "C"
|
||||
extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
||||
{
|
||||
|
||||
MXS_MODULE* MXS_CREATE_MODULE()
|
||||
static MXS_PROTOCOL MyObject =
|
||||
{
|
||||
static MXS_PROTOCOL MyObject =
|
||||
{
|
||||
gw_read_client_event, /* Read - EPOLLIN handler */
|
||||
gw_MySQLWrite_client, /* Write - data from gateway */
|
||||
gw_write_client_event, /* WriteReady - EPOLLOUT handler */
|
||||
gw_error_client_event, /* Error - EPOLLERR handler */
|
||||
gw_client_hangup_event, /* HangUp - EPOLLHUP handler */
|
||||
gw_MySQLAccept, /* Accept */
|
||||
NULL, /* Connect */
|
||||
gw_client_close, /* Close */
|
||||
NULL, /* Authentication */
|
||||
gw_default_auth, /* Default authenticator */
|
||||
gw_connection_limit, /* Send error connection limit */
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
gw_read_client_event, /* Read - EPOLLIN handler */
|
||||
gw_MySQLWrite_client, /* Write - data from gateway */
|
||||
gw_write_client_event, /* WriteReady - EPOLLOUT handler */
|
||||
gw_error_client_event, /* Error - EPOLLERR handler */
|
||||
gw_client_hangup_event, /* HangUp - EPOLLHUP handler */
|
||||
gw_MySQLAccept, /* Accept */
|
||||
NULL, /* Connect */
|
||||
gw_client_close, /* Close */
|
||||
NULL, /* Authentication */
|
||||
gw_default_auth, /* Default authenticator */
|
||||
gw_connection_limit, /* Send error connection limit */
|
||||
NULL,
|
||||
NULL,
|
||||
gw_reject_connection
|
||||
};
|
||||
|
||||
static MXS_MODULE info =
|
||||
static MXS_MODULE info =
|
||||
{
|
||||
MXS_MODULE_API_PROTOCOL,
|
||||
MXS_MODULE_GA,
|
||||
MXS_PROTOCOL_VERSION,
|
||||
"The client to MaxScale MySQL protocol implementation",
|
||||
"V1.1.0",
|
||||
MXS_NO_MODULE_CAPABILITIES,
|
||||
&MyObject,
|
||||
process_init,
|
||||
process_finish,
|
||||
thread_init,
|
||||
thread_finish,
|
||||
{
|
||||
MXS_MODULE_API_PROTOCOL,
|
||||
MXS_MODULE_GA,
|
||||
MXS_PROTOCOL_VERSION,
|
||||
"The client to MaxScale MySQL protocol implementation",
|
||||
"V1.1.0",
|
||||
MXS_NO_MODULE_CAPABILITIES,
|
||||
&MyObject,
|
||||
process_init,
|
||||
process_finish,
|
||||
thread_init,
|
||||
thread_finish,
|
||||
{
|
||||
{MXS_END_MODULE_PARAMS}
|
||||
}
|
||||
};
|
||||
{MXS_END_MODULE_PARAMS}
|
||||
}
|
||||
};
|
||||
|
||||
return &info;
|
||||
}
|
||||
return &info;
|
||||
}
|
||||
/*lint +e14 */
|
||||
|
||||
@ -2122,3 +2121,10 @@ static void parse_and_set_trx_state(MXS_SESSION* ses, GWBUF* data)
|
||||
MXS_DEBUG("trx state:%s", session_trx_state_to_string(ses->trx_state));
|
||||
MXS_DEBUG("autcommit:%s", session_is_autocommit(ses) ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
static GWBUF* gw_reject_connection(const char* host)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Host '" << host << "' is temporarily blocked due to too many authentication failures.";
|
||||
return modutil_create_mysql_err_msg(0, 0, 1129, "HY000", ss.str().c_str());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user