Version 21.4: Sep 15, 2021 New module swad_firewall_database for database queries related to firewall.

This commit is contained in:
acanas 2021-09-15 08:14:09 +02:00
parent 9d25990134
commit 26eddc4534
8 changed files with 196 additions and 86 deletions

View File

@ -48,8 +48,9 @@ OBJS = swad_account.o swad_account_database.o swad_action.o swad_admin.o \
swad_exam_database.o swad_exam_log.o swad_exam_print.o \
swad_exam_result.o swad_exam_session.o swad_exam_set.o \
swad_figure.o swad_figure_cache.o swad_figure_database.o swad_file.o \
swad_file_extension.o swad_file_MIME.o swad_firewall.o swad_follow.o \
swad_follow_database.o swad_form.o swad_forum.o \
swad_file_extension.o swad_file_MIME.o swad_firewall.o \
swad_firewall_database.o swad_follow.o swad_follow_database.o \
swad_form.o swad_forum.o \
swad_game.o swad_global.o swad_group.o swad_group_database.o \
swad_help.o swad_hierarchy.o swad_hierarchy_config.o swad_holiday.o \
swad_HTML.o \

View File

@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
*/
#define Log_PLATFORM_VERSION "SWAD 21.3.1 (2021-09-15)"
#define Log_PLATFORM_VERSION "SWAD 21.4 (2021-09-15)"
#define CSS_FILE "swad20.45.css"
#define JS_FILE "swad20.69.1.js"
/*
TODO: Rename CENTRE to CENTER in help wiki.
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
Version 21.4: Sep 15, 2021 New module swad_firewall_database for database queries related to firewall. (315286 lines)
Version 21.3.1: Sep 15, 2021 Queries moved to module swad_browser_database. (315201 lines)
Version 21.3: Sep 15, 2021 New module swad_notification_database for database queries related to notifications. (315211 lines)
Version 21.2.2: Sep 14, 2021 Queries moved to module swad_browser_database. (315051 lines)

View File

@ -28,6 +28,8 @@
#include <stdlib.h> // For exit
#include "swad_database.h"
#include "swad_firewall.h"
#include "swad_firewall_database.h"
#include "swad_global.h"
/*****************************************************************************/
@ -40,17 +42,6 @@ extern struct Globals Gbl;
/***************************** Private constants *****************************/
/*****************************************************************************/
/* The maximum number of clicks in the interval
should be large enough to prevent an IP from being banned
due to automatic refresh when the user is viewing the last clicks. */
#define Fw_CHECK_INTERVAL ((time_t)(30UL)) // Check clicks in the last 30 seconds
#define Fw_MAX_CLICKS_IN_INTERVAL 150 // Maximum of 150 clicks allowed in 30 seconds
// (5 clicks/s sustained for 30 s)
#define Fw_TIME_BANNED ((time_t)(60UL*60UL)) // Ban IP for 1 hour
#define Fw_TIME_TO_DELETE_OLD_CLICKS Fw_CHECK_INTERVAL // Remove clicks older than these seconds
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
@ -59,38 +50,8 @@ extern struct Globals Gbl;
/****************************** Private prototypes ***************************/
/*****************************************************************************/
static void Fir_DB_BanIP (void);
static void Fir_WriteHTML (const char *Title,const char *H1);
/*****************************************************************************/
/************************** Log access into firewall *************************/
/*****************************************************************************/
void Fir_DB_LogAccess (void)
{
/***** Log access in firewall recent log *****/
DB_QueryINSERT ("can not log access into firewall_log",
"INSERT INTO fir_log"
" (ClickTime,IP)"
" VALUES"
" (NOW(),'%s')",
Gbl.IP);
}
/*****************************************************************************/
/********************** Remove old clicks from firewall **********************/
/*****************************************************************************/
void Fir_DB_PurgeFirewall (void)
{
/***** Remove old clicks *****/
DB_QueryDELETE ("can not purge firewall log",
"DELETE LOW_PRIORITY FROM fir_log"
" WHERE ClickTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
(unsigned long) Fw_TIME_TO_DELETE_OLD_CLICKS);
}
/*****************************************************************************/
/*************************** Check if IP is banned ***************************/
/*****************************************************************************/
@ -100,13 +61,7 @@ void Fir_CheckFirewallAndExitIfBanned (void)
unsigned NumCurrentBans;
/***** Get number of current bans from database *****/
NumCurrentBans = (unsigned)
DB_QueryCOUNT ("can not check firewall log",
"SELECT COUNT(*)"
" FROM fir_banned"
" WHERE IP='%s'"
" AND UnbanTime>NOW()",
Gbl.IP);
NumCurrentBans = Fir_DB_GetNumBansIP ();
/***** Exit with status 403 if banned *****/
/* RFC 6585 suggests "403 Forbidden", according to
@ -134,14 +89,7 @@ void Fir_CheckFirewallAndExitIfTooManyRequests (void)
unsigned NumClicks;
/***** Get number of clicks from database *****/
NumClicks = (unsigned)
DB_QueryCOUNT ("can not check firewall log",
"SELECT COUNT(*)"
" FROM fir_log"
" WHERE IP='%s'"
" AND ClickTime>FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
Gbl.IP,
Fw_CHECK_INTERVAL);
NumClicks = Fir_DB_GetNumClicksFromLog ();
/***** Exit with status 429 if too many connections *****/
/* RFC 6585 suggests "429 Too Many Requests", according to
@ -169,31 +117,15 @@ void Fir_CheckFirewallAndExitIfTooManyRequests (void)
/********************************* Ban an IP *********************************/
/*****************************************************************************/
static void Fir_DB_BanIP (void)
{
/***** Insert IP into table of banned IPs *****/
DB_QueryINSERT ("can not ban IP",
"INSERT INTO fir_banned"
" (IP,BanTime,UnbanTime)"
" VALUES"
" ('%s',NOW(),FROM_UNIXTIME(UNIX_TIMESTAMP()+%lu))",
Gbl.IP,
(unsigned long) Fw_TIME_BANNED);
}
/*****************************************************************************/
/********************************* Ban an IP *********************************/
/*****************************************************************************/
static void Fir_WriteHTML (const char *Title,const char *H1)
{
fprintf (stdout,"<html>"
"<head>"
"<title>%s</title>"
"</head>"
"<body>"
"<h1>%s</h1>"
"</body>"
"<head>"
"<title>%s</title>"
"</head>"
"<body>"
"<h1>%s</h1>"
"</body>"
"</html>\n",
Title,H1);
}

View File

@ -31,13 +31,21 @@
/************************** Public types and constants ***********************/
/*****************************************************************************/
/* The maximum number of clicks in the interval
should be large enough to prevent an IP from being banned
due to automatic refresh when the user is viewing the last clicks. */
#define Fw_CHECK_INTERVAL ((time_t)(30UL)) // Check clicks in the last 30 seconds
#define Fw_MAX_CLICKS_IN_INTERVAL 150 // Maximum of 150 clicks allowed in 30 seconds
// (5 clicks/s sustained for 30 s)
#define Fw_TIME_BANNED ((time_t)(60UL*60UL)) // Ban IP for 1 hour
#define Fw_TIME_TO_DELETE_OLD_CLICKS Fw_CHECK_INTERVAL // Remove clicks older than these seconds
/*****************************************************************************/
/***************************** Public prototypes *****************************/
/*****************************************************************************/
void Fir_DB_LogAccess (void);
void Fir_DB_PurgeFirewall (void);
void Fir_CheckFirewallAndExitIfBanned (void);
void Fir_CheckFirewallAndExitIfTooManyRequests (void);

122
swad_firewall_database.c Normal file
View File

@ -0,0 +1,122 @@
// swad_firewall_database.c: firewall to mitigate denial of service attacks, operations with database
/*
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-2021 Antonio Cañas Vargas
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 ***********************************/
/*****************************************************************************/
#include <stdlib.h> // For exit
#include "swad_database.h"
#include "swad_firewall.h"
#include "swad_global.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/****************************** Private prototypes ***************************/
/*****************************************************************************/
/*****************************************************************************/
/********************* Log access into firewall recent log *******************/
/*****************************************************************************/
void Fir_DB_LogAccess (void)
{
DB_QueryINSERT ("can not log access into firewall_log",
"INSERT INTO fir_log"
" (ClickTime,IP)"
" VALUES"
" (NOW(),'%s')",
Gbl.IP);
}
/*****************************************************************************/
/********************* Get number of clicks from database ********************/
/*****************************************************************************/
unsigned Fir_DB_GetNumClicksFromLog (void)
{
return (unsigned)
DB_QueryCOUNT ("can not check firewall log",
"SELECT COUNT(*)"
" FROM fir_log"
" WHERE IP='%s'"
" AND ClickTime>FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
Gbl.IP,
Fw_CHECK_INTERVAL);
}
/*****************************************************************************/
/********************** Remove old clicks from firewall **********************/
/*****************************************************************************/
void Fir_DB_PurgeFirewallLog (void)
{
DB_QueryDELETE ("can not purge firewall log",
"DELETE LOW_PRIORITY FROM fir_log"
" WHERE ClickTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
(unsigned long) Fw_TIME_TO_DELETE_OLD_CLICKS);
}
/*****************************************************************************/
/********************************* Ban an IP *********************************/
/*****************************************************************************/
void Fir_DB_BanIP (void)
{
DB_QueryINSERT ("can not ban IP",
"INSERT INTO fir_banned"
" (IP,BanTime,UnbanTime)"
" VALUES"
" ('%s',NOW(),FROM_UNIXTIME(UNIX_TIMESTAMP()+%lu))",
Gbl.IP,
(unsigned long) Fw_TIME_BANNED);
}
/*****************************************************************************/
/***************** Get number of current bans from database ******************/
/*****************************************************************************/
unsigned Fir_DB_GetNumBansIP (void)
{
return (unsigned)
DB_QueryCOUNT ("can not check firewall log",
"SELECT COUNT(*)"
" FROM fir_banned"
" WHERE IP='%s'"
" AND UnbanTime>NOW()",
Gbl.IP);
}

45
swad_firewall_database.h Normal file
View File

@ -0,0 +1,45 @@
// swad_firewall_database.h: firewall to mitigate denial of service attacks, operations with database
#ifndef _SWAD_FW_DB
#define _SWAD_FW_DB
/*
SWAD (Shared Workspace At a Distance in Spanish),
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-2021 Antonio Cañas Vargas
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 ***********************************/
/*****************************************************************************/
/*****************************************************************************/
/************************** Public types and constants ***********************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Public prototypes *****************************/
/*****************************************************************************/
void Fir_DB_LogAccess (void);
unsigned Fir_DB_GetNumClicksFromLog (void);
void Fir_DB_PurgeFirewallLog (void);
void Fir_DB_BanIP (void);
unsigned Fir_DB_GetNumBansIP (void);
#endif

View File

@ -41,7 +41,7 @@
#include "swad_database.h"
#include "swad_error.h"
#include "swad_exam_session.h"
#include "swad_firewall.h"
#include "swad_firewall_database.h"
#include "swad_follow.h"
#include "swad_form.h"
#include "swad_global.h"
@ -1437,7 +1437,7 @@ void Lay_RefreshNotifsAndConnected (void)
if (!(Gbl.PID % 11))
Ntf_SendPendingNotifByEMailToAllUsrs (); // Send pending notifications by email
else if (!(Gbl.PID % 19))
Fir_DB_PurgeFirewall (); // Remove old clicks from firewall
Fir_DB_PurgeFirewallLog (); // Remove old clicks from firewall
else if (!(Gbl.PID % 23))
Fil_RemoveOldTmpFiles (Cfg_PATH_FILE_BROWSER_TMP_PUBLIC ,Cfg_TIME_TO_DELETE_BROWSER_TMP_FILES ,false); // Remove the oldest temporary public directories used for downloading
else if (!(Gbl.PID % 101))

View File

@ -37,6 +37,7 @@
#include "swad_database.h"
#include "swad_error.h"
#include "swad_firewall.h"
#include "swad_firewall_database.h"
#include "swad_global.h"
#include "swad_hierarchy.h"
#include "swad_hierarchy_level.h"