Skip to content

Commit

Permalink
[libfscp/libfreelan] Adds also limit per endpoint for HELLO messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
s-vincent committed Dec 18, 2018
1 parent 590ccd8 commit 64ab23e
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 12 deletions.
6 changes: 3 additions & 3 deletions apps/freelan/config/freelan.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,12 @@ public_endpoint=0.0.0.0
# Default: yes
#upnp_enabled=yes

# Maximum PRESENTATION message from one host allowed per second.
# Maximum unauthenticated messages from one host allowed per second.
#
# This is a way to mitigates PRESENTATION flood attack.
# This is a way to mitigates HELLO/PRESENTATION flood attack.
#
# Default: 1
#max_presentation_per_second=1
#max_unauthenticated_messages_per_second=1

[tap_adapter]

Expand Down
4 changes: 2 additions & 2 deletions apps/freelan/src/configuration_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ po::options_description get_fscp_options()
("fscp.cipher_suite_capability", po::value<std::vector<fscp::cipher_suite_type> >()->multitoken()->zero_tokens()->default_value(fscp::get_default_cipher_suites(), ""), "A cipher suite to allow.")
("fscp.elliptic_curve_capability", po::value<std::vector<fscp::elliptic_curve_type> >()->multitoken()->zero_tokens()->default_value(fscp::get_default_elliptic_curves(), ""), "A elliptic curve to allow.")
("fscp.upnp_enabled", po::value<bool>()->default_value(true, "yes"), "Enable UPnP.")
("fscp.max_presentation_per_second", po::value<size_t>()->default_value(1, "1"), "Maximum PRESENTATION message from one host per second.")
("fscp.max_unauthenticated_messages_per_second", po::value<size_t>()->default_value(1, "1"), "Maximum unauthenticated messages from one host per second.")
;

return result;
Expand Down Expand Up @@ -465,7 +465,7 @@ void setup_configuration(const fscp::logger& logger, fl::configuration& configur
configuration.fscp.cipher_suite_capabilities = vm["fscp.cipher_suite_capability"].as<std::vector<fscp::cipher_suite_type>>();
configuration.fscp.elliptic_curve_capabilities = vm["fscp.elliptic_curve_capability"].as<std::vector<fscp::elliptic_curve_type>>();
configuration.fscp.upnp_enabled = vm["fscp.upnp_enabled"].as<bool>();
configuration.fscp.max_presentation_per_second = vm["fscp.max_presentation_per_second"].as<size_t>();
configuration.fscp.max_unauthenticated_messages_per_second = vm["fscp.max_unauthenticated_messages_per_second"].as<size_t>();

// Security options
const std::string passphrase = vm["security.passphrase"].as<std::string>();
Expand Down
4 changes: 2 additions & 2 deletions libs/freelan/include/freelan/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,9 @@ namespace freelan
bool upnp_enabled;

/*
* \brief Maximum PRESENTATION message from one host per second.
* \brief Maximum HELLO/PRESENTATION message from one host per second.
*/
size_t max_presentation_per_second;
size_t max_unauthenticated_messages_per_second;
};

/**
Expand Down
3 changes: 2 additions & 1 deletion libs/freelan/src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,8 @@ namespace freelan
{
m_fscp_server->set_cipher_suites(m_configuration.fscp.cipher_suite_capabilities);
m_fscp_server->set_elliptic_curves(m_configuration.fscp.elliptic_curve_capabilities);
m_fscp_server->set_presentation_max_per_second(m_configuration.fscp.max_presentation_per_second);
m_fscp_server->set_hello_max_per_second(m_configuration.fscp.max_unauthenticated_messages_per_second);
m_fscp_server->set_presentation_max_per_second(m_configuration.fscp.max_unauthenticated_messages_per_second);

m_fscp_server->set_hello_message_received_callback(boost::bind(&core::do_handle_hello_received, this, _1, _2));
m_fscp_server->set_contact_request_received_callback(boost::bind(&core::do_handle_contact_request_received, this, _1, _2, _3, _4));
Expand Down
34 changes: 32 additions & 2 deletions libs/fscp/include/fscp/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,15 @@ namespace fscp
m_hello_message_received_handler = callback;
}

/**
* \brief Set maximum hello message from one host per second.
* \param max_per_second value to set.
*/
void set_hello_max_per_second(size_t max_per_second)
{
m_hello_max_per_second = max_per_second;
}

/**
* \brief Set the hello message received callback.
* \param callback The callback.
Expand Down Expand Up @@ -1413,6 +1422,12 @@ namespace fscp
void do_set_accept_hello_messages_default(bool, void_handler_type);
void do_set_hello_message_received_callback(hello_message_received_handler_type, void_handler_type);

/**
* \brief Reset hello limit.
* \param ec error code.
*/
void do_hello_reset_limit(const boost::system::error_code& ec);

