Added logic to ban IPv6 hosts
This commit is contained in:
parent
428ba970c1
commit
fb66e72a97
172
src/api.hpp
172
src/api.hpp
|
@ -1,46 +1,69 @@
|
||||||
|
|
||||||
Status FastnetmonApiServiceImpl::GetBanlist(::grpc::ServerContext* context,
|
Status FastnetmonApiServiceImpl::GetBanlist(::grpc::ServerContext* context,
|
||||||
const ::fastmitigation::BanListRequest* request,
|
const ::fastmitigation::BanListRequest* request,
|
||||||
::grpc::ServerWriter< ::fastmitigation::BanListReply>* writer) {
|
::grpc::ServerWriter< ::fastmitigation::BanListReply>* writer) {
|
||||||
logger << log4cpp::Priority::INFO << "API we asked for banlist";
|
logger << log4cpp::Priority::INFO << "API we asked for banlist";
|
||||||
|
|
||||||
for (std::map<uint32_t, banlist_item_t>::iterator itr = ban_list.begin(); itr != ban_list.end(); ++itr) {
|
for (std::map<uint32_t, banlist_item_t>::iterator itr = ban_list.begin(); itr != ban_list.end(); ++itr) {
|
||||||
std::string client_ip_as_string = convert_ip_as_uint_to_string(itr->first);
|
std::string client_ip_as_string = convert_ip_as_uint_to_string(itr->first);
|
||||||
|
|
||||||
BanListReply reply;
|
BanListReply reply;
|
||||||
reply.set_ip_address(client_ip_as_string + "/32");
|
reply.set_ip_address(client_ip_as_string + "/32");
|
||||||
writer->Write(reply);
|
writer->Write(reply);
|
||||||
}
|
|
||||||
|
|
||||||
// IPv6
|
|
||||||
std::map<subnet_ipv6_cidr_mask_t, banlist_item_t> ban_list_copy;
|
|
||||||
|
|
||||||
// Get whole ban list content atomically
|
|
||||||
ban_list_ipv6_ng.get_whole_banlist(ban_list_copy);
|
|
||||||
|
|
||||||
|
|
||||||
for (auto itr : ban_list_copy) {
|
|
||||||
BanListReply reply;
|
|
||||||
reply.set_ip_address( print_ipv6_cidr_subnet(itr.first) );
|
|
||||||
writer->Write(reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
std::map<subnet_ipv6_cidr_mask_t, banlist_item_t> ban_list_copy;
|
||||||
|
|
||||||
|
// Get whole ban list content atomically
|
||||||
|
ban_list_ipv6_ng.get_whole_banlist(ban_list_copy);
|
||||||
|
|
||||||
|
|
||||||
|
for (auto itr : ban_list_copy) {
|
||||||
|
BanListReply reply;
|
||||||
|
reply.set_ip_address( print_ipv6_cidr_subnet(itr.first) );
|
||||||
|
writer->Write(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
Status FastnetmonApiServiceImpl::ExecuteBan(ServerContext* context,
|
Status FastnetmonApiServiceImpl::ExecuteBan(ServerContext* context,
|
||||||
const fastmitigation::ExecuteBanRequest* request,
|
const fastmitigation::ExecuteBanRequest* request,
|
||||||
fastmitigation::ExecuteBanReply* reply) {
|
fastmitigation::ExecuteBanReply* reply) {
|
||||||
logger << log4cpp::Priority::INFO << "API we asked for ban for IP: " << request->ip_address();
|
logger << log4cpp::Priority::INFO << "API we asked for ban for IP: " << request->ip_address();
|
||||||
|
|
||||||
if (!is_v4_host(request->ip_address())) {
|
if (!validate_ipv6_or_ipv4_host(request->ip_address())) {
|
||||||
logger << log4cpp::Priority::ERROR << "IP bad format";
|
logger << log4cpp::Priority::ERROR << "You specified malformed IP address";
|
||||||
return Status::CANCELLED;
|
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Malformed IP address");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t client_ip = convert_ip_as_string_to_uint(request->ip_address());
|
// At this step IP should be valid IPv4 or IPv6 address
|
||||||
|
bool ipv6 = false;
|
||||||
|
|
||||||
|
if (request->ip_address().find(":") != std::string::npos) {
|
||||||
|
ipv6 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ipv4 = !ipv6;
|
||||||
|
|
||||||
|
uint32_t client_ip = 0;
|
||||||
|
|
||||||
|
subnet_ipv6_cidr_mask_t ipv6_address;
|
||||||
|
ipv6_address.cidr_prefix_length = 128;
|
||||||
|
|
||||||
|
attack_details_t current_attack;
|
||||||
|
current_attack.ipv6 = ipv6;
|
||||||
|
|
||||||
|
boost::circular_buffer<simple_packet_t> empty_simple_packets_buffer;
|
||||||
|
|
||||||
|
std::string flow_attack_details = "manually triggered attack";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ipv4) {
|
||||||
|
client_ip = convert_ip_as_string_to_uint(request->ip_address());
|
||||||
|
|
||||||
attack_details_t current_attack;
|
|
||||||
ban_list_mutex.lock();
|
ban_list_mutex.lock();
|
||||||
ban_list[client_ip] = current_attack;
|
ban_list[client_ip] = current_attack;
|
||||||
ban_list_mutex.unlock();
|
ban_list_mutex.unlock();
|
||||||
|
@ -48,48 +71,59 @@
|
||||||
ban_list_details_mutex.lock();
|
ban_list_details_mutex.lock();
|
||||||
ban_list_details[client_ip] = std::vector<simple_packet_t>();
|
ban_list_details[client_ip] = std::vector<simple_packet_t>();
|
||||||
ban_list_details_mutex.unlock();
|
ban_list_details_mutex.unlock();
|
||||||
|
} else {
|
||||||
|
bool parsed_ipv6 = read_ipv6_host_from_string(request->ip_address(), ipv6_address.subnet_address);
|
||||||
|
|
||||||
|
if (!parsed_ipv6) {
|
||||||
subnet_ipv6_cidr_mask_t zero_ipv6_address;
|
logger << log4cpp::Priority::ERROR << "Can't parse IPv6 address: " << request->ip_address();
|
||||||
boost::circular_buffer<simple_packet_t> empty_simple_packets_buffer;
|
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Can't parse IPv6 address");
|
||||||
|
|
||||||
logger << log4cpp::Priority::INFO << "API call ban handlers manually";
|
|
||||||
|
|
||||||
std::string flow_attack_details = "manually triggered attack";
|
|
||||||
call_ban_handlers(client_ip, zero_ipv6_address, false, current_attack, flow_attack_details, attack_detection_source_t::Automatic, "", empty_simple_packets_buffer);
|
|
||||||
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status FastnetmonApiServiceImpl::ExecuteUnBan(ServerContext* context,
|
|
||||||
const fastmitigation::ExecuteBanRequest* request,
|
|
||||||
fastmitigation::ExecuteBanReply* reply) {
|
|
||||||
logger << log4cpp::Priority::INFO << "API: We asked for unban for IP: " << request->ip_address();
|
|
||||||
|
|
||||||
if (!is_v4_host(request->ip_address())) {
|
|
||||||
logger << log4cpp::Priority::ERROR << "IP bad format";
|
|
||||||
return Status::CANCELLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t banned_ip = convert_ip_as_string_to_uint(request->ip_address());
|
bool in_our_networks_list = ip_belongs_to_patricia_tree_ipv6(lookup_tree_ipv6, ipv6_address.subnet_address);
|
||||||
|
|
||||||
if (ban_list.count(banned_ip) == 0) {
|
if (!in_our_networks_list) {
|
||||||
logger << log4cpp::Priority::ERROR << "API: Could not find IP in ban list";
|
logger << log4cpp::Priority::ERROR << "IP address " << request->ip_address() << " is not belongs to our networks.";
|
||||||
return Status::CANCELLED;
|
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "This IP not belongs to our subnets");
|
||||||
}
|
}
|
||||||
|
|
||||||
banlist_item_t ban_details = ban_list[banned_ip];
|
ban_list_ipv6_ng.add_to_blackhole(ipv6_address, current_attack);
|
||||||
|
|
||||||
logger << log4cpp::Priority::INFO << "API: call unban handlers";
|
|
||||||
|
|
||||||
subnet_ipv6_cidr_mask_t zero_ipv6_address;
|
|
||||||
call_unban_handlers(banned_ip, zero_ipv6_address, false, ban_details, attack_detection_source_t::Automatic);
|
|
||||||
|
|
||||||
logger << log4cpp::Priority::INFO << "API: remove IP from ban list";
|
|
||||||
|
|
||||||
ban_list_mutex.lock();
|
|
||||||
ban_list.erase(banned_ip);
|
|
||||||
ban_list_mutex.unlock();
|
|
||||||
|
|
||||||
return Status::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger << log4cpp::Priority::INFO << "API call ban handlers manually";
|
||||||
|
call_ban_handlers(client_ip, ipv6_address, ipv6, current_attack, flow_attack_details, attack_detection_source_t::Automatic, "", empty_simple_packets_buffer);
|
||||||
|
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FastnetmonApiServiceImpl::ExecuteUnBan(ServerContext* context,
|
||||||
|
const fastmitigation::ExecuteBanRequest* request,
|
||||||
|
fastmitigation::ExecuteBanReply* reply) {
|
||||||
|
logger << log4cpp::Priority::INFO << "API: We asked for unban for IP: " << request->ip_address();
|
||||||
|
|
||||||
|
if (!is_v4_host(request->ip_address())) {
|
||||||
|
logger << log4cpp::Priority::ERROR << "IP bad format";
|
||||||
|
return Status::CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t banned_ip = convert_ip_as_string_to_uint(request->ip_address());
|
||||||
|
|
||||||
|
if (ban_list.count(banned_ip) == 0) {
|
||||||
|
logger << log4cpp::Priority::ERROR << "API: Could not find IP in ban list";
|
||||||
|
return Status::CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
banlist_item_t ban_details = ban_list[banned_ip];
|
||||||
|
|
||||||
|
logger << log4cpp::Priority::INFO << "API: call unban handlers";
|
||||||
|
|
||||||
|
subnet_ipv6_cidr_mask_t zero_ipv6_address;
|
||||||
|
call_unban_handlers(banned_ip, zero_ipv6_address, false, ban_details, attack_detection_source_t::Automatic);
|
||||||
|
|
||||||
|
logger << log4cpp::Priority::INFO << "API: remove IP from ban list";
|
||||||
|
|
||||||
|
ban_list_mutex.lock();
|
||||||
|
ban_list.erase(banned_ip);
|
||||||
|
ban_list_mutex.unlock();
|
||||||
|
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
|
@ -1471,3 +1471,20 @@ bool read_ipv6_host_from_string(std::string ipv6_host_as_string, in6_addr& resul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validates IPv4 or IPv6 address in host form:
|
||||||
|
// 127.0.0.1 or ::1
|
||||||
|
bool validate_ipv6_or_ipv4_host(const std::string host) {
|
||||||
|
// Validate host address
|
||||||
|
boost::system::error_code ec;
|
||||||
|
|
||||||
|
// Try to build it from string representation
|
||||||
|
auto parsed_ip_address = boost::asio::ip::address::from_string(host, ec);
|
||||||
|
|
||||||
|
// If we failed to parse it
|
||||||
|
if (ec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,3 +122,4 @@ bool set_boost_process_name(boost::thread* thread, std::string process_name);
|
||||||
std::string convert_any_ip_to_string(subnet_ipv6_cidr_mask_t subnet);
|
std::string convert_any_ip_to_string(subnet_ipv6_cidr_mask_t subnet);
|
||||||
bool convert_string_to_positive_integer_safe(std::string line, int& value);
|
bool convert_string_to_positive_integer_safe(std::string line, int& value);
|
||||||
bool read_ipv6_host_from_string(std::string ipv6_host_as_string, in6_addr& result);
|
bool read_ipv6_host_from_string(std::string ipv6_host_as_string, in6_addr& result);
|
||||||
|
bool validate_ipv6_or_ipv4_host(const std::string host);
|
||||||
|
|
|
@ -42,7 +42,7 @@ class FastnetmonClient {
|
||||||
std::cerr << "Could not connect to API server. Timeout exceed" << std::endl;
|
std::cerr << "Could not connect to API server. Timeout exceed" << std::endl;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "RPC failed " + status.error_message() << std::endl;
|
std::cerr << "Query failed " + status.error_message() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ class FastnetmonClient {
|
||||||
std::cerr << "Could not connect to API server. Timeout exceed" << std::endl;
|
std::cerr << "Could not connect to API server. Timeout exceed" << std::endl;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "RPC failed " + status.error_message() << std::endl;
|
std::cerr << "Query failed " + status.error_message() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue