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:
@ -295,6 +295,16 @@ private:
|
|||||||
*/
|
*/
|
||||||
void accept_connections();
|
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
|
* The file descriptor for accepting new connections
|
||||||
*
|
*
|
||||||
|
@ -167,7 +167,18 @@ struct MXS_PROTOCOL
|
|||||||
*
|
*
|
||||||
* @return JSON representation of the DCB
|
* @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
|
* the MXS_PROTOCOL structure is changed. See the rules defined in modinfo.h
|
||||||
* that define how these numbers should change.
|
* 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.
|
* 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);
|
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)
|
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;
|
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()
|
void Listener::accept_connections()
|
||||||
{
|
{
|
||||||
for (ClientConn conn = accept_one_connection(fd()); conn.fd != -1; conn = accept_one_connection(fd()))
|
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))
|
if (DCB* dcb = accept_one_dcb(conn.fd, &conn.addr, conn.host))
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
#include <maxscale/authenticator.hh>
|
#include <maxscale/authenticator.hh>
|
||||||
@ -80,6 +81,8 @@ static spec_com_res_t handle_query_kill(DCB* dcb,
|
|||||||
unsigned int packet_len);
|
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 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 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
|
* The module entry point routine. It is this routine that
|
||||||
* must populate the structure that is referred to as the
|
* must populate the structure that is referred to as the
|
||||||
@ -88,12 +91,8 @@ static void parse_and_set_trx_state(MXS_SESSION* ses, GWBUF* data);
|
|||||||
*
|
*
|
||||||
* @return The module object
|
* @return The module object
|
||||||
*/
|
*/
|
||||||
|
extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
||||||
extern "C"
|
|
||||||
{
|
{
|
||||||
|
|
||||||
MXS_MODULE* MXS_CREATE_MODULE()
|
|
||||||
{
|
|
||||||
static MXS_PROTOCOL MyObject =
|
static MXS_PROTOCOL MyObject =
|
||||||
{
|
{
|
||||||
gw_read_client_event, /* Read - EPOLLIN handler */
|
gw_read_client_event, /* Read - EPOLLIN handler */
|
||||||
@ -108,7 +107,8 @@ extern "C"
|
|||||||
gw_default_auth, /* Default authenticator */
|
gw_default_auth, /* Default authenticator */
|
||||||
gw_connection_limit, /* Send error connection limit */
|
gw_connection_limit, /* Send error connection limit */
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL,
|
||||||
|
gw_reject_connection
|
||||||
};
|
};
|
||||||
|
|
||||||
static MXS_MODULE info =
|
static MXS_MODULE info =
|
||||||
@ -130,7 +130,6 @@ extern "C"
|
|||||||
};
|
};
|
||||||
|
|
||||||
return &info;
|
return &info;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*lint +e14 */
|
/*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("trx state:%s", session_trx_state_to_string(ses->trx_state));
|
||||||
MXS_DEBUG("autcommit:%s", session_is_autocommit(ses) ? "ON" : "OFF");
|
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());
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user