swad-core/swad_firewall.c

117 lines
4.3 KiB
C
Raw Normal View History

2019-03-27 14:36:57 +01:00
// swad_firewall.c: firewall to mitigate denial of service attacks
2019-02-13 13:32:11 +01:00
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2023 Antonio Ca<EFBFBD>as Vargas
2019-02-13 13:32:11 +01:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
2019-02-14 00:33:51 +01:00
#include <stdlib.h> // For exit
2019-02-13 13:32:11 +01:00
#include "swad_database.h"
#include "swad_firewall.h"
#include "swad_firewall_database.h"
2019-02-13 13:32:11 +01:00
/*****************************************************************************/
2019-11-21 16:47:07 +01:00
/****************************** Private prototypes ***************************/
2019-02-13 13:32:11 +01:00
/*****************************************************************************/
static void Fir_WriteHTML (const char *Title,const char *H1);
2019-02-13 17:26:19 +01:00
2019-02-13 15:06:02 +01:00
/*****************************************************************************/
/*************************** Check if IP is banned ***************************/
/*****************************************************************************/
void Fir_CheckFirewallAndExitIfBanned (void)
2019-02-13 15:06:02 +01:00
{
unsigned NumCurrentBans;
2019-02-13 15:06:02 +01:00
/***** Get number of current bans from database *****/
NumCurrentBans = Fir_DB_GetNumBansIP ();
2019-02-13 15:06:02 +01:00
/***** Exit with status 403 if banned *****/
2019-03-27 14:36:57 +01:00
/* RFC 6585 suggests "403 Forbidden", according to
2019-02-13 15:06:02 +01:00
https://stackoverflow.com/questions/7447283/proper-http-status-to-return-for-hacking-attempts
https://tools.ietf.org/html/rfc2616#section-10.4.4 */
if (NumCurrentBans)
{
/* Return status 403 Forbidden */
fprintf (stdout,"Content-Type: text/html; charset=windows-1252\n"
2019-02-13 17:26:19 +01:00
"Status: 403\r\n\r\n");
Fir_WriteHTML ("Forbidden","You are temporarily banned");
2019-02-13 15:06:02 +01:00
/* Close database connection and exit */
DB_CloseDBConnection ();
exit (0);
}
}
/*****************************************************************************/
/**************** Check if too many connections from this IP *****************/
2019-02-13 13:32:11 +01:00
/*****************************************************************************/
void Fir_CheckFirewallAndExitIfTooManyRequests (void)
2019-02-13 13:32:11 +01:00
{
unsigned NumClicks;
2019-02-13 13:32:11 +01:00
/***** Get number of clicks from database *****/
NumClicks = Fir_DB_GetNumClicksFromLog ();
2019-02-13 13:32:11 +01:00
/***** Exit with status 429 if too many connections *****/
/* RFC 6585 suggests "429 Too Many Requests", according to
https://stackoverflow.com/questions/46664695/whats-the-correct-http-response-code-to-return-for-denial-of-service-dos-atta
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429 */
if (NumClicks > Fw_MAX_CLICKS_IN_INTERVAL)
{
2019-02-13 15:06:02 +01:00
/* Ban this IP */
Fir_DB_BanIP ();
2019-02-13 15:06:02 +01:00
2019-02-13 13:32:11 +01:00
/* Return status 429 Too Many Requests */
fprintf (stdout,"Content-Type: text/html; charset=windows-1252\n"
2019-02-13 15:06:02 +01:00
"Retry-After: %lu\n"
2019-02-13 17:26:19 +01:00
"Status: 429\r\n\r\n",
2019-02-13 15:06:02 +01:00
(unsigned long) Fw_TIME_BANNED);
Fir_WriteHTML ("Too Many Requests","Please stop that");
2019-02-13 13:32:11 +01:00
/* Close database connection and exit */
DB_CloseDBConnection ();
exit (0);
}
}
/*****************************************************************************/
2019-02-13 15:06:02 +01:00
/********************************* Ban an IP *********************************/
2019-02-13 13:32:11 +01:00
/*****************************************************************************/
static void Fir_WriteHTML (const char *Title,const char *H1)
2019-02-13 17:26:19 +01:00
{
fprintf (stdout,"<html>"
"<head>"
"<title>%s</title>"
"</head>"
"<body>"
"<h1>%s</h1>"
"</body>"
2019-02-13 17:26:19 +01:00
"</html>\n",
Title,H1);
}