ep_hello_context_map m_ep_hello_contexts;
#if BOOST_ASIO_VERSION >= 101200 // Boost 1.66+
boost::asio::io_context::strand m_greet_strand;
Expand All @@ -1422,6 +1437,21 @@ namespace fscp
bool m_accept_hello_messages_default;
hello_message_received_handler_type m_hello_message_received_handler;

/**
* \brief Current number of session request sent per endpoint.
*/
std::map<ep_type, size_t> m_hello_requests_map;

/**
* \brief Timer for reesting hello requests limit.
*/
boost::asio::deadline_timer m_hello_limit_timer;

/**
* \brief Maximum hello message from one host per second.
*/
size_t m_hello_max_per_second;

private: // PRESENTATION messages

typedef std::map<ep_type, presentation_store> presentation_store_map;
Expand All @@ -1435,14 +1465,14 @@ namespace fscp
void handle_presentation_message_from(const identity_store&, const presentation_message&, const ep_type&);
void do_handle_presentation(const identity_store& identity, const ep_type&, bool, cert_type);

void do_set_presentation_message_received_callback(presentation_message_received_handler_type, void_handler_type);

/**
* \brief Reset presentation limit.
* \param ec error code.
*/
void do_presentation_reset_limit(const boost::system::error_code& ec);

void do_set_presentation_message_received_callback(presentation_message_received_handler_type, void_handler_type);

// This strand is also used by session requests and session messages during the cipherment/decipherment phase.
#if BOOST_ASIO_VERSION >= 101200 // Boost 1.66+
boost::asio::io_context::strand m_presentation_strand;
Expand Down
41 changes: 39 additions & 2 deletions libs/fscp/src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ namespace fscp
m_greet_strand(io_service),
m_accept_hello_messages_default(true),
m_hello_message_received_handler(),
m_hello_limit_timer(io_service, boost::posix_time::seconds(10)),
m_hello_max_per_second(1),
m_presentation_strand(io_service),
m_presentation_message_received_handler(),
m_presentation_limit_timer(io_service, boost::posix_time::seconds(10)),
Expand Down Expand Up @@ -320,6 +322,7 @@ namespace fscp

m_keep_alive_timer.cancel();

m_hello_limit_timer.cancel();
m_presentation_limit_timer.cancel();

m_socket.close();
Expand Down Expand Up @@ -1255,6 +1258,27 @@ namespace fscp
void server::do_handle_hello_request(const ep_type& sender, uint32_t hello_unique_number)
{
// All do_handle_hello_request() calls are done in the same strand so the following is thread-safe.
std::map<ep_type, size_t>::iterator sender_hello = m_hello_requests_map.find(sender);

if(sender_hello == m_hello_requests_map.end())
{
// new hello
m_hello_requests_map[sender] = 1;
}
else if(m_hello_requests_map[sender] >= (m_hello_max_per_second * 10))
{
// in 10s we have reach limits! Presentation flood?
m_logger(log_level::warning) <<
"Received too many HELLO messages from " << sender <<
", limit is " << (m_hello_max_per_second * 10) <<
" messages per 10 seconds";
return;
}
else
{
m_hello_requests_map[sender]++;
}

bool can_reply = m_accept_hello_messages_default;

if (m_hello_message_received_handler)
Expand Down Expand Up @@ -1295,6 +1319,21 @@ namespace fscp
}
}

void server::do_hello_reset_limit(const boost::system::error_code& ec)
{
// All do_hello_reset_limit calls are done in the same strand so the following is thread-safe.
if (ec != boost::asio::error::operation_aborted)
{
m_hello_requests_map.clear();

// rearm timer again
m_hello_limit_timer.expires_from_now(boost::posix_time::seconds(10));
m_hello_limit_timer.async_wait(m_greet_strand.wrap(
boost::bind(&server::do_hello_reset_limit, this,
boost::asio::placeholders::error)));
}
}

void server::do_set_hello_message_received_callback(hello_message_received_handler_type callback, void_handler_type handler)
{
// All do_set_hello_message_received_callback() calls are done in the same strand so the following is thread-safe.
Expand Down Expand Up @@ -1422,7 +1461,6 @@ namespace fscp
void server::do_handle_presentation(const identity_store& identity, const ep_type& sender, bool has_session, cert_type signature_certificate)
{
// All do_handle_presentation() calls are done in the same strand so the following is thread-safe.

std::map<ep_type, size_t>::iterator sender_presentation = m_presentation_requests_map.find(sender);

if(sender_presentation == m_presentation_requests_map.end())
Expand All @@ -1437,7 +1475,6 @@ namespace fscp
"Received too many PRESENTATION messages from " << sender <<
", limit is " << (m_presentation_max_per_second * 10) <<
" messages per 10 seconds";

return;
}
else
Expand Down

0 comments on commit 64ab23e

Please sign in to comment.