Skip to content

Commit

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

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

[tap_adapter]

# The tap adapter type.
Expand Down
3 changes: 3 additions & 0 deletions apps/freelan/src/configuration_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +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.")
;

return result;
Expand Down Expand Up @@ -463,6 +464,8 @@ void setup_configuration(const fscp::logger& logger, fl::configuration& configur
configuration.fscp.never_contact_list = vm["fscp.never_contact"].as<std::vector<asiotap::ip_network_address>>();
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>();

// Security options
const std::string passphrase = vm["security.passphrase"].as<std::string>();
Expand Down
5 changes: 5 additions & 0 deletions libs/freelan/include/freelan/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ namespace freelan
* \brief State of UPnP.
*/
bool upnp_enabled;

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

/**
Expand Down
1 change: 1 addition & 0 deletions libs/freelan/src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ 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_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
17 changes: 13 additions & 4 deletions libs/fscp/include/fscp/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,15 @@ namespace fscp
m_presentation_message_received_handler = callback;
}

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

/**
* \brief Set the presentation message received callback.
* \param callback The callback.
Expand Down Expand Up @@ -1444,19 +1453,19 @@ namespace fscp
presentation_message_received_handler_type m_presentation_message_received_handler;

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

/**
* \brief Timer for reesting presentation requests limit.
*/
boost::asio::deadline_timer m_presentation_limit_timer;

/**
* \brief maximum number of session request.
* \brief Maximum presentation message from one host per second.
*/
static const size_t MAX_PRESENTATION_REQUESTS;
size_t m_presentation_max_per_second;

private: // SESSION_REQUEST messages

Expand Down
27 changes: 19 additions & 8 deletions libs/fscp/src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,6 @@ namespace fscp
}
}

const size_t server::MAX_PRESENTATION_REQUESTS = 512;

// Public methods

server::server(boost::asio::io_service& io_service, fscp::logger& _logger, const identity_store& identity) :
Expand All @@ -229,8 +227,8 @@ namespace fscp
m_hello_message_received_handler(),
m_presentation_strand(io_service),
m_presentation_message_received_handler(),
m_presentation_requests(0),
m_presentation_limit_timer(io_service, boost::posix_time::seconds(10)),
m_presentation_max_per_second(1),
m_session_strand(io_service),
m_accept_session_request_messages_default(true),
m_cipher_suites(get_default_cipher_suites()),
Expand Down Expand Up @@ -1424,15 +1422,28 @@ 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.
if(m_presentation_requests <= MAX_PRESENTATION_REQUESTS)

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

if(sender_presentation == m_presentation_requests_map.end())
{
m_presentation_requests++;
// new presentation
m_presentation_requests_map[sender] = 1;
}
else
else if(m_presentation_requests_map[sender] >= (m_presentation_max_per_second * 10))
{
// presentation flood?
// in 10s we have reach limits! Presentation flood?
m_logger(log_level::warning) <<
"Received too many PRESENTATION messages from " << sender <<
", limit is " << (m_presentation_max_per_second * 10) <<
" messages per 10 seconds";

return;
}
else
{
m_presentation_requests_map[sender]++;
}

presentation_status_type presentation_status = PS_FIRST;

Expand Down Expand Up @@ -1466,7 +1477,7 @@ namespace fscp
// All do_presentation_reset_limit calls are done in the same strand so the following is thread-safe.
if (ec != boost::asio::error::operation_aborted)
{
m_presentation_requests = 0;
m_presentation_requests_map.clear();

// rearm timer again
m_presentation_limit_timer.expires_from_now(boost::posix_time::seconds(10));
Expand Down

0 comments on commit 590ccd8

Please sign in to comment.