mirror of https://github.com/acanas/swad-core.git
Version 18.40
This commit is contained in:
parent
c62e46d617
commit
3c4dc97d5b
14
sql/swad.sql
14
sql/swad.sql
|
@ -522,9 +522,19 @@ CREATE TABLE IF NOT EXISTS files (
|
||||||
INDEX(ZoneUsrCod),
|
INDEX(ZoneUsrCod),
|
||||||
INDEX(PublisherUsrCod));
|
INDEX(PublisherUsrCod));
|
||||||
--
|
--
|
||||||
-- Table firewall: stores the most recent IPs in order to mitigate denial of service attacks
|
-- Table firewall_banned: stores the banned IPs in order to mitigate denial of service attacks
|
||||||
--
|
--
|
||||||
CREATE TABLE IF NOT EXISTS firewall (
|
CREATE TABLE IF NOT EXISTS firewall_banned (
|
||||||
|
IP CHAR(15) NOT NULL,
|
||||||
|
BanTime DATETIME NOT NULL,
|
||||||
|
UnbanTime DATETIME NOT NULL,
|
||||||
|
INDEX(IP,UnbanTime),
|
||||||
|
INDEX(BanTime),
|
||||||
|
INDEX(UnbanTime));
|
||||||
|
--
|
||||||
|
-- Table firewall_log: stores the most recent IPs in order to mitigate denial of service attacks
|
||||||
|
--
|
||||||
|
CREATE TABLE IF NOT EXISTS firewall_log (
|
||||||
ClickTime DATETIME NOT NULL,
|
ClickTime DATETIME NOT NULL,
|
||||||
IP CHAR(15) NOT NULL,
|
IP CHAR(15) NOT NULL,
|
||||||
INDEX(ClickTime),
|
INDEX(ClickTime),
|
||||||
|
|
|
@ -335,9 +335,6 @@ Buenos d
|
||||||
// TODO: Que la opción por defecto en "Permitir que los profesores vean este examen" la configuren los profesores en cada asignatura"
|
// TODO: Que la opción por defecto en "Permitir que los profesores vean este examen" la configuren los profesores en cada asignatura"
|
||||||
// TODO: URGENTE: Bego del Pino, una columna en resultados de test que indique los descriptores de ese examen
|
// TODO: URGENTE: Bego del Pino, una columna en resultados de test que indique los descriptores de ese examen
|
||||||
|
|
||||||
// TODO: Pedro Villar Castro:
|
|
||||||
// Al asignar un TFG a alumnos, no escribir el DNI del alumno, sino escogerlo de una lista de entre los alumnos inscritos en la asignatura.
|
|
||||||
|
|
||||||
// TODO: Cuando se muestre un usuario duplicado, que SWAD calcule automáticamente sus cifras no calculadas sin tener que pulsar en Calcular
|
// TODO: Cuando se muestre un usuario duplicado, que SWAD calcule automáticamente sus cifras no calculadas sin tener que pulsar en Calcular
|
||||||
|
|
||||||
// TODO: Miguel Damas Hermoso sugiere poder editar texto enriquecido (Markdown) en las preguntas de tipo test
|
// TODO: Miguel Damas Hermoso sugiere poder editar texto enriquecido (Markdown) en las preguntas de tipo test
|
||||||
|
@ -361,6 +358,15 @@ Buenos d
|
||||||
|
|
||||||
// TODO: Tabla de asistencia con símbolos tip ok como entidades HTML
|
// TODO: Tabla de asistencia con símbolos tip ok como entidades HTML
|
||||||
|
|
||||||
|
// TODO: Pedro Villar Castro:
|
||||||
|
// Al asignar un TFG a alumnos, no escribir el DNI del alumno, sino escogerlo de una lista de entre los alumnos inscritos en la asignatura.
|
||||||
|
|
||||||
|
// TODO: Pedro Villar Castro:
|
||||||
|
// Bloquear individualmente la edición con una casilla de configuración para cada TFG, sólo el profesor de la asignatura (Perico) podría bloquear/desbloquear
|
||||||
|
// Que haya una opción general que los bloquee todos y que los desbloquee todos
|
||||||
|
// Para bloquear/desbloquear se usará un icono candado
|
||||||
|
// Para preasignado/no preasignado usar otro icono (usuario/usuario tachado, por ej.)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/****************************** Public constants *****************************/
|
/****************************** Public constants *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -380,11 +386,16 @@ En OpenSWAD:
|
||||||
ps2pdf source.ps destination.pdf
|
ps2pdf source.ps destination.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define Log_PLATFORM_VERSION "SWAD 18.39 (2019-02-13)"
|
#define Log_PLATFORM_VERSION "SWAD 18.40 (2019-02-13)"
|
||||||
#define CSS_FILE "swad18.33.css"
|
#define CSS_FILE "swad18.33.css"
|
||||||
#define JS_FILE "swad18.32.1.js"
|
#define JS_FILE "swad18.32.1.js"
|
||||||
/*
|
/*
|
||||||
Version 18.39: Feb 13, 2019 New module swad_firewall to mitigate mitigate DoS attacks. (239101 lines)
|
Version 18.40: Feb 13, 2019 New table for banned IPs to mitigate DoS attacks. (239198 lines)
|
||||||
|
2 changes necessary in database:
|
||||||
|
RENAME TABLE firewall TO firewall_log;
|
||||||
|
CREATE TABLE IF NOT EXISTS firewall_banned (IP CHAR(15) NOT NULL,BanTime DATETIME NOT NULL,UnbanTime DATETIME NOT NULL,INDEX(IP,UnbanTime),INDEX(BanTime),INDEX(UnbanTime));
|
||||||
|
|
||||||
|
Version 18.39: Feb 13, 2019 New module swad_firewall to mitigate DoS attacks. (239101 lines)
|
||||||
1 change necessary in database:
|
1 change necessary in database:
|
||||||
CREATE TABLE IF NOT EXISTS firewall (ClickTime DATETIME NOT NULL,IP CHAR(15) NOT NULL,INDEX(ClickTime),INDEX(IP));
|
CREATE TABLE IF NOT EXISTS firewall (ClickTime DATETIME NOT NULL,IP CHAR(15) NOT NULL,INDEX(ClickTime),INDEX(IP));
|
||||||
|
|
||||||
|
|
|
@ -1149,9 +1149,29 @@ mysql> DESCRIBE files;
|
||||||
"INDEX(ZoneUsrCod),"
|
"INDEX(ZoneUsrCod),"
|
||||||
"INDEX(PublisherUsrCod))");
|
"INDEX(PublisherUsrCod))");
|
||||||
|
|
||||||
/***** Table firewall *****/
|
/***** Table firewall_banned *****/
|
||||||
/*
|
/*
|
||||||
mysql> DESCRIBE firewall;
|
mysql> DESCRIBE firewall_banned;
|
||||||
|
+-----------+----------+------+-----+---------+-------+
|
||||||
|
| Field | Type | Null | Key | Default | Extra |
|
||||||
|
+-----------+----------+------+-----+---------+-------+
|
||||||
|
| IP | char(15) | NO | MUL | NULL | |
|
||||||
|
| BanTime | datetime | NO | MUL | NULL | |
|
||||||
|
| UnbanTime | datetime | NO | MUL | NULL | |
|
||||||
|
+-----------+----------+------+-----+---------+-------+
|
||||||
|
3 rows in set (0.00 sec)
|
||||||
|
*/
|
||||||
|
DB_CreateTable ("CREATE TABLE IF NOT EXISTS firewall_banned ("
|
||||||
|
"IP CHAR(15) NOT NULL," // Cns_MAX_BYTES_IP
|
||||||
|
"BanTime DATETIME NOT NULL,"
|
||||||
|
"UnbanTime DATETIME NOT NULL,"
|
||||||
|
"INDEX(IP,UnbanTime),"
|
||||||
|
"INDEX(BanTime),"
|
||||||
|
"INDEX(UnbanTime));");
|
||||||
|
|
||||||
|
/***** Table firewall_log *****/
|
||||||
|
/*
|
||||||
|
mysql> DESCRIBE firewall_log;
|
||||||
+-----------+----------+------+-----+---------+-------+
|
+-----------+----------+------+-----+---------+-------+
|
||||||
| Field | Type | Null | Key | Default | Extra |
|
| Field | Type | Null | Key | Default | Extra |
|
||||||
+-----------+----------+------+-----+---------+-------+
|
+-----------+----------+------+-----+---------+-------+
|
||||||
|
@ -1160,7 +1180,7 @@ mysql> DESCRIBE firewall;
|
||||||
+-----------+----------+------+-----+---------+-------+
|
+-----------+----------+------+-----+---------+-------+
|
||||||
2 rows in set (0.00 sec)
|
2 rows in set (0.00 sec)
|
||||||
*/
|
*/
|
||||||
DB_CreateTable ("CREATE TABLE IF NOT EXISTS firewall ("
|
DB_CreateTable ("CREATE TABLE IF NOT EXISTS firewall_log ("
|
||||||
"ClickTime DATETIME NOT NULL,"
|
"ClickTime DATETIME NOT NULL,"
|
||||||
"IP CHAR(15) NOT NULL," // Cns_MAX_BYTES_IP
|
"IP CHAR(15) NOT NULL," // Cns_MAX_BYTES_IP
|
||||||
"INDEX(ClickTime),"
|
"INDEX(ClickTime),"
|
||||||
|
|
|
@ -38,9 +38,14 @@ extern struct Globals Gbl;
|
||||||
/***************************** Private constants *****************************/
|
/***************************** 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)(10UL)) // Check clicks in the last 10 seconds
|
#define Fw_CHECK_INTERVAL ((time_t)(10UL)) // Check clicks in the last 10 seconds
|
||||||
#define Fw_MAX_CLICKS_IN_INTERVAL 30 // Maximum of 30 clicks allowed in 10 seconds
|
#define Fw_MAX_CLICKS_IN_INTERVAL 30 // Maximum of 30 clicks allowed in 10 seconds
|
||||||
|
|
||||||
|
#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
|
#define Fw_TIME_TO_DELETE_OLD_CLICKS Fw_CHECK_INTERVAL // Remove clicks older than these seconds
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -51,6 +56,8 @@ extern struct Globals Gbl;
|
||||||
/***************************** Internal prototypes ***************************/
|
/***************************** Internal prototypes ***************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void FW_BanIP (void);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/************************** Log access into firewall *************************/
|
/************************** Log access into firewall *************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -58,13 +65,67 @@ extern struct Globals Gbl;
|
||||||
void FW_LogAccess (void)
|
void FW_LogAccess (void)
|
||||||
{
|
{
|
||||||
/***** Log access in firewall recent log *****/
|
/***** Log access in firewall recent log *****/
|
||||||
DB_QueryINSERT ("can not log access into firewall",
|
DB_QueryINSERT ("can not log access into firewall_log",
|
||||||
"INSERT INTO firewall (ClickTime,IP) VALUES (NOW(),'%s')",
|
"INSERT INTO firewall_log"
|
||||||
|
" (ClickTime,IP)"
|
||||||
|
" VALUES"
|
||||||
|
" (NOW(),'%s')",
|
||||||
Gbl.IP);
|
Gbl.IP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/************************** Log access into firewall *************************/
|
/********************** Remove old clicks from firewall **********************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void FW_PurgeFirewall (void)
|
||||||
|
{
|
||||||
|
/***** Remove old clicks *****/
|
||||||
|
DB_QueryDELETE ("can not purge firewall log",
|
||||||
|
"DELETE LOW_PRIORITY FROM firewall_log"
|
||||||
|
" WHERE ClickTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
|
||||||
|
(unsigned long) Fw_TIME_TO_DELETE_OLD_CLICKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*************************** Check if IP is banned ***************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void FW_CheckFirewallAndExitIfBanned (void)
|
||||||
|
{
|
||||||
|
unsigned long NumCurrentBans;
|
||||||
|
|
||||||
|
/***** Get number of current bans from database *****/
|
||||||
|
NumCurrentBans = DB_QueryCOUNT ("can not check firewall log",
|
||||||
|
"SELECT COUNT(*) FROM firewall_banned"
|
||||||
|
" WHERE IP='%s' AND UnbanTime>NOW()",
|
||||||
|
Gbl.IP);
|
||||||
|
|
||||||
|
/***** Exit with status 403 if banned *****/
|
||||||
|
/* RFC 6585 suggests "429 Too Many Requests", according to
|
||||||
|
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"
|
||||||
|
"Status: 403\r\n\r\n"
|
||||||
|
"<html>"
|
||||||
|
"<head>"
|
||||||
|
"<title>Forbidden</title>"
|
||||||
|
"</head>"
|
||||||
|
"<body>"
|
||||||
|
"<h1>You are banned temporarily</h1>"
|
||||||
|
"</body>"
|
||||||
|
"</html>\n");
|
||||||
|
|
||||||
|
/* Close database connection and exit */
|
||||||
|
DB_CloseDBConnection ();
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**************** Check if too many connections from this IP *****************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void FW_CheckFirewallAndExitIfTooManyRequests (void)
|
void FW_CheckFirewallAndExitIfTooManyRequests (void)
|
||||||
|
@ -72,8 +133,8 @@ void FW_CheckFirewallAndExitIfTooManyRequests (void)
|
||||||
unsigned long NumClicks;
|
unsigned long NumClicks;
|
||||||
|
|
||||||
/***** Get number of clicks from database *****/
|
/***** Get number of clicks from database *****/
|
||||||
NumClicks = DB_QueryCOUNT ("can not check firewall",
|
NumClicks = DB_QueryCOUNT ("can not check firewall log",
|
||||||
"SELECT COUNT(*) FROM firewall"
|
"SELECT COUNT(*) FROM firewall_log"
|
||||||
" WHERE IP='%s'"
|
" WHERE IP='%s'"
|
||||||
" AND ClickTime>FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
|
" AND ClickTime>FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
|
||||||
Gbl.IP,
|
Gbl.IP,
|
||||||
|
@ -85,9 +146,12 @@ void FW_CheckFirewallAndExitIfTooManyRequests (void)
|
||||||
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429 */
|
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429 */
|
||||||
if (NumClicks > Fw_MAX_CLICKS_IN_INTERVAL)
|
if (NumClicks > Fw_MAX_CLICKS_IN_INTERVAL)
|
||||||
{
|
{
|
||||||
|
/* Ban this IP */
|
||||||
|
FW_BanIP ();
|
||||||
|
|
||||||
/* Return status 429 Too Many Requests */
|
/* Return status 429 Too Many Requests */
|
||||||
fprintf (stdout,"Content-Type: text/html; charset=windows-1252\n"
|
fprintf (stdout,"Content-Type: text/html; charset=windows-1252\n"
|
||||||
"Retry-After: 3600\n"
|
"Retry-After: %lu\n"
|
||||||
"Status: 429\r\n\r\n"
|
"Status: 429\r\n\r\n"
|
||||||
"<html>"
|
"<html>"
|
||||||
"<head>"
|
"<head>"
|
||||||
|
@ -96,7 +160,8 @@ void FW_CheckFirewallAndExitIfTooManyRequests (void)
|
||||||
"<body>"
|
"<body>"
|
||||||
"<h1>Please stop that</h1>"
|
"<h1>Please stop that</h1>"
|
||||||
"</body>"
|
"</body>"
|
||||||
"</html>\n");
|
"</html>\n",
|
||||||
|
(unsigned long) Fw_TIME_BANNED);
|
||||||
|
|
||||||
/* Close database connection and exit */
|
/* Close database connection and exit */
|
||||||
DB_CloseDBConnection ();
|
DB_CloseDBConnection ();
|
||||||
|
@ -105,14 +170,16 @@ void FW_CheckFirewallAndExitIfTooManyRequests (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/********************** Remove old clicks from firewall **********************/
|
/********************************* Ban an IP *********************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void FW_PurgeFirewall (void)
|
static void FW_BanIP (void)
|
||||||
{
|
{
|
||||||
/***** Remove old clicks *****/
|
/***** Insert IP into table of banned IPs *****/
|
||||||
DB_QueryDELETE ("can not purge firewall",
|
DB_QueryINSERT ("can not ban IP",
|
||||||
"DELETE LOW_PRIORITY FROM firewall"
|
"INSERT INTO firewall_banned"
|
||||||
" WHERE ClickTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
|
" (IP,BanTime,UnbanTime)"
|
||||||
Fw_TIME_TO_DELETE_OLD_CLICKS);
|
" VALUES"
|
||||||
|
" ('%s',NOW(),FROM_UNIXTIME(UNIX_TIMESTAMP()+%lu))",
|
||||||
|
Gbl.IP,(unsigned long) Fw_TIME_BANNED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,9 @@
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void FW_LogAccess (void);
|
void FW_LogAccess (void);
|
||||||
void FW_CheckFirewallAndExitIfTooManyRequests (void);
|
|
||||||
void FW_PurgeFirewall (void);
|
void FW_PurgeFirewall (void);
|
||||||
|
|
||||||
|
void FW_CheckFirewallAndExitIfBanned (void);
|
||||||
|
void FW_CheckFirewallAndExitIfTooManyRequests (void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -112,6 +112,7 @@ int main (void)
|
||||||
Par_GetMainParameters ();
|
Par_GetMainParameters ();
|
||||||
|
|
||||||
/***** Mitigate DoS attacks *****/
|
/***** Mitigate DoS attacks *****/
|
||||||
|
FW_CheckFirewallAndExitIfBanned ();
|
||||||
FW_LogAccess ();
|
FW_LogAccess ();
|
||||||
FW_CheckFirewallAndExitIfTooManyRequests ();
|
FW_CheckFirewallAndExitIfTooManyRequests ();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue