From 60790fd6e08b8aa5ccd0fd710dc0ff1b4202bdca Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 13 May 2022 06:28:32 +0200 Subject: [PATCH 01/58] expat: Fix rootfile. The libexpat.so.1 file is just a symlink to libexpat.so.1.8.8 which contains all the functions and symbols required by the binaries, linked against it. Therefore this file needs to be present on the systems. Signed-off-by: Stefan Schantl --- config/rootfiles/common/expat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/rootfiles/common/expat b/config/rootfiles/common/expat index 3911aa90b..69b3fbfe6 100644 --- a/config/rootfiles/common/expat +++ b/config/rootfiles/common/expat @@ -10,7 +10,7 @@ #usr/lib/libexpat.la #usr/lib/libexpat.so usr/lib/libexpat.so.1 -#usr/lib/libexpat.so.1.8.8 +usr/lib/libexpat.so.1.8.8 #usr/lib/pkgconfig/expat.pc #usr/share/doc/expat #usr/share/doc/expat-2.4.8 From e9e2a282c3219999a3982ce066a32886e6e2e006 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 13 May 2022 18:51:15 +0200 Subject: [PATCH 02/58] pango: Fix rootfile. The main libraries libpangocairo and libpangosoft2 accidently have been marked to be not shipped or part of the system. They are required by collecty and various other libraries or binaries. Signed-off-by: Stefan Schantl --- config/rootfiles/common/pango | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/rootfiles/common/pango b/config/rootfiles/common/pango index fe3164613..1ca33d42b 100644 --- a/config/rootfiles/common/pango +++ b/config/rootfiles/common/pango @@ -44,10 +44,10 @@ usr/lib/libpango-1.0.so.0 usr/lib/libpango-1.0.so.0.5000.6 #usr/lib/libpangocairo-1.0.so usr/lib/libpangocairo-1.0.so.0 -#usr/lib/libpangocairo-1.0.so.0.5000.6 +usr/lib/libpangocairo-1.0.so.0.5000.6 #usr/lib/libpangoft2-1.0.so usr/lib/libpangoft2-1.0.so.0 -#usr/lib/libpangoft2-1.0.so.0.5000.6 +usr/lib/libpangoft2-1.0.so.0.5000.6 #usr/lib/pkgconfig/pango.pc #usr/lib/pkgconfig/pangocairo.pc #usr/lib/pkgconfig/pangofc.pc From 89c7320bcfd8bfd19cb9f98965477520ef14ff78 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 13 May 2022 19:06:31 +0200 Subject: [PATCH 03/58] update-ids-ruleset: Silent script if no providers settings file exists. Only try to read-in the providers settings file, in case it exists. Otherwise the script produces an error message, about the missing file, each time it gets executed. Because of the fcron job this would be twice a day in most cases. Signed-off-by: Stefan Schantl --- src/scripts/update-ids-ruleset | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/update-ids-ruleset b/src/scripts/update-ids-ruleset index e9a082e62..553c1a1e1 100644 --- a/src/scripts/update-ids-ruleset +++ b/src/scripts/update-ids-ruleset @@ -95,8 +95,8 @@ if ($return) { # The script has requested a lock, so set locket to "1". $locked = "1"; -# Grab the configured providers. -&General::readhasharray("$IDS::providers_settings_file", \%providers); +# Grab the configured providers, if the providers settings file exists. +&General::readhasharray("$IDS::providers_settings_file", \%providers) if (-f "$IDS::providers_settings_file"); # Loop through the array of available providers. foreach my $id (keys %providers) { From 4131a0a1ad88e7e93eb0111ead3ac941a4919ae1 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 13 May 2022 23:15:02 +0200 Subject: [PATCH 04/58] liburcu: Fix rootfile. At least the xfsprogs is linked agains the urcu libraries and therefore requires them to run and deal with xfs filesystems. Signed-off-by: Stefan Schantl --- config/rootfiles/common/liburcu | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/config/rootfiles/common/liburcu b/config/rootfiles/common/liburcu index f1de29d87..ab8cb0649 100644 --- a/config/rootfiles/common/liburcu +++ b/config/rootfiles/common/liburcu @@ -101,36 +101,36 @@ #usr/include/urcu/wfstack.h #usr/lib/liburcu-bp.la #usr/lib/liburcu-bp.so -#usr/lib/liburcu-bp.so.8 -#usr/lib/liburcu-bp.so.8.0.0 +usr/lib/liburcu-bp.so.8 +usr/lib/liburcu-bp.so.8.0.0 #usr/lib/liburcu-cds.la #usr/lib/liburcu-cds.so -#usr/lib/liburcu-cds.so.8 -#usr/lib/liburcu-cds.so.8.0.0 +usr/lib/liburcu-cds.so.8 +usr/lib/liburcu-cds.so.8.0.0 #usr/lib/liburcu-common.la #usr/lib/liburcu-common.so -#usr/lib/liburcu-common.so.8 -#usr/lib/liburcu-common.so.8.0.0 +usr/lib/liburcu-common.so.8 +usr/lib/liburcu-common.so.8.0.0 #usr/lib/liburcu-mb.la #usr/lib/liburcu-mb.so -#usr/lib/liburcu-mb.so.8 -#usr/lib/liburcu-mb.so.8.0.0 +usr/lib/liburcu-mb.so.8 +usr/lib/liburcu-mb.so.8.0.0 #usr/lib/liburcu-memb.la #usr/lib/liburcu-memb.so -#usr/lib/liburcu-memb.so.8 -#usr/lib/liburcu-memb.so.8.0.0 +usr/lib/liburcu-memb.so.8 +usr/lib/liburcu-memb.so.8.0.0 #usr/lib/liburcu-qsbr.la #usr/lib/liburcu-qsbr.so -#usr/lib/liburcu-qsbr.so.8 -#usr/lib/liburcu-qsbr.so.8.0.0 +usr/lib/liburcu-qsbr.so.8 +usr/lib/liburcu-qsbr.so.8.0.0 #usr/lib/liburcu-signal.la #usr/lib/liburcu-signal.so -#usr/lib/liburcu-signal.so.8 -#usr/lib/liburcu-signal.so.8.0.0 +usr/lib/liburcu-signal.so.8 +usr/lib/liburcu-signal.so.8.0.0 #usr/lib/liburcu.la #usr/lib/liburcu.so -#usr/lib/liburcu.so.8 -#usr/lib/liburcu.so.8.0.0 +usr/lib/liburcu.so.8 +usr/lib/liburcu.so.8.0.0 #usr/lib/pkgconfig/liburcu-bp.pc #usr/lib/pkgconfig/liburcu-cds.pc #usr/lib/pkgconfig/liburcu-mb.pc From 30199da1150343fb813c2e49cfe2bab65446e833 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 13 May 2022 23:19:45 +0200 Subject: [PATCH 05/58] libinih: Fix rootfile. Some tools of the xfsprogs are linked against libinih and therefore we need to ship those libs. Signed-off-by: Stefan Schantl --- config/rootfiles/common/libinih | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/rootfiles/common/libinih b/config/rootfiles/common/libinih index c8a467edc..af22932dc 100644 --- a/config/rootfiles/common/libinih +++ b/config/rootfiles/common/libinih @@ -1,8 +1,8 @@ #usr/include/INIReader.h #usr/include/ini.h #usr/lib/libINIReader.so -#usr/lib/libINIReader.so.0 +usr/lib/libINIReader.so.0 #usr/lib/libinih.so -#usr/lib/libinih.so.0 +usr/lib/libinih.so.0 #usr/lib/pkgconfig/INIReader.pc #usr/lib/pkgconfig/inih.pc From 8533f1b1d36fcdfcd7e3d5c8b027cc90898ef635 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 13 May 2022 23:24:43 +0200 Subject: [PATCH 06/58] poppler: Fix rootfile. libpoppler.so.120.0.0 contains all the functions and symbols which are required by the tools linked against it. Signed-off-by: Stefan Schantl --- config/rootfiles/common/poppler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/rootfiles/common/poppler b/config/rootfiles/common/poppler index 0ea058043..5c6f48e00 100644 --- a/config/rootfiles/common/poppler +++ b/config/rootfiles/common/poppler @@ -174,7 +174,7 @@ usr/lib/libpoppler-glib.so.8 usr/lib/libpoppler-glib.so.8.23.0 #usr/lib/libpoppler.so usr/lib/libpoppler.so.120 -#usr/lib/libpoppler.so.120.0.0 +usr/lib/libpoppler.so.120.0.0 #usr/lib/pkgconfig/poppler-cpp.pc #usr/lib/pkgconfig/poppler-glib.pc #usr/lib/pkgconfig/poppler.pc From d7a292cbea6146d442ca8b904f847895c37e4e14 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 15 May 2022 17:54:12 +0200 Subject: [PATCH 07/58] krb5: Move package into core system. On one hand, the key.dns_resolver binary is linked against libkrb5, so this library at least is required by the base system. On the other hand this easily allows different services on the firewall to use kerberos for authentication (ssh etc). Signed-off-by: Stefan Schantl --- config/rootfiles/{packages => common}/krb5 | 0 lfs/cups | 4 ++-- lfs/krb5 | 4 ---- lfs/netatalk | 4 ++-- lfs/samba | 4 ++-- lfs/tshark | 4 ++-- 6 files changed, 8 insertions(+), 12 deletions(-) rename config/rootfiles/{packages => common}/krb5 (100%) diff --git a/config/rootfiles/packages/krb5 b/config/rootfiles/common/krb5 similarity index 100% rename from config/rootfiles/packages/krb5 rename to config/rootfiles/common/krb5 diff --git a/lfs/cups b/lfs/cups index cd4519b63..7d4dc20c2 100644 --- a/lfs/cups +++ b/lfs/cups @@ -33,9 +33,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/cups-$(VER) TARGET = $(DIR_INFO)/$(THISAPP) PROG = cups -PAK_VER = 25 +PAK_VER = 26 -DEPS = avahi cups-filters dbus ghostscript krb5 libtiff +DEPS = avahi cups-filters dbus ghostscript libtiff SERVICES = cups diff --git a/lfs/krb5 b/lfs/krb5 index 399f9338e..e08948005 100644 --- a/lfs/krb5 +++ b/lfs/krb5 @@ -33,10 +33,6 @@ DL_FILE = $(THISAPP).tar.gz DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP)/src TARGET = $(DIR_INFO)/$(THISAPP) -PROG = krb5 -PAK_VER = 7 - -DEPS = SERVICES = diff --git a/lfs/netatalk b/lfs/netatalk index 61ba193a5..ef75c89fe 100644 --- a/lfs/netatalk +++ b/lfs/netatalk @@ -34,9 +34,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = netatalk -PAK_VER = 2 +PAK_VER = 3 -DEPS = avahi dbus krb5 +DEPS = avahi dbus SERVICES = netatalk diff --git a/lfs/samba b/lfs/samba index 97fe96918..a48a0ecb1 100644 --- a/lfs/samba +++ b/lfs/samba @@ -33,9 +33,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = samba -PAK_VER = 84 +PAK_VER = 85 -DEPS = avahi cups libtirpc krb5 perl-Parse-Yapp perl-JSON +DEPS = avahi cups libtirpc perl-Parse-Yapp perl-JSON SERVICES = samba diff --git a/lfs/tshark b/lfs/tshark index eb89f7474..ee9c06dc4 100644 --- a/lfs/tshark +++ b/lfs/tshark @@ -34,8 +34,8 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = tshark -DEPS = krb5 c-ares -PAK_VER = 12 +DEPS = c-ares +PAK_VER = 13 SERVICES = From 9c5f467dcf6b956b690529036bd5032ff44eaef1 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 15 May 2022 18:00:34 +0200 Subject: [PATCH 08/58] libtiff: Move into core system. pango and the PDF tools as core parts are linked against libtiff, therefore this library has to become a part of the core distribution too. Signed-off-by: Stefan Schantl --- config/rootfiles/{packages => common}/libtiff | 0 lfs/cups | 4 ++-- lfs/foomatic | 4 ++-- lfs/ghostscript | 4 ++-- lfs/libtiff | 4 ---- lfs/spandsp | 4 ++-- 6 files changed, 8 insertions(+), 12 deletions(-) rename config/rootfiles/{packages => common}/libtiff (100%) diff --git a/config/rootfiles/packages/libtiff b/config/rootfiles/common/libtiff similarity index 100% rename from config/rootfiles/packages/libtiff rename to config/rootfiles/common/libtiff diff --git a/lfs/cups b/lfs/cups index 7d4dc20c2..d333532e3 100644 --- a/lfs/cups +++ b/lfs/cups @@ -33,9 +33,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/cups-$(VER) TARGET = $(DIR_INFO)/$(THISAPP) PROG = cups -PAK_VER = 26 +PAK_VER = 27 -DEPS = avahi cups-filters dbus ghostscript libtiff +DEPS = avahi cups-filters dbus ghostscript SERVICES = cups diff --git a/lfs/foomatic b/lfs/foomatic index 50f5c2377..73dc16842 100644 --- a/lfs/foomatic +++ b/lfs/foomatic @@ -37,9 +37,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/foomatic-filters-$(VER_FILTERS) TARGET = $(DIR_INFO)/$(THISAPP) PROG = foomatic -PAK_VER = 6 +PAK_VER = 7 -DEPS = cups ghostscript libtiff hplip +DEPS = cups ghostscript hplip SERVICES = diff --git a/lfs/ghostscript b/lfs/ghostscript index 7df96bdd5..ce318a572 100644 --- a/lfs/ghostscript +++ b/lfs/ghostscript @@ -34,9 +34,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = ghostscript -PAK_VER = 10 +PAK_VER = 11 -DEPS = cups dbus libtiff +DEPS = cups dbus SERVICES = diff --git a/lfs/libtiff b/lfs/libtiff index ef8991e31..23cb19b68 100644 --- a/lfs/libtiff +++ b/lfs/libtiff @@ -33,10 +33,6 @@ DL_FILE = $(THISAPP).tar.gz DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) -PROG = libtiff -PAK_VER = 5 - -DEPS = SERVICES = diff --git a/lfs/spandsp b/lfs/spandsp index 19b606117..5d609cb06 100644 --- a/lfs/spandsp +++ b/lfs/spandsp @@ -34,9 +34,9 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = spandsp -PAK_VER = 5 +PAK_VER = 6 -DEPS = libtiff +DEPS = SERVICES = From b7273366c41cdf63b1ed58cef53086bc871bac42 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 15 May 2022 18:08:41 +0200 Subject: [PATCH 09/58] Core 168: Remove pakfire metadata for krb5 and libtiff. Both packages have become part of the core system, so these files are not longer needed. Signed-off-by: Stefan Schantl --- config/rootfiles/core/168/update.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/config/rootfiles/core/168/update.sh b/config/rootfiles/core/168/update.sh index e11e08b7f..283cb1098 100644 --- a/config/rootfiles/core/168/update.sh +++ b/config/rootfiles/core/168/update.sh @@ -133,6 +133,22 @@ if grep -q "ENABLED=on" /var/ipfire/vpn/settings; then /etc/init.d/ipsec start fi +# krb5 is now part of the core system, remove Pakfire metadata for it +if [ -e "/opt/pakfire/db/installed/meta-krb5" ] && [ -e "/opt/pakfire/db/meta/meta-krb5" ]; then + rm -vf \ + /opt/pakfire/db/installed/meta-krb5 \ + /opt/pakfire/db/meta/meta-krb5 \ + /opt/pakfire/db/rootfiles/krb5 +fi + +# libtiff is now part of the core system, remove Pakfire metadata for it +if [ -e "/opt/pakfire/db/installed/meta-libtiff" ] && [ -e "/opt/pakfire/db/meta/meta-libtiff" ]; then + rm -vf \ + /opt/pakfire/db/installed/meta-libtiff \ + /opt/pakfire/db/meta/meta-libtiff \ + /opt/pakfire/db/rootfiles/libtiff +fi + # This update needs a reboot... touch /var/run/need_reboot From f17b5303cb853b2c38ae8b5a1f866056f966e86e Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Tue, 1 Mar 2022 15:31:58 +0100 Subject: [PATCH 10/58] ipblocklist: Add sources file. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/ipblocklist/sources | 140 +++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 config/ipblocklist/sources diff --git a/config/ipblocklist/sources b/config/ipblocklist/sources new file mode 100644 index 000000000..4d42ad974 --- /dev/null +++ b/config/ipblocklist/sources @@ -0,0 +1,140 @@ +############################################################################ +# # +# IP Address blocklists for IPFire # +# # +# This file contains a list of blocklist sources that will replace the one # +# internal to the updated if it is found at /var/ipfire/blocklist/sources. # +# The intention is to provide a common source of information for both the # +# updater and WUI. # +# # +# The chains created in the packet filter will be named by the top level # +# key and this will also be used in the log message to identify the reason # +# for the dropped packet. # +# # +# The fields are: # +# # +# name The blocklist's full name # +# url URL of the file containing the list # +# info URL giving information about the source # +# parser The parser function used to extract IP addresses from the # +# downloaded list # +# rate Minimum period between checks for updates. Can be specified in # +# days (d), hours (h) or minutes (m) # +# category Used for documentation on the WUI. Can be one of the following # +# 'application' Potentially unwanted applications # +# 'attacker' Generic source of malicious packets # +# 'c and c' Malware Command and Control source # +# 'composite' Composite of other lists # +# 'invalid' Invalid addresses on the public internet # +# 'scanner' Port scanner that is not initself malicious # +# disable Name of another list to disable if this one is enabled. Used # +# when the other list is a subset of this one. # +# # +# The info and category fields are purely for documentation. # +# # +############################################################################ + +package IPblocklist::List; + +our %sources = ( 'EMERGING_FWRULE' => { 'name' => 'Emerging Threats Blocklist', + 'url' => 'https://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt', + 'info' => 'https://doc.emergingthreats.net/bin/view/Main/EmergingFirewallRules', + 'parser' => 'ip-or-net-list', + 'rate' => '1h', + 'category' => 'composite', + 'disable' => ['FEODO_RECOMMENDED', 'FEODO_IP', 'FEODO_AGGRESIVE', 'SPAMHAUS_DROP', 'DSHIELD'] }, + 'EMERGING_COMPROMISED' => { 'name' => 'Emerging Threats Compromised IPs', + 'url' => 'https://rules.emergingthreats.net/blockrules/compromised-ips.txt', + 'info' => 'https://doc.emergingthreats.net/bin/view/Main/CompromisedHost', + 'parser' => 'ip-or-net-list', + 'rate' => '1h', + 'category' => 'attacker' }, + 'SPAMHAUS_DROP' => { 'name' => "Spamhaus Don't Route or Peer List", + 'url' => 'https://www.spamhaus.org/drop/drop.txt', + 'info' => 'https://www.spamhaus.org/drop/', + 'parser' => 'ip-or-net-list', + 'rate' => '12h', + 'category' => 'reputation' }, + 'SPAMHAUS_EDROP' => { 'name' => "Spamhaus Extended Don't Route or Peer List", + 'url' => 'https://www.spamhaus.org/drop/edrop.txt', + 'info' => 'https://www.spamhaus.org/drop/', + 'parser' => 'ip-or-net-list', + 'rate' => '1h', + 'category' => 'reputation' }, + 'DSHIELD' => { 'name' => 'Dshield.org Recommended Block List', + 'url' => 'https://www.dshield.org/block.txt', + 'info' => 'https://dshield.org/', + 'parser' => 'dshield', + 'rate' => '1h', + 'category' => 'attacker' }, + 'FEODO_RECOMMENDED'=> {'name' => 'Feodo Trojan IP Blocklist (Recommended)', + 'url' => 'https://feodotracker.abuse.ch/downloads/ipblocklist_recommended.txt', + 'info' => 'https://feodotracker.abuse.ch/blocklist', + 'parser' => 'ip-or-net-list', + 'rate' => '5m', + 'category' => 'c and c' }, + 'FEODO_IP' => { 'name' => 'Feodo Trojan IP Blocklist', + 'url' => 'https://feodotracker.abuse.ch/downloads/ipblocklist.txt', + 'info' => 'https://feodotracker.abuse.ch/blocklist', + 'parser' => 'ip-or-net-list', + 'rate' => '5m', + 'category' => 'c and c', + 'disable' => 'FEODO_RECOMMENDED' }, + 'FEODO_AGGRESIVE' => { 'name' => 'Feodo Trojan IP Blocklist (Aggresive)', + 'url' => 'https://feodotracker.abuse.ch/downloads/ipblocklist_aggressive.txt', + 'info' => 'https://feodotracker.abuse.ch/blocklist', + 'parser' => 'ip-or-net-list', + 'rate' => '5m', + 'category' => 'c and c', + 'disable' => ['FEODO_IP', 'FEODO_RECOMMENDED'] }, + 'CIARMY' => { 'name' => 'The CINS Army List', + 'url' => 'https://cinsscore.com/list/ci-badguys.txt', + 'info' => 'https://cinsscore.com/#list', + 'parser' => 'ip-or-net-list', + 'rate' => '15m', + 'category' => 'reputation' }, + 'TOR_ALL' => { 'name' => 'Known TOR Nodes', + 'url' => 'https://www.dan.me.uk/torlist', + 'info' => 'https://www.dan.me.uk/tornodes', + 'parser' => 'ip-or-net-list', + 'rate' => '1h', + 'category' => 'application', + 'disable' => 'TOR_EXIT' }, + 'TOR_EXIT' => { 'name' => 'Known TOR Exit Nodes', + 'url' => 'https://www.dan.me.uk/torlist/?exit', + 'info' => 'https://www.dan.me.uk/tornodes', + 'parser' => 'ip-or-net-list',, + 'rate' => '1h', + 'category' => 'application' }, + 'ALIENVAULT' => { 'name' => 'AlienVault IP Reputation database', + 'url' => 'https://reputation.alienvault.com/reputation.generic', + 'info' => 'https://www.alienvault.com/resource-center/videos/what-is-ip-domain-reputation', + 'parser' => 'ip-or-net-list', + 'rate' => '1h', + 'category' => 'reputation' }, + 'BOGON' => { 'name' => 'Bogus address list (Martian)', + 'url' => 'https://www.team-cymru.org/Services/Bogons/bogon-bn-agg.txt', + 'info' => 'https://www.team-cymru.com/bogon-reference.html', + 'parser' => 'ip-or-net-list', + 'rate' => '1d', + 'category' => 'invalid' }, + 'BOGON_FULL' => { 'name' => 'Full Bogus Address List', + 'url' => 'https://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt', + 'info' => 'https://www.team-cymru.com/bogon-reference.html', + 'parser' => 'ip-or-net-list', + 'rate' => '4h', + 'category' => 'invalid', + 'disable' => 'BOGON' }, + 'SHODAN' => { 'name' => 'ISC Shodan scanner blocklist', + 'url' => 'https://isc.sans.edu/api/threatlist/shodan?tab', + 'info' => 'https://isc.sans.edu', + 'parser' => 'ip-or-net-list', + 'rate' => '1d', + 'category' => 'scanner' }, + 'BLOCKLIST_DE' => { 'name' => 'Blocklist.de all attacks list', + 'url' => 'https://lists.blocklist.de/lists/all.txt', + 'info' => 'https://www.blocklist.de', + 'parser' => 'ip-or-net-list', + 'rate' => '30m', + 'category' => 'attacker' } + ); From f4c25a44e20a21d4fb7e04d0cbc0e02613db20f5 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 1 Mar 2022 15:23:44 +0100 Subject: [PATCH 11/58] ipblocklist-functions.pl: Initial commit. This library file will contain a collection of functions, which are required to deal with the ipblocklist feature. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 42 +++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 config/cfgroot/ipblocklist-functions.pl diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl new file mode 100644 index 000000000..2072f3f32 --- /dev/null +++ b/config/cfgroot/ipblocklist-functions.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2022 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 2 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 General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +package IPblocklist; + +require '/var/ipfire/ipblocklist/sources'; + +# +## Function to get all available blocklists. +# +sub get_blocklists () { + my @blocklists; + + # Loop through the hash of blocklists. + foreach my $blocklist ( keys %IPblocklist::List::sources ) { + # Add the list to the array. + push(@blocklists, $blocklist); + } + + # Sort and return the array. + return sort(@blocklists); +} + +1; From e64587a43d9cf5ef6fb275330ef83c62e71e4453 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 1 Mar 2022 17:35:20 +0100 Subject: [PATCH 12/58] ipblocklist-functions.pl: Add get_ipset_db_file() function. This function is used to generate the filename and full path for a given blocklist name. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index 2072f3f32..f7ffbdbca 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -23,6 +23,12 @@ package IPblocklist; require '/var/ipfire/ipblocklist/sources'; +# Location where the blocklists in ipset compatible format are stored. +our $blocklist_dir = "/var/lib/ipblocklist"; + +# File extension of the blocklist files. +our $blocklist_file_extension = ".conf"; + # ## Function to get all available blocklists. # @@ -39,4 +45,17 @@ sub get_blocklists () { return sort(@blocklists); } +# +## Tiny function to get the full path and name of a given blocklist. +# +sub get_ipset_db_file($) { + my ($set) = @_; + + # Generate the + my $file = "$blocklist_dir/$set$blocklist_file_extension"; + + # Return the file name. + return $file; +} + 1; From ba8455e4699b71f07d8cd54e4b4d72edcc5d24c4 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Fri, 4 Mar 2022 21:57:03 +0100 Subject: [PATCH 13/58] ipblocklist-functions.pl: Add download_and_create_blocklist function. This function is responisible for downloading and converting the blocklist into an ipset compatible format. The only required argument is the blocklist (in upper letter format) which should be performed. It automatically will setup an upstream proxy (if configured) and grab the file specified in the blocklist vendor configuration hash. There is a maximum amount of five attempts until the script gives up and returns a "dl_error". In case the server responses with "Not Modified" (Code 304) a "not_modified" will be returned. If the blocklist successfully has been grabbed, the modification date get stored for further purposes and the list content will be converted and stored in an ipset compatible format. Signed-off-by: Stefan Schantl Inspired-by: Tim FitzGeorge --- config/cfgroot/ipblocklist-functions.pl | 205 +++++++++++++++++++++++- 1 file changed, 202 insertions(+), 3 deletions(-) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index f7ffbdbca..f312e349a 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -21,13 +21,29 @@ package IPblocklist; -require '/var/ipfire/ipblocklist/sources'; +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/ipblocklist/sources"; + +# The directory where all ipblocklist related files and settings are stored. +our $settings_dir = "/var/ipfire/ipblocklist"; + +# Main settings file. +our $settings_file = "$settings_dir/settings"; + +# The file which keeps the time, when a blocklist last has been modified. +my $modified_file = "$settings_dir/modified"; # Location where the blocklists in ipset compatible format are stored. -our $blocklist_dir = "/var/lib/ipblocklist"; +my $blocklist_dir = "/var/lib/ipblocklist"; # File extension of the blocklist files. -our $blocklist_file_extension = ".conf"; +my $blocklist_file_extension = ".conf"; + +# Hash which calls the correct parser functions. +my %parsers = ( + 'ip-or-net-list' => \&parse_ip_or_net_list, + 'dshield' => \&parse_dshield +); # ## Function to get all available blocklists. @@ -58,4 +74,187 @@ sub get_ipset_db_file($) { return $file; } +# +## The main download_and_create blocklist function. +## +## Uses LWP to download a given blocklist. The If-Modified-Since header is +## specified in the request so that only updated lists are downloaded (providing +## that the server supports this functionality). +## +## Once downloaded the list gets parsed, converted and stored in an ipset compatible +## format. +## +## Parameters: +## list The name of the blocklist +## +## Returns: +## nothing - On success +## not_modified - In case the servers responds with "Not modified" (304) +## dl_error - If the requested blocklist could not be downloaded. +# +sub download_and_create_blocklist($) { + my ($list) = @_; + + # Check if the given blockist is known and data available. + unless($IPblocklist::List::sources{$list}) { + # No valid data for this blocklist - exit and return "1". + return 1; + } + + # The allowed maximum download size in bytes. + my $max_dl_bytes = 10_485_760; + + # The amount of download attempts before giving up and + # logging an error. + my $max_dl_attempts = 5; + + # Read proxysettings. + my %proxysettings=(); + &General::readhash("${General::swroot}/proxy/settings", \%proxysettings); + + # Load required perl module to handle the download. + use LWP::UserAgent; + + # Create a user agent for downloading the blacklist + # Limit the download size for safety + my $ua = LWP::UserAgent->new ( + ssl_opts => { + SSL_ca_file => '/etc/ssl/cert.pem', + verify_hostname => 1, + }, + + max_size => $max_dl_bytes, + ); + + # Set timeout to 10 seconds. + $ua->timeout(10); + + # Check if an upstream proxy is configured. + if ($proxysettings{'UPSTREAM_PROXY'}) { + my $proxy_url; + + $proxy_url = "http://"; + + # Check if the proxy requires authentication. + if (($proxysettings{'UPSTREAM_USER'}) && ($proxysettings{'UPSTREAM_PASSWORD'})) { + $proxy_url .= "$proxysettings{'UPSTREAM_USER'}\:$proxysettings{'UPSTREAM_PASSWORD'}\@"; + } + + # Add proxy server address and port. + $proxy_url .= $proxysettings{'UPSTREAM_PROXY'}; + + # Setup proxy settings. + $ua->proxy(['http', 'https'], $proxy_url); + } + + # Gather the details, when a list got modified last time. + my %modified = (); + + # Read-in data if the file exists. + &General::readhash($modified_file, \%modified ) if (-e $modified_file); + + # Get the last modified time for this list. + my $last_modified = gmtime($modified{$list} || 0); + + my $dl_attempt = 1; + my $response; + + # Download and rety on failure loop. + while ($dl_attempt <= $max_dl_attempts) { + # Try to determine if there is a newer blocklist since last time and grab it. + $response = $ua->get($IPblocklist::List::sources{$list}{'url'}, 'If-Modified-Since' => $last_modified ); + + # Check if the download attempt was successfull. + if ($response->is_success) { + # We successfully grabbed the list - no more retries needed, break the loop. + # Further process the script code. + last; + + # Exit, if the server responds with "Not modified (304). + } elsif ($response->code == 304) { + # Exit and return "not modified". + return "not_modified"; + + # Exit and log an erro + } elsif ($dl_attempt eq $max_dl_attempts) { + # Exit and return "dl_error". + return "dl_error"; + } + + # Increase download attempt counter. + $dl_attempt++; + } + + # Update the timestamp for the new or modified list. + $modified{$list} = $response->last_modified; + + # Write-back the modified timestamps. + &General::writehash($modified_file, \%modified); + + # Parse and loop through the downloaded list. + my @blocklist = (); + + # Get the responsible parser for the current list. + my $parser = $parsers{$IPblocklist::List::sources{$list}{'parser'}}; + + # Loop through the grabbed raw list. + foreach my $line (split /[\r\n]+/, $response->content) { + # Remove newlines. + chomp $line; + + # Call the parser and obtain the addess or network. + my $address = &$parser($line); + + # Skip the line if it does not contain an address. + next unless ($address and $address =~ m/\d+\.\d+\.\d+\.\d+/); + + # Check if we got a single address. + if ($address =~ m|/32|) { + # Add /32 as prefix. + $address =~ s|/32||; + } + + # Push the address/network to the blocklist array. + push(@blocklist, $address); + } + + # Get amount of entries in the blocklist array. + my $list_entries = scalar(@blocklist); + + # Optain the filename for this blocklist to save. + my $file = &get_ipset_db_file($list); + + # Open the file for writing. + open(FILE, ">", "$file") or die "Could not write to $file. $!\n"; + + # Write file header. + print FILE "#Autogenerated file. Any custom changes will be overwritten!\n\n"; + + # Calculate the hashsize for better list performance. + my $hashsize = &_calculate_hashsize($list_entries); + + # Simply set the limit of list elements to the double of current list elements. + my $maxelem = $list_entries *2; + + # Write line to create the set. + # + # We safely can use hash:net as type because it supports single addresses and networks. + print FILE "create $list hash:net family inet hashsize $hashsize maxelem $maxelem -exist\n"; + + # Write line to flush the set itself during loading. + print FILE "flush $list\n"; + + # Loop through the array which contains the blocklist. + foreach my $entry (@blocklist) { + # Add the entry to the list. + print FILE "add $list $entry\n"; + } + + # Close the file handle. + close(FILE); + + # Finished. + return; +} + 1; From ab0179617dc7d9377aba2e45c1ae4ccccce4da6e Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Fri, 4 Mar 2022 22:08:16 +0100 Subject: [PATCH 14/58] ipblocklist-functions.pl: Add parser to obtain IP or Net addresses from a blocklist. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index f312e349a..9e862bb0e 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -257,4 +257,25 @@ sub download_and_create_blocklist($) { return; } +# +## sub parse_ip_or_net_list( line ) +## +## Parses an input line, looking for lines starting with an IP Address or +### Network specification. +## +## Parameters: +## line The line to parse +## +## Returns: +## Either an IP Address or a null string +# +sub parse_ip_or_net_list( $ ) { + my ($line) = @_; + + # Grab the IP address or network. + $line =~ m|^(\d+\.\d+\.\d+\.\d+(?:/\d+)?)|; + + # Return the grabbed address. + return $1; +} 1; From ac9b5d8e6b300cf9c404c05a756288aeb4b4ab90 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Fri, 4 Mar 2022 22:10:29 +0100 Subject: [PATCH 15/58] ipblocklist-functions.pl: Add parser of dshield. This vendor has a different list format and therefore requires an own parser. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index 9e862bb0e..9420fc948 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -278,4 +278,40 @@ sub parse_ip_or_net_list( $ ) { # Return the grabbed address. return $1; } + +# +## sub parse_dshield( line ) +## +## Parses an input line removing comments. +## +## The format is: +## Start Addrs End Addrs Netmask Nb Attacks Network Name Country email +## We're only interested in the start address and netmask. +## +## Parameters: +## line The line to parse +## +## Returns: +## Either and IP Address or a null string +# +sub parse_dshield( $ ) { + my ($line) = @_; + + # Skip coments. + return "" if ($line =~ m/^\s*#/); + + $line =~ s/#.*$//; + + # |Start addrs | |End Addrs | |Mask + $line =~ m|(\d+\.\d+\.\d+\.\d+(?:/\d+)?)\s+\d+\.\d+\.\d+\.\d+(?:/\d+)?\s+(\d+)|; + + # Return nothing if no start address could be grabbed. + return unless ($1); + + # Add /32 as prefix for single addresses and return it. + return "$1/32" unless ($2); + + # Return the obtained network. + return "$1/$2"; +} 1; From 0a4f60f28c6f8954493732f0f57ab0b097faf842 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Fri, 4 Mar 2022 22:11:48 +0100 Subject: [PATCH 16/58] ipblocklist-functions.pl: Add helper function to proper calculate the hashsize. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index 9420fc948..6da371a00 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -314,4 +314,18 @@ sub parse_dshield( $ ) { # Return the obtained network. return "$1/$2"; } + +# +## Helper function to proper calculate the hashsize. +# +sub _calculate_hashsize($) { + my ($list_entries) = @_; + + my $hashsize = 1; + $hashsize <<= 1 while ($hashsize < $list_entries); + + # Return the calculated hashsize. + return $hashsize; +} + 1; From d7dd5653419bc9303a3745a96168a4f78cb8122e Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sat, 5 Mar 2022 10:01:24 +0100 Subject: [PATCH 17/58] ipblocklist-functions.pl: Abort and return code if a list is empty or not parse-able. In case the downloaded list is empty or the parser is not able to parse it properly, the download_and_create_blocklist() function now exits and will return "empty_list" as new error code. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index 6da371a00..b6abb1bef 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -91,6 +91,8 @@ sub get_ipset_db_file($) { ## nothing - On success ## not_modified - In case the servers responds with "Not modified" (304) ## dl_error - If the requested blocklist could not be downloaded. +## empty_list - The downloaded blocklist is empty, or the parser was not able to parse +## it correctly. # sub download_and_create_blocklist($) { my ($list) = @_; @@ -218,6 +220,13 @@ sub download_and_create_blocklist($) { push(@blocklist, $address); } + # Check if the content could be parsed correctly and the blocklist + # contains at least one item. + unless(@blocklist) { + # No entries - exit and return "empty_list". + return "empty_list"; + } + # Get amount of entries in the blocklist array. my $list_entries = scalar(@blocklist); From a7bf1d9666f3e108486639cd4115b78a24235954 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 1 Mar 2022 17:36:51 +0100 Subject: [PATCH 18/58] rules.pl: Add code to deal with ipblocklists. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 432619184..c578405ba 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -26,6 +26,7 @@ require '/var/ipfire/general-functions.pl'; require "${General::swroot}/lang.pl"; require "/usr/lib/firewall/firewall-lib.pl"; require "${General::swroot}/location-functions.pl"; +require "${General::swroot}/ipblocklist-functions.pl"; # Set to one to enable debugging mode. my $DEBUG = 0; @@ -73,6 +74,10 @@ my %confignatfw=(); my %locationsettings = ( "LOCATIONBLOCK_ENABLED" => "off" ); +my %blocklistsettings= ( + "ENABLE" => "off", +); + my %ipset_loaded_sets = (); my @ipset_used_sets = (); @@ -82,6 +87,7 @@ my $configoutgoing = "${General::swroot}/firewall/outgoing"; my $locationfile = "${General::swroot}/firewall/locationblock"; my $configgrp = "${General::swroot}/fwhosts/customgroups"; my $netsettings = "${General::swroot}/ethernet/settings"; +my $blocklistfile = "${General::swroot}/ipblocklist/settings"; &General::readhash("${General::swroot}/firewall/settings", \%fwdfwsettings); &General::readhash("${General::swroot}/optionsfw/settings", \%fwoptions); @@ -97,9 +103,18 @@ if (-e "$locationfile") { &General::readhash("$locationfile", \%locationsettings); } +# Check if the ipblocklist settings file exits. +if (-e "$blocklistfile") { + # Read-in settings file. + &General::readhash("$blocklistfile", \%blocklistsettings); +} + # Get all available locations. my @locations = &Location::Functions::get_locations(); +# Get all supported blocklists. +my @blocklists = &IPblocklist::get_blocklists(); + # Name or the RED interface. my $RED_DEV = &General::get_red_interface(); @@ -144,6 +159,9 @@ sub main { # Load rules to block hostile networks. &drop_hostile_networks(); + # Handle ipblocklist. + &ipblocklist(); + # Reload firewall policy. run("/usr/sbin/firewall-policy"); @@ -708,6 +726,43 @@ sub drop_hostile_networks () { run("$IPTABLES -A HOSTILE -o $RED_DEV -m set --match-set $HOSTILE_CCODE dst -j HOSTILE_DROP"); } +sub ipblocklist () { + # Flush the ipblocklist chains. + run("$IPTABLES -F BLOCKLISTIN"); + run("$IPTABLES -F BLOCKLISTOUT"); + + # If the blocklist feature is disabled we are finished here. + if($blocklistsettings{'ENABLE'} ne "on") { + # Bye. + return; + } + + # Loop through the array of blocklists. + foreach my $blocklist (@blocklists) { + # Skip disabled blocklists. + next unless($blocklistsettings{$blocklist} eq "on"); + + # Call function to load the blocklist. + &ipset_restore($blocklist); + + # Create iptables chain. + run("$IPTABLES -N ${blocklist}_DROP"); + + # Check if logging is enables. + if($blocklistsettings{'LOGGING'} eq "on") { + # Create logging rule. + run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\""); + } + + # Create Drop rule. + run("$IPTABLES A ${blocklist}_DROP -j DROP"); + + # Add the rules to check against the set + run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP"); + run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -m set --match-set $blocklist dst -j ${blocklist}_DROP"); + } +} + sub get_protocols { my $hash = shift; my $key = shift; @@ -986,6 +1041,14 @@ sub ipset_restore ($) { # If the set is not loaded, we have to rename it to proper use it. run("$IPSET rename $loc_set $set"); } + + # Check if the given set name is a blocklist. + } elsif ($set ~~ @blocklists) { + # Get the database file for the given blocklist. + my $db_file = &IPblocklist::get_ipset_db_file($set); + + # Call function to restore/load the set. + &ipset_call_restore($db_file); } # Store the restored set to the hash to prevent from loading it again. From 8d12d12a4f2d6cd071517a0cc0d3cf885536e6a5 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Sun, 6 Mar 2022 15:07:17 +0100 Subject: [PATCH 19/58] ipblocklist-functions.pl: Add function to get the holdoff_rate of a given list. The function will return the rate in seconds based on the configured rate value in the blocklist sources file and the given blocklist. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index b6abb1bef..284503a02 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -337,4 +337,43 @@ sub _calculate_hashsize($) { return $hashsize; } +# +## sub get_holdoff_rate(list) +## +## This function is used to get the holdoff rate in seconds for a desired provider, +## based on the configured rate limit in minutes (m), hours (h) or days (d) in the +## blacklist sources settings file. +## +# +sub get_holdoff_rate($) { + my ($list) = @_; + + # Grab the configured lookup rate for the given list. + my $rate = $IPblocklist::List::sources{$list}{'rate'}; + + # Split the grabbed rate into value and unit. + my ($value, $unit) = (uc $rate) =~ m/(\d+)([DHM]?)/; + + # Days + if ($unit eq 'D') { + $value *= 60 * 60 * 24; + + # Minutes + } elsif ($unit eq 'M') { + $value *= 60; + + # Everything else - assume hours. + } else { + $value *= 60 * 60; + } + + # Sanity check - limit to range 5 min .. 1 week + + # d h m s + $value = 5 * 60 if ($value < 5 * 60); + $value = 7 * 24 * 60 * 60 if ($value > 7 * 24 * 60 * 60); + + return $value; +} + 1; From d8113820e37a8ca29c2190f9a0c2ccfefeb87841 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 6 Mar 2022 15:09:18 +0100 Subject: [PATCH 20/58] ipblocklist-functions.pl: Store the local time if no last modified could be determined. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index 284503a02..cde81684f 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -188,7 +188,11 @@ sub download_and_create_blocklist($) { } # Update the timestamp for the new or modified list. - $modified{$list} = $response->last_modified; + if($response->last_modified) { + $modified{$list} = $response->last_modified; + } else { + $modified{$list} = time(); + } # Write-back the modified timestamps. &General::writehash($modified_file, \%modified); From 7f4829de97dff28d9368015b9e74a701a3d5dfce Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 6 Mar 2022 15:09:58 +0100 Subject: [PATCH 21/58] ipblocklist-functions.pl: Allow export of modified_file and blocklist_dir values. They so easily can be accessed by other perl scripts. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index cde81684f..f0e5ff73f 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -31,10 +31,10 @@ our $settings_dir = "/var/ipfire/ipblocklist"; our $settings_file = "$settings_dir/settings"; # The file which keeps the time, when a blocklist last has been modified. -my $modified_file = "$settings_dir/modified"; +our $modified_file = "$settings_dir/modified"; # Location where the blocklists in ipset compatible format are stored. -my $blocklist_dir = "/var/lib/ipblocklist"; +our $blocklist_dir = "/var/lib/ipblocklist"; # File extension of the blocklist files. my $blocklist_file_extension = ".conf"; From ec1878771a278faaa4922955a3d1a1db7c0039f8 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 6 Mar 2022 15:11:48 +0100 Subject: [PATCH 22/58] ipblocklist-update: Introduce script to automatically update blacklists. Signed-off-by: Stefan Schantl --- src/scripts/update-ipblocklists | 145 ++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 src/scripts/update-ipblocklists diff --git a/src/scripts/update-ipblocklists b/src/scripts/update-ipblocklists new file mode 100644 index 000000000..16ed3da38 --- /dev/null +++ b/src/scripts/update-ipblocklists @@ -0,0 +1,145 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2022 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU 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 General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; +use POSIX; + +# Load perl module to talk to the kernel syslog. +use Sys::Syslog qw(:DEFAULT setlogsock); + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/ipblocklist-functions.pl"; +require "${General::swroot}/lang.pl"; + +# Hash to store the settings. +my %settings = (); + +# The user and group name as which this script should be run. +my $run_as = 'nobody'; + +# Get user and group id of the user. +my ( $uid, $gid ) = ( getpwnam $run_as )[ 2, 3 ]; + +# Check if the script currently runs as root. +if ( $> == 0 ) { + # Drop privileges and switch to the specified user and group. + POSIX::setgid( $gid ); + POSIX::setuid( $uid ); +} + +# Establish the connection to the syslog service. +openlog('ipblocklist', 'cons,pid', 'user'); + +# Grab the configured providers. +&General::readhash("${General::swroot}/ipblocklist/settings", \%settings); + +# Check if the blocklist feature is enabled. +unless ($settings{'ENABLE'} eq "on") { + # Exit. + exit 0; +} + +# Check if the red device is active. +unless (-e "${General::swroot}/red/active") { + # Log to syslog. + &_log_to_syslog(" Could not update any blocklist - The system is offline!"); + + # Exit. + exit 1; +} + +# Get all available blocklists. +my @blocklists = &IPblocklist::get_blocklists(); + +# Gather the details, when a list got modified last time. +my %modified = (); + +# Read-in data if the file exists. +&General::readhash($IPblocklist::modified_file, \%modified ) if (-e $IPblocklist::modified_file); + +# Loop through the array of blocklists. +foreach my $blocklist (@blocklists) { + # Skip if the blocklist is not enabled. + next if($settings{$blocklist} ne "on"); + + # Get current time. + my $time = time(); + + # Get time, when the blocklist has been downloaded last. + my $last_download_time = $modified{$blocklist}; + + # Get the holdoff rate in seconds for the current processed blocklist. + my $rate_time = &IPblocklist::get_holdoff_rate($blocklist); + + # Calculate holdoff time. + my $holdoff_time = $last_download_time + $rate_time; + + # Check if enough time has passed since the last download of the list. + if ($time <= $holdoff_time) { + # To frequent updates, log to syslog. + &_log_to_syslog(" Skipping $blocklist blocklist - Too frequent update attempts!"); + + # Skip this provider. + next; + } + + # Try to download and update the blocklist. + my $return = &IPblocklist::download_and_create_blocklist($blocklist); + + # Check if we got a return code. + if ($return) { + # Handle different return codes. + if ($return eq "not_modified") { + # Log notice to syslog. + &_log_to_syslog(" Skipping $blocklist blocklist - It has not been modified!"); + } elsif ($return eq "dl_error") { + # Log error to the syslog. + &_log_to_syslog(" Could not update $blocklist blocklist - Download error\!"); + } else { + # Log error to syslog. + &_log_to_syslog(" Could not update $blocklist blocklist - Unexpected error\!"); + } + } else { + # Log successfull update. + &_log_to_syslog(" Successfully updated $blocklist blocklist."); + } +} + +END { + # Close connection to syslog. + closelog(); +} + +# +# Tiny function to sent the error message to the syslog. +# +sub _log_to_syslog($) { + my ($message) = @_; + + # The syslog function works best with an array based input, + # so generate one before passing the message details to syslog. + my @syslog = ("ERR", "$message"); + + # Send the log message. + syslog(@syslog); +} + +1; From 5d2421534115c0953189d71d26fce8d1fe5dfd46 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Mon, 27 Apr 2020 15:04:38 +0100 Subject: [PATCH 23/58] ipblocklist: WUI Settings page Signed-off-by: Tim FitzGeorge --- html/cgi-bin/ipblocklist.cgi | 463 +++++++++++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 html/cgi-bin/ipblocklist.cgi diff --git a/html/cgi-bin/ipblocklist.cgi b/html/cgi-bin/ipblocklist.cgi new file mode 100644 index 000000000..28b42edf2 --- /dev/null +++ b/html/cgi-bin/ipblocklist.cgi @@ -0,0 +1,463 @@ +#!/usr/bin/perl + +############################################################################### +# # +# IPFire.org - A linux based firewall # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU 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 General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +# Copyright (C) 2018 - 2020 The IPFire Team # +# # +############################################################################### + +use strict; +use CGI qw/:standard/; +# enable the following only for debugging purposes +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; +use Sort::Naturally; +use Socket; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; + +############################################################################### +# Configuration variables +############################################################################### + +my $settings = "${General::swroot}/ipblacklist/settings"; +my $sources = "${General::swroot}/ipblacklist/sources"; +my $getipstat = '/usr/local/bin/getipstat'; +my $getipsetstat = '/usr/local/bin/getipsetstat'; +my $control = '/usr/local/bin/ipblacklistctrl'; +my $lockfile = '/var/run/ipblacklist.pid'; +my %cgiparams = ('ACTION' => ''); + +############################################################################### +# Variables +############################################################################### + +my $errormessage = ''; +my $updating = 0; +my %mainsettings; +my %color; +my %sources; +my %stats; + +# Default settings - normally overwritten by settings file + +my %settings = ( 'DEBUG' => 0, + 'LOGGING' => 'on', + 'ENABLE' => 'off' ); + +# Read all parameters + +Header::getcgihash( \%cgiparams); +General::readhash( "${General::swroot}/main/settings", \%mainsettings ); +General::readhash( "/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color ); +General::readhash( $settings, \%settings ) if (-r $settings); +eval qx|/bin/cat $sources| if (-r $sources); + +# Show Headers + +Header::showhttpheaders(); + +# Process actions + +if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") +{ + # Save Button + + my %new_settings = ( 'ENABLE' => 'off', + 'LOGGING' => 'off', + 'DEBUG' => 0 ); + + foreach my $item ('LOGGING', 'ENABLE', keys %sources) + { + $new_settings{$item} = (exists $cgiparams{$item}) ? 'on' : 'off'; + + $updating = 1 if (not exists $settings{$item} or $new_settings{$item} ne $settings{$item}); + } + + # Check for redundant blacklists being enabled + + foreach my $list (keys %sources) + { + if (exists $new_settings{$list} and + $new_settings{$list} eq 'on' and + exists $sources{$list}{'disable'}) + { + my @disable; + + if ('ARRAY' eq ref $sources{$list}{'disable'}) + { + @disable = @{ $sources{$list}{'disable'} }; + } + else + { + @disable = ( $sources{$list}{'disable'} ); + } + + foreach my $disable (@disable) + { + if ($new_settings{$disable} eq 'on') + { + $new_settings{$disable} = 'off'; + + $updating = 1; + $errormessage .= "$Lang::tr{'ipblacklist disable pre'} $disable " . + "$Lang::tr{'ipblacklist disable mid'} $list $Lang::tr{'ipblacklist disable post'}
\n"; + } + } + } + } + + if ($settings{'LOGGING'} ne $new_settings{'LOGGING'}) + { + if ($new_settings{'LOGGING'} eq 'on') + { + system( "$control log-on" ); + } + else + { + system( "$control log-off" ); + } + } + + if ($settings{'ENABLE'} ne $new_settings{'ENABLE'}) + { + if ($new_settings{'ENABLE'} eq 'on') + { + system( "$control enable" ); + } + else + { + system( "$control disable" ); + } + + $updating = 1; + } + + %settings = %new_settings; + + if ($errormessage) + { + $updating = 0; + } + else + { + General::writehash($settings, \%new_settings); + + if ($updating) + { + system( "$control update &" ); + show_running(); + exit 0; + } + } +} + +if (is_running()) +{ + show_running(); + exit 0; +} + +# Show site + +Header::openpage($Lang::tr{'ipblacklist'}, 1, ''); +Header::openbigbox('100%', 'left'); + +error() if ($errormessage); + +configsite(); + +# End of page + +Header::closebigbox(); +Header::closepage(); + +exit 0; + + +#------------------------------------------------------------------------------ +# sub configsite() +# +# Displays configuration +#------------------------------------------------------------------------------ + +sub configsite +{ + # Find preselections + + my $enable = 'checked'; + Header::openbox('100%', 'left', $Lang::tr{'settings'}); + + #### JAVA SCRIPT #### + + print< + \$(document).ready(function() + { + // Show/Hide elements when ENABLE checkbox is checked. + if (\$("#ENABLE").attr("checked")) + { + \$(".sources").show(); + } + else + { + \$(".sources").hide(); + } + + // Toggle Source list elements when "ENABLE" checkbox is clicked + \$("#ENABLE").change(function() + { + \$(".sources").toggle(); + }); + }); + +END + + ##### JAVA SCRIPT END #### + + # Enable checkbox + + $enable = ($settings{'ENABLE'} eq 'on') ? ' checked' : ''; + + print< + + + + + +
$Lang::tr{'ipblacklist use ipblacklists'}

+ +END + + # The following are only displayed if the blacklists are enabled + + $enable = ($settings{'LOGGING'} eq 'on') ? ' checked' : ''; + + print < + + + + + +
$Lang::tr{'ipblacklist log'}
+

+

$Lang::tr{'ipblacklist blacklist settings'}

+ + + + + + + +END + + # Iterate through the list of sources + + my $lines = 0; + + foreach my $list (sort keys %sources) + { + my $name = escapeHTML( $sources{$list}{'name'} ); + my $category = $Lang::tr{"ipblacklist category $sources{$list}{'category'}"}; + $enable = ''; + my $col = ($lines++ % 2) ? "bgcolor='$color{'color20'}'" : "bgcolor='$color{'color22'}'"; + + $enable = ' checked' if (exists $settings{$list} and $settings{$list} eq 'on'); + + print < + + + + \n +END + } + + # The save button at the bottom of the table + + print < + +
$Lang::tr{'ipblacklist id'}$Lang::tr{'ipblacklist name'}$Lang::tr{'ipblacklist category'}$Lang::tr{'ipblacklist enable'}
+END + + if ($sources{$list}{info}) + { + print "$list\n"; + } + else + { + print "$list\n"; + } + + print < + $name$category
+ + + +
+END + + Header::closebox(); +} + + +#------------------------------------------------------------------------------ +# sub get_ipset_stats() +# +# Gets the number of entries in each IPSet. +#------------------------------------------------------------------------------ + +sub get_ipset_stats +{ + my $name; + + system( $getipsetstat ); + + if (-r '/var/tmp/ipsets.txt') + { + open STATS, '<', '/var/tmp/ipsets.txt' or die "Can't open IP Sets stats file: $!"; + + foreach my $line () + { + if ($line =~ m/Name: (\w+)/) + { + $name = $1; + next; + } + + if ($line =~ m/Number of entries: (\d+)/) + { + $stats{$name}{'size'} = $1; + } + } + + close STATS; + + unlink( '/var/tmp/ipsets.txt' ); + } +} + + +#------------------------------------------------------------------------------ +# sub is_running() +# +# Checks to see if the main script is running +#------------------------------------------------------------------------------ + +sub is_running +{ + return 0 unless (-r $lockfile); + + open LOCKFILE, '<', $lockfile or die "Can't open lockfile"; + my $pid = ; + close LOCKFILE; + + chomp $pid; + + return (-e "/proc/$pid"); +} + + +#------------------------------------------------------------------------------ +# sub show_running +# +# Displayed when update is running. +# Shows a 'working' message plus some information about the IPSets. +#------------------------------------------------------------------------------ + +sub show_running +{ + # Open site + + Header::openpage( $Lang::tr{'ipblacklist'}, 1, '' ); + Header::openbigbox( '100%', 'center' ); + error(); + Header::openbox( 'Working', 'center', "$Lang::tr{'ipblacklist working'}" ); + + print < + + + $Lang::tr{  + + + +
+ + +END + + get_ipset_stats(); + + foreach my $name (sort keys %stats) + { + print "\n" if (exists $stats{$name}{'size'}); + } + + print < +END + + Header::closebox(); + + Header::closebigbox(); + Header::closepage(); +} + + +#------------------------------------------------------------------------------ +# sub error() +# +# Shows error messages +#------------------------------------------------------------------------------ + +sub error +{ + Header::openbox('100%', 'left', $Lang::tr{'error messages'}); + print "$errormessage\n"; + print " \n"; + Header::closebox(); +} + + +#------------------------------------------------------------------------------ +# sub format_time( seconds ) +# +# Converts time in seconds to HH:MM:SS +#------------------------------------------------------------------------------ + +sub format_time($) { + my $time = shift; + + my $seconds = $time % 60; + my $minutes = $time / 60; + + my $hours = 0; + if ($minutes >= 60) { + $hours = $minutes / 60; + $minutes %= 60; + } + + return sprintf("%3d:%02d:%02d", $hours, $minutes, $seconds); +} From 8f49b75b087bbff7b989ce7a94b6f1bd33b1edda Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 6 Mar 2022 20:23:55 +0100 Subject: [PATCH 24/58] ipblocklist.cgi: Adjust CGI to work with backend from ipblocklist-functions.pl * Slightly adjust code indention. * Remove Java Script code for show/hiding. * Remove unnedded functions. Signed-off-by: Stefan Schantl --- html/cgi-bin/ipblocklist.cgi | 516 +++++++++++------------------------ 1 file changed, 154 insertions(+), 362 deletions(-) diff --git a/html/cgi-bin/ipblocklist.cgi b/html/cgi-bin/ipblocklist.cgi index 28b42edf2..99ce68d17 100644 --- a/html/cgi-bin/ipblocklist.cgi +++ b/html/cgi-bin/ipblocklist.cgi @@ -22,27 +22,24 @@ ############################################################################### use strict; -use CGI qw/:standard/; + # enable the following only for debugging purposes #use warnings; #use CGI::Carp 'fatalsToBrowser'; -use Sort::Naturally; -use Socket; require '/var/ipfire/general-functions.pl'; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; +require "${General::swroot}/ipblocklist-functions.pl"; + +# Import blockist sources and settings file. +require "${General::swroot}/ipblocklist/sources"; ############################################################################### # Configuration variables ############################################################################### -my $settings = "${General::swroot}/ipblacklist/settings"; -my $sources = "${General::swroot}/ipblacklist/sources"; -my $getipstat = '/usr/local/bin/getipstat'; -my $getipsetstat = '/usr/local/bin/getipsetstat'; -my $control = '/usr/local/bin/ipblacklistctrl'; -my $lockfile = '/var/run/ipblacklist.pid'; +my $settings = "${General::swroot}/ipblocklist/settings"; my %cgiparams = ('ACTION' => ''); ############################################################################### @@ -53,143 +50,95 @@ my $errormessage = ''; my $updating = 0; my %mainsettings; my %color; -my %sources; -my %stats; # Default settings - normally overwritten by settings file - -my %settings = ( 'DEBUG' => 0, - 'LOGGING' => 'on', - 'ENABLE' => 'off' ); +my %settings = ( + 'DEBUG' => 0, + 'LOGGING' => 'on', + 'ENABLE' => 'off' +); # Read all parameters +&Header::getcgihash( \%cgiparams); +&General::readhash( "${General::swroot}/main/settings", \%mainsettings ); +&General::readhash( "/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color ); -Header::getcgihash( \%cgiparams); -General::readhash( "${General::swroot}/main/settings", \%mainsettings ); -General::readhash( "/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color ); -General::readhash( $settings, \%settings ) if (-r $settings); -eval qx|/bin/cat $sources| if (-r $sources); +# Get list of supported blocklists. +my @blocklists = &IPblocklist::get_blocklists(); # Show Headers - -Header::showhttpheaders(); +&Header::showhttpheaders(); # Process actions +if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") { + # Array to store if blocklists are missing on the system + # and needs to be downloaded first. + my @missing_blocklists = (); -if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") -{ - # Save Button + # Loop through the array of supported blocklists. + foreach my $blocklist (@blocklists) { + # Skip the blocklist if it is not enabled. + next if($cgiparams{$blocklist} ne "on"); - my %new_settings = ( 'ENABLE' => 'off', - 'LOGGING' => 'off', - 'DEBUG' => 0 ); + # Get the file name which keeps the converted blocklist. + my $ipset_db_file = &IPblocklist::get_ipset_db_file($blocklist); - foreach my $item ('LOGGING', 'ENABLE', keys %sources) - { - $new_settings{$item} = (exists $cgiparams{$item}) ? 'on' : 'off'; + # Check if the blocklist already has been downloaded. + if(-f "$ipset_db_file") { + # Blocklist already exits, we can skip it. + next; + } else { + # Blocklist not present, store in array to download it. + push(@missing_blocklists, $blocklist); + } + } - $updating = 1 if (not exists $settings{$item} or $new_settings{$item} ne $settings{$item}); - } + # Check if the red device is not active and blocklists are missing. + if ((not -e "${General::swroot}/red/active") && (@missing_blocklists)) { + # The system is offline, cannot download the missing blocklists. + # Store an error message. + $errormessage = "$Lang::tr{'system is offline'}"; + } else { + # Loop over the array of missing blocklists. + foreach my $missing_blocklist (@missing_blocklists) { + # Call the download and convert function to get the missing blocklist. + my $status = &IPblocklist::download_and_create_blocklist($missing_blocklist); - # Check for redundant blacklists being enabled + # Check if there was an error during download. + # XXX - fill with messages. + if ($status eq "dl_error") { + $errormessage = "XXX - dl_error"; + } elsif ($status eq "empty_list") { + $errormessage = "XXX - empty"; + } + } + } - foreach my $list (keys %sources) - { - if (exists $new_settings{$list} and - $new_settings{$list} eq 'on' and - exists $sources{$list}{'disable'}) - { - my @disable; + # Check if there was an error. + unless($errormessage) { + # Write configuration hash. + &General::writehash($settings, \%cgiparams); - if ('ARRAY' eq ref $sources{$list}{'disable'}) - { - @disable = @{ $sources{$list}{'disable'} }; - } - else - { - @disable = ( $sources{$list}{'disable'} ); - } - - foreach my $disable (@disable) - { - if ($new_settings{$disable} eq 'on') - { - $new_settings{$disable} = 'off'; - - $updating = 1; - $errormessage .= "$Lang::tr{'ipblacklist disable pre'} $disable " . - "$Lang::tr{'ipblacklist disable mid'} $list $Lang::tr{'ipblacklist disable post'}
\n"; - } - } - } - } - - if ($settings{'LOGGING'} ne $new_settings{'LOGGING'}) - { - if ($new_settings{'LOGGING'} eq 'on') - { - system( "$control log-on" ); - } - else - { - system( "$control log-off" ); - } - } - - if ($settings{'ENABLE'} ne $new_settings{'ENABLE'}) - { - if ($new_settings{'ENABLE'} eq 'on') - { - system( "$control enable" ); - } - else - { - system( "$control disable" ); - } - - $updating = 1; - } - - %settings = %new_settings; - - if ($errormessage) - { - $updating = 0; - } - else - { - General::writehash($settings, \%new_settings); - - if ($updating) - { - system( "$control update &" ); - show_running(); - exit 0; - } - } -} - -if (is_running()) -{ - show_running(); - exit 0; + # XXX display firewall reload stuff + } } # Show site +&Header::openpage($Lang::tr{'ipblocklist'}, 1, ''); +&Header::openbigbox('100%', 'left'); -Header::openpage($Lang::tr{'ipblacklist'}, 1, ''); -Header::openbigbox('100%', 'left'); +# Display error message if there was one. +&error() if ($errormessage); -error() if ($errormessage); +# Read-in ipblocklist settings. +&General::readhash( $settings, \%settings ) if (-r $settings); -configsite(); +# Display configuration section. +&configsite(); # End of page - -Header::closebigbox(); -Header::closepage(); - -exit 0; +&Header::closebigbox(); +&Header::closepage(); #------------------------------------------------------------------------------ @@ -198,266 +147,109 @@ exit 0; # Displays configuration #------------------------------------------------------------------------------ -sub configsite -{ - # Find preselections +sub configsite { + # Find preselections + my $enable = 'checked'; - my $enable = 'checked'; - Header::openbox('100%', 'left', $Lang::tr{'settings'}); + &Header::openbox('100%', 'left', $Lang::tr{'settings'}); - #### JAVA SCRIPT #### + # Enable checkbox + $enable = ($settings{'ENABLE'} eq 'on') ? ' checked' : ''; - print< - \$(document).ready(function() - { - // Show/Hide elements when ENABLE checkbox is checked. - if (\$("#ENABLE").attr("checked")) - { - \$(".sources").show(); - } - else - { - \$(".sources").hide(); - } - - // Toggle Source list elements when "ENABLE" checkbox is clicked - \$("#ENABLE").change(function() - { - \$(".sources").toggle(); - }); - }); - +print< +
$Lang::tr{'ipblacklist id'}$Lang::tr{'ipblacklist entries'}
$name$stats{$name}{'size'}
+ + + + +
$Lang::tr{'ipblocklist use ipblocklists'}

END - ##### JAVA SCRIPT END #### + # The following are only displayed if the blacklists are enabled + $enable = ($settings{'LOGGING'} eq 'on') ? ' checked' : ''; - # Enable checkbox +print < + + + + + +
$Lang::tr{'ipblocklist log'}
- $enable = ($settings{'ENABLE'} eq 'on') ? ' checked' : ''; - - print< - - - - - -
$Lang::tr{'ipblacklist use ipblacklists'}

+

+

$Lang::tr{'ipblocklist blocklist settings'}

+ + + + + + + END - # The following are only displayed if the blacklists are enabled + # Iterate through the list of sources + my $lines = 0; - $enable = ($settings{'LOGGING'} eq 'on') ? ' checked' : ''; + foreach my $blocklist (@blocklists) { + # Display blocklist name or provide a link to the website if available. + my $website = "$blocklist"; + if ($IPblocklist::List::sources{$blocklist}{info}) { + $website ="$blocklist"; + } - print < -
$Lang::tr{'ipblocklist id'}$Lang::tr{'ipblocklist name'}$Lang::tr{'ipblocklist category'}$Lang::tr{'ipblocklist enable'}
- - - - -
$Lang::tr{'ipblacklist log'}
-

-

$Lang::tr{'ipblacklist blacklist settings'}

- - - - - - - + # Get the full name for the blocklist. + my $name = &CGI::escapeHTML( $IPblocklist::List::sources{$blocklist}{'name'} ); + + # Get category for this blocklist. + my $category = $Lang::tr{"ipblocklist category $IPblocklist::List::sources{$blocklist}{'category'}"}; + + # Determine if the blocklist is enabled. + my $enable = ''; + $enable = 'checked' if ($settings{$blocklist} eq 'on'); + + # Set colour for the table columns. + my $col = ($lines++ % 2) ? "bgcolor='$color{'color20'}'" : "bgcolor='$color{'color22'}'"; + + +print < + + + + + +END + } + +# The save button at the bottom of the table +print < + + + +
$Lang::tr{'ipblacklist id'}$Lang::tr{'ipblacklist name'}$Lang::tr{'ipblacklist category'}$Lang::tr{'ipblacklist enable'}
$website$name$category
+ + + +
+ END - # Iterate through the list of sources - - my $lines = 0; - - foreach my $list (sort keys %sources) - { - my $name = escapeHTML( $sources{$list}{'name'} ); - my $category = $Lang::tr{"ipblacklist category $sources{$list}{'category'}"}; - $enable = ''; - my $col = ($lines++ % 2) ? "bgcolor='$color{'color20'}'" : "bgcolor='$color{'color22'}'"; - - $enable = ' checked' if (exists $settings{$list} and $settings{$list} eq 'on'); - - print < - -END - - if ($sources{$list}{info}) - { - print "$list\n"; - } - else - { - print "$list\n"; - } - - print < - $name - $category - - \n -END - } - - # The save button at the bottom of the table - - print < - - - - - -
-END - - Header::closebox(); + &Header::closebox(); } - -#------------------------------------------------------------------------------ -# sub get_ipset_stats() -# -# Gets the number of entries in each IPSet. -#------------------------------------------------------------------------------ - -sub get_ipset_stats -{ - my $name; - - system( $getipsetstat ); - - if (-r '/var/tmp/ipsets.txt') - { - open STATS, '<', '/var/tmp/ipsets.txt' or die "Can't open IP Sets stats file: $!"; - - foreach my $line () - { - if ($line =~ m/Name: (\w+)/) - { - $name = $1; - next; - } - - if ($line =~ m/Number of entries: (\d+)/) - { - $stats{$name}{'size'} = $1; - } - } - - close STATS; - - unlink( '/var/tmp/ipsets.txt' ); - } -} - - -#------------------------------------------------------------------------------ -# sub is_running() -# -# Checks to see if the main script is running -#------------------------------------------------------------------------------ - -sub is_running -{ - return 0 unless (-r $lockfile); - - open LOCKFILE, '<', $lockfile or die "Can't open lockfile"; - my $pid = ; - close LOCKFILE; - - chomp $pid; - - return (-e "/proc/$pid"); -} - - -#------------------------------------------------------------------------------ -# sub show_running -# -# Displayed when update is running. -# Shows a 'working' message plus some information about the IPSets. -#------------------------------------------------------------------------------ - -sub show_running -{ - # Open site - - Header::openpage( $Lang::tr{'ipblacklist'}, 1, '' ); - Header::openbigbox( '100%', 'center' ); - error(); - Header::openbox( 'Working', 'center', "$Lang::tr{'ipblacklist working'}" ); - - print < - - - $Lang::tr{  - - - -
- - -END - - get_ipset_stats(); - - foreach my $name (sort keys %stats) - { - print "\n" if (exists $stats{$name}{'size'}); - } - - print < -END - - Header::closebox(); - - Header::closebigbox(); - Header::closepage(); -} - - #------------------------------------------------------------------------------ # sub error() # # Shows error messages #------------------------------------------------------------------------------ -sub error -{ - Header::openbox('100%', 'left', $Lang::tr{'error messages'}); - print "$errormessage\n"; - print " \n"; - Header::closebox(); -} - - -#------------------------------------------------------------------------------ -# sub format_time( seconds ) -# -# Converts time in seconds to HH:MM:SS -#------------------------------------------------------------------------------ - -sub format_time($) { - my $time = shift; - - my $seconds = $time % 60; - my $minutes = $time / 60; - - my $hours = 0; - if ($minutes >= 60) { - $hours = $minutes / 60; - $minutes %= 60; - } - - return sprintf("%3d:%02d:%02d", $hours, $minutes, $seconds); +sub error { + &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); + print "$errormessage\n"; + print " \n"; + &Header::closebox(); } From 09a8d6127a59f5e2ca60bdad05a963d906fb935e Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Mon, 27 Apr 2020 15:05:16 +0100 Subject: [PATCH 25/58] ipblocklist: WUI Log page Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- html/cgi-bin/logs.cgi/ipblocklists.dat | 368 +++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100755 html/cgi-bin/logs.cgi/ipblocklists.dat diff --git a/html/cgi-bin/logs.cgi/ipblocklists.dat b/html/cgi-bin/logs.cgi/ipblocklists.dat new file mode 100755 index 000000000..c86cb8822 --- /dev/null +++ b/html/cgi-bin/logs.cgi/ipblocklists.dat @@ -0,0 +1,368 @@ +#!/usr/bin/perl +# +# SmoothWall CGIs +# +# This code is distributed under the terms of the GPL +# +# JC HERITIER +# page inspired from the initial firewalllog.dat +# +# Modified for IPFire by Christian Schmidt +# and Michael Tremer (www.ipfire.org) + +use strict; +use Getopt::Std; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/geoip-functions.pl"; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; + +require "${General::swroot}/ipblocklist-functions.pl"; +require "${General::swroot}/ipblocklist/sources"; + +use POSIX(); + +my %cgiparams=(); +my $errormessage = ''; + +my @shortmonths = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', + 'Sep', 'Oct', 'Nov', 'Dec' ); +my @longmonths = ( $Lang::tr{'january'}, $Lang::tr{'february'}, $Lang::tr{'march'}, + $Lang::tr{'april'}, $Lang::tr{'may'}, $Lang::tr{'june'}, $Lang::tr{'july'}, $Lang::tr{'august'}, + $Lang::tr{'september'}, $Lang::tr{'october'}, $Lang::tr{'november'}, + $Lang::tr{'december'} ); + +my @now = localtime(); +my $dow = $now[6]; +my $doy = $now[7]; +my $tdoy = $now[7]; +my $year = $now[5]+1900; + +$cgiparams{'DAY'} = $now[3]; +$cgiparams{'MONTH'} = $now[4]; +$cgiparams{'ACTION'} = ''; + +&Header::getcgihash(\%cgiparams); + +my $start = -1; +if ($ENV{'QUERY_STRING'} && $cgiparams{'ACTION'} ne $Lang::tr{'update'}) +{ + my @temp = split(',',$ENV{'QUERY_STRING'}); + $start = $temp[0]; + $cgiparams{'MONTH'} = $temp[1]; + $cgiparams{'DAY'} = $temp[2]; +} + +if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) || + !($cgiparams{'DAY'} =~ /^(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)$/)) +{ + $cgiparams{'DAY'} = $now[3]; + $cgiparams{'MONTH'} = $now[4]; +} +elsif($cgiparams{'ACTION'} eq '>>') +{ + my @temp_then=(); + my @temp_now = localtime(time); + $temp_now[4] = $cgiparams{'MONTH'}; + $temp_now[3] = $cgiparams{'DAY'}; + @temp_then = localtime(POSIX::mktime(@temp_now) + 86400); + ## Retrieve the same time on the next day - + ## 86400 seconds in a day + $cgiparams{'MONTH'} = $temp_then[4]; + $cgiparams{'DAY'} = $temp_then[3]; +} +elsif($cgiparams{'ACTION'} eq '<<') +{ + my @temp_then=(); + my @temp_now = localtime(time); + $temp_now[4] = $cgiparams{'MONTH'}; + $temp_now[3] = $cgiparams{'DAY'}; + @temp_then = localtime(POSIX::mktime(@temp_now) - 86400); + ## Retrieve the same time on the previous day - + ## 86400 seconds in a day + $cgiparams{'MONTH'} = $temp_then[4]; + $cgiparams{'DAY'} = $temp_then[3]; +} + +if (($cgiparams{'DAY'} ne $now[3]) || ($cgiparams{'MONTH'} ne $now[4])) +{ + my @then = (); + if ( ( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) || + ( $cgiparams{'MONTH'} > $now[4] ) ) { + @then = localtime(POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 )); + } else { + @then = localtime(POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 )); + } + $tdoy = $then[7]; + my $lastleap=($year-1)%4; + if ($tdoy>$doy) { + if ($lastleap == 0 && $tdoy < 60) { + $doy=$tdoy+366; + } else { + $doy=$doy+365; + } + } +} + +my $datediff=0; +my $dowd=0; +my $multifile=0; +if ($tdoy ne $doy) { + $datediff=int(($doy-$tdoy)/7); + $dowd=($doy-$tdoy)%7; + if (($dow-$dowd)<1) { + $datediff=$datediff+1; + } + if (($dow-$dowd)==0) { + $multifile=1; + } +} + +my $monthstr = $shortmonths[$cgiparams{'MONTH'}]; +my $longmonthstr = $longmonths[$cgiparams{'MONTH'}]; +my $day = $cgiparams{'DAY'}; +my $daystr=''; +if ($day <= 9) { + $daystr = " $day"; } +else { + $daystr = $day; +} + +my %lists; +my %directions; +my %sources = (); +my %settings = (); +&General::readhash("${General::swroot}/ipblocklist/settings", \%settings); + +# Get all available blocklists. +my @blocklists = &IPblocklist::get_blocklists(); + +foreach my $blocklist (@blocklists) +{ + $lists{$blocklist} = {} if ($settings{$blocklist} eq 'on'); +} + +my $skip=0; +my $filestr=''; +if ($datediff==0) { + $filestr="/var/log/messages"; +} else { + $filestr="/var/log/messages.$datediff"; + $filestr = "$filestr.gz" if -f "$filestr.gz"; +} + +if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { + $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; + $skip=1; + # Note: This is in case the log does not exist for that date +} + +my $lines = 0; +my $directions = 0; + +if (!$skip) +{ + while () + { + if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)\s*IN=(\w*)/) + { + my $list = $1; + + if ($2 =~ m/ppp|red/) + { + $lists{$list}{in}++; + $directions{in}++; + } + else + { + $lists{$list}{out}++; + $directions{out}++; + } + + $lines++; + } + + } + close (FILE); +} + +if ($multifile) { + $datediff=$datediff-1; + if ($datediff==0) { + $filestr="/var/log/messages"; + } else { + $filestr="/var/log/messages.$datediff"; + $filestr = "$filestr.gz" if -f "$filestr.gz"; + } + if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { + $errormessage="$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; + $skip=1; + } + if (!$skip) { + while () { + if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)\s*IN=(\w+)/) + { + my $list = $1; + + if ($2 =~ m/ppp|red/) + { + $lists{$list}{in}++; + $directions{in}++; + } + else + { + $lists{$list}{out}++; + $directions{out}++; + } + + $lines++; + } + } + close (FILE); + } +} + +my $MODNAME="fwlogs"; + +&Header::showhttpheaders(); +&Header::openpage($Lang::tr{'ipblocklist logs'}, 1, ''); +&Header::openbigbox('100%', 'left', '', $errormessage); + + +if ($errormessage) { + &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); + print "$errormessage \n"; + &Header::closebox(); +} + +&Header::openbox('100%', 'left', "$Lang::tr{'settings'}"); + +print < +
$Lang::tr{'ipblacklist id'}$Lang::tr{'ipblacklist entries'}
$name$stats{$name}{'size'}
+ + + + + + + + + +
$Lang::tr{'month'}:  +  $Lang::tr{'day'}:  +
+ +END +; + +&Header::closebox(); + +&Header::openbox('100%', 'left', $Lang::tr{'firewall log'}); +print "

$Lang::tr{'ipblocklist hits'} $longmonthstr $daystr: $lines

"; + +my %color = (); +my %mainsettings = (); +&General::readhash("${General::swroot}/main/settings", \%mainsettings); +&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); + +my @lists = sort keys (%lists); + +print < + + +$Lang::tr{'ipblocklist id'} +$Lang::tr{'ipblocklist category'} +$Lang::tr{'ipblocklist input'} +$Lang::tr{'ipblocklist output'} + + +$Lang::tr{'count'} +$Lang::tr{'percentage'} +$Lang::tr{'count'} +$Lang::tr{'percentage'} + +END +; + +$lines = 0; +my $lists = join ',', @lists; + +foreach my $list (@lists) +{ + my $col = ($lines++ % 2) ? "bgcolor='$color{'color20'}'" : "bgcolor='$color{'color22'}'"; + my $category = exists( $IPblocklist::List::sources{$list}) ? $Lang::tr{"ipblocklist category $IPblocklist::List::sources{$list}{'category'}"} : ' '; + + print ""; + + print "
"; + + if (exists($IPblocklist::List::sources{$list}) and $IPblocklist::List::sources{$list}{'info'}) + { + print "$list"; + } + else + { + print "$list"; + } + + print "$category"; + + foreach my $direction ('in', 'out') + { + my $count = $lists{$list}{$direction} || 0; + my $percent = $directions{$direction} > 0 ? $count * 100 / $directions{$direction} : 0; + $percent = sprintf("%.f", $percent); + print "$count"; + print "$percent%"; + } + + print ""; +} +print < +END +; + +&Header::closebox(); +&Header::closebigbox(); +&Header::closepage(); + +sub checkversion { + #Automatic Updates is disabled + return "0","0"; +} From cd07e6c6592aef6976ae35d80df272f329bbe04d Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Mon, 27 Apr 2020 15:06:14 +0100 Subject: [PATCH 26/58] ipblacklist: WUI Log details page Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- .../logs.cgi/showrequestfromblocklist.dat | 415 ++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100755 html/cgi-bin/logs.cgi/showrequestfromblocklist.dat diff --git a/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat b/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat new file mode 100755 index 000000000..d189a78d4 --- /dev/null +++ b/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat @@ -0,0 +1,415 @@ +#!/usr/bin/perl +# SmoothWall CGIs +# +# This code is distributed under the terms of the GPL +# +# JC HERITIER +# page inspired from the initial firewalllog.dat +# +# Modified for IPFire by Christian Schmidt (www.ipfire.org) + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; + +use POSIX(); + +#workaround to suppress a warning when a variable is used only once +my @dummy = ( ${Header::table2colour} ); +undef (@dummy); + +my %cgiparams=(); +my %logsettings=(); +my $errormessage = ''; + +my @shortmonths = ( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', + 'Sep', 'Oct', 'Nov', 'Dec' ); +my @longmonths = ( $Lang::tr{'january'}, $Lang::tr{'february'}, $Lang::tr{'march'}, + $Lang::tr{'april'}, $Lang::tr{'may'}, $Lang::tr{'june'}, $Lang::tr{'july'}, $Lang::tr{'august'}, + $Lang::tr{'september'}, $Lang::tr{'october'}, $Lang::tr{'november'}, + $Lang::tr{'december'} ); + +my @now = localtime(); +my $dow = $now[6]; +my $doy = $now[7]; +my $tdoy = $now[7]; +my $year = $now[5]+1900; + +$cgiparams{'DAY'} = $now[3]; +$cgiparams{'MONTH'} = $now[4]; +$cgiparams{'ACTION'} = ''; + +&Header::getcgihash(\%cgiparams); + +$logsettings{'LOGVIEW_REVERSE'} = 'off'; +&General::readhash("${General::swroot}/logging/settings", \%logsettings); + +my $start = -1; +my @blocklists; +if ($ENV{'QUERY_STRING'} && $cgiparams{'ACTION'} ne $Lang::tr{'update'}) +{ + my @temp = split(',',$ENV{'QUERY_STRING'}, 5); + $start = shift @temp; + $cgiparams{'MONTH'} = shift @temp; + $cgiparams{'DAY'} = shift @temp; + $cgiparams{'blocklist'} = shift @temp; + $cgiparams{'blocklists'} = shift @temp; +} + +if (!($cgiparams{'MONTH'} =~ /^(0|1|2|3|4|5|6|7|8|9|10|11)$/) || + !($cgiparams{'DAY'} =~ /^(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)$/)) +{ + $cgiparams{'DAY'} = $now[3]; + $cgiparams{'MONTH'} = $now[4]; +} +elsif($cgiparams{'ACTION'} eq '>>') +{ + my @temp_then=(); + my @temp_now = localtime(time); + $temp_now[4] = $cgiparams{'MONTH'}; + $temp_now[3] = $cgiparams{'DAY'}; + @temp_then = localtime(POSIX::mktime(@temp_now) + 86400); + ## Retrieve the same time on the next day - + ## 86400 seconds in a day + $cgiparams{'MONTH'} = $temp_then[4]; + $cgiparams{'DAY'} = $temp_then[3]; +} +elsif($cgiparams{'ACTION'} eq '<<') +{ + my @temp_then=(); + my @temp_now = localtime(time); + $temp_now[4] = $cgiparams{'MONTH'}; + $temp_now[3] = $cgiparams{'DAY'}; + @temp_then = localtime(POSIX::mktime(@temp_now) - 86400); + ## Retrieve the same time on the previous day - + ## 86400 seconds in a day + $cgiparams{'MONTH'} = $temp_then[4]; + $cgiparams{'DAY'} = $temp_then[3]; +} + +if (($cgiparams{'DAY'} ne $now[3]) || ($cgiparams{'MONTH'} ne $now[4])) +{ + my @then = (); + if ( ( $cgiparams{'MONTH'} eq $now[4]) && ($cgiparams{'DAY'} > $now[3]) || + ( $cgiparams{'MONTH'} > $now[4] ) ) { + @then = localtime(POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1901 )); + } else { + @then = localtime(POSIX::mktime( 0, 0, 0, $cgiparams{'DAY'}, $cgiparams{'MONTH'}, $year - 1900 )); + } + $tdoy = $then[7]; + my $lastleap=($year-1)%4; + if ($tdoy>$doy) { + if ($lastleap == 0 && $tdoy < 60) { + $doy=$tdoy+366; + } else { + $doy=$doy+365; + } + } +} + +if ($cgiparams{'blocklists'}) +{ + @blocklists = split ',', $cgiparams{'blocklists'}; +} + +my $datediff=0; +my $dowd=0; +my $multifile=0; +if ($tdoy ne $doy) { + $datediff=int(($doy-$tdoy)/7); + $dowd=($doy-$tdoy)%7; + if (($dow-$dowd)<1) { + $datediff=$datediff+1; + } + if (($dow-$dowd)==0) { + $multifile=1; + } +} + +my $monthstr = $shortmonths[$cgiparams{'MONTH'}]; +my $longmonthstr = $longmonths[$cgiparams{'MONTH'}]; +my $day = $cgiparams{'DAY'}; +my $daystr=''; +if ($day <= 9) { + $daystr = " $day"; } +else { + $daystr = $day; +} + +my $skip=0; +my $filestr=''; +if ($datediff==0) { + $filestr="/var/log/messages"; +} else { + $filestr="/var/log/messages.$datediff"; + $filestr = "$filestr.gz" if -f "$filestr.gz"; +} + +if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { + $errormessage = "$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; + $skip=1; + # Note: This is in case the log does not exist for that date +} +my $lines = 0; +my @log=(); +my $blaoklist = $cgiparams{blocklist}; + +if (!$skip) +{ + while () { + if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)IN=.*/) { + if($1 eq $blocklist){ + $log[$lines] = $_; + $lines++; + } + } + } + close (FILE); +} + +$skip=0; +if ($multifile) { + $datediff=$datediff-1; + if ($datediff==0) { + $filestr="/var/log/messages"; + } else { + $filestr="/var/log/messages.$datediff"; + $filestr = "$filestr.gz" if -f "$filestr.gz"; + } + if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { + $errormessage="$Lang::tr{'date not in logs'}: $filestr $Lang::tr{'could not be opened'}"; + $skip=1; + } + if (!$skip) { + while () { + if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)IN=.*/) { + if($1 eq $blocklist){ + $log[$lines] = $_; + $lines++; + } + } + } + close (FILE); + } +} + +&Header::showhttpheaders(); +&Header::openpage($Lang::tr{'ipblocklist log list'}, 1, ''); +&Header::openbigbox('100%', 'left', '', $errormessage); + +if ($errormessage) { + &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); + print "$errormessage \n"; + &Header::closebox(); +} + +&Header::openbox('100%', 'left', "$Lang::tr{'settings'}:"); + +print < + + + + + + + + + + + + +
$Lang::tr{'month'}:  +  $Lang::tr{'day'}:  +
$Lang::tr{'ipblocklist id'}
+ +END +; + +&Header::closebox(); + +&Header::openbox('100%', 'left', $Lang::tr{'ipblocklist log list'}); +print "

$Lang::tr{'firewall hits'} $longmonthstr $daystr: $lines

"; + +if ($start == -1) { + $start = $lines - ${Header::viewsize}; +} +if ($start >= $lines - ${Header::viewsize}) { $start = $lines - ${Header::viewsize}; }; +if ($start < 0) { $start = 0; } + +my $prev = $start - ${Header::viewsize}; +my $next = $start + ${Header::viewsize}; + +if ($prev < 0) { $prev = 0; } +if ($next >= $lines) { $next = -1 } +if ($start == 0) { $prev = -1; } + +if ($lines != 0) { &oldernewer(); } + +print < + +$Lang::tr{'time'} +$Lang::tr{'iface'} +$Lang::tr{'proto'} +$Lang::tr{'source'} +$Lang::tr{'src port'} +$Lang::tr{'destination'} +$Lang::tr{'dst port'} + +END +; + +my @slice = splice(@log, $start, ${Header::viewsize}); + +if ($logsettings{'LOGVIEW_REVERSE'} eq 'on') { @slice = reverse @slice; } + +$lines = 0; +foreach $_ (@slice) { + $a = $_; + # Check whether valid ipv4 or ipv6 address + if (($_ =~ /BLKLST_(\w+)IN=/)) { + if($1 eq $blocklist) { + + my $in = '-'; my $out = '-'; + my $srcaddr = ''; my $dstaddr = ''; + my $protostr = ''; + my $srcport = ''; my $dstport = ''; + + # If ipv6 uses bridge, the use PHYSIN, otherwise use IN + if ($_ =~ /(^.* ..:..:..) [\w\-]+ kernel:.*(IN=.*)(PHYSIN=.*)$/) {} + elsif ($_ =~ /(^.* ..:..:..) [\w\-]+ kernel:.*(IN=.*)$/) {} + my $timestamp = $1; my $packet = $2; + $timestamp =~ /(...) (..) (..:..:..)/; + my $month = $1; my $day = $2; my $time = $3; + + # If ipv6 uses bridge, the use PHYSIN and PHYSOUT, otherwise use IN and OUT + if ($a =~ /PHYSIN=(\w+)/) { $iface = $1; } elsif ($a =~ /IN=(\w+)/) { $iface = $1; } + if ($a =~ /PHYSOUT=(\w+)/) { $out = $1; } elsif ($a =~ /OUT=(\w+)/) { $out = $1; } + # Detect ipv4 and ipv6 addresses + if (($a =~ /SRC\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($a =~ /SRC\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { $srcaddr = $1; } + if (($a =~ /DST\=(([\d]{1,3})(\.([\d]{1,3})){3})/) or ($a =~ /DST\=(([0-9a-fA-F]{0,4})(\:([0-9a-fA-F]{0,4})){2,7})/)) { $dstaddr = $1; } + if ($a =~ /PROTO\=(\w+)/) { $protostr = $1; } + my $protostrlc = lc($protostr); + if ($a =~ /SPT\=([\d\.]+)/){ $srcport = $1; } + if ($a =~ /DPT\=([\d\.]+)/){ $dstport = $1; } + + if ($lines % 2) { + print "\n"; + } + else { + print "\n"; + } + print <$time + $iface + $protostr + + + +
$srcaddr
+ + $srcport + + + +
$dstaddr
+ + $dstport + +END + ; + $lines++; + } + } +} + +print < +END +; + +&oldernewer(); + + print"
$Lang::tr{
"; + +&Header::closebox(); + +&Header::closebigbox(); + +&Header::closepage(); + +sub oldernewer +{ + print < + +END + ; + + my $blocklists = join ',', @blocklists; + + print ""; + if ($prev != -1) { + print "$Lang::tr{'older'}"; + } + else { + print "$Lang::tr{'older'}"; + } + print "\n"; + + print ""; + if ($next != -1) { + print "$Lang::tr{'newer'}"; + } + else { + print "$Lang::tr{'newer'}"; + } + print "\n"; + + print < + +END + ; +} From 33a446d8e18d24337e60b4f5baa060403cd703b8 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Sun, 6 Mar 2022 20:53:07 +0100 Subject: [PATCH 27/58] Language file update for ipblocklist Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- langs/en/cgi-bin/en.pl | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/langs/en/cgi-bin/en.pl b/langs/en/cgi-bin/en.pl index 99698948d..87cc679a5 100644 --- a/langs/en/cgi-bin/en.pl +++ b/langs/en/cgi-bin/en.pl @@ -1585,6 +1585,33 @@ 'ip basic info' => 'Basic IP information', 'ip info' => 'IP information', 'ip info for' => 'IP information for', +'ipblocklist' => 'IP Address Blocklists', +'ipblocklist blocklist settings' => 'Blocklist settings', +'ipblocklist category' => 'Category', +'ipblocklist category application' => 'Application', +'ipblocklist category attacker' => 'Attacker', +'ipblocklist category c and c' => 'Malware C&C', +'ipblocklist category composite' => 'Composite', +'ipblocklist category invalid' => 'Invalid Address', +'ipblocklist category reputation' => 'Reputation', +'ipblocklist category scanner' => 'Scanner', +'ipblocklist could not download blocklist' => 'Could not download blocklist', +'ipblocklist disable mid' => 'because it is included in', +'ipblocklist disable post' => '', +'ipblocklist disable pre' => 'Disabling', +'ipblocklist download error' => 'A download error occurs.', +'ipblocklist empyt blocklist received' => 'An empty blocklist has been received.', +'ipblocklist enable' => 'Enable', +'ipblocklist entries' => 'Entries', +'ipblocklist hits' => 'Total number of blocklist hits for', +'ipblocklist id' => 'Blocklist', +'ipblocklist input' => 'Packets Dropped In', +'ipblocklist log list' => 'Firewall log (blocklist)', +'ipblocklist log' => 'Log dropped packets', +'ipblocklist logs' => 'IP Address Blocklist Logs', +'ipblocklist name' => 'Name', +'ipblocklist output' => 'Packets Dropped Out', +'ipblocklist use ipblocklists' => 'Enable IP Blocklists', 'ipfire has now rebooted' => 'IPFire is rebooting now.', 'ipfire has now shutdown' => 'IPFire is shutting down now.', 'ipfire side' => 'IPFire side:', From d6b061374423db3cf55c38bee7cbacb703c40f29 Mon Sep 17 00:00:00 2001 From: Rob Brewer Date: Sun, 6 Mar 2022 20:55:25 +0100 Subject: [PATCH 28/58] ipblocklists.dat: Remove uneccessary and broken module includes. Signed-off-by: Rob Brewer Signed-off-by: Stefan Schantl --- html/cgi-bin/logs.cgi/ipblocklists.dat | 2 -- 1 file changed, 2 deletions(-) diff --git a/html/cgi-bin/logs.cgi/ipblocklists.dat b/html/cgi-bin/logs.cgi/ipblocklists.dat index c86cb8822..d4b2593a7 100755 --- a/html/cgi-bin/logs.cgi/ipblocklists.dat +++ b/html/cgi-bin/logs.cgi/ipblocklists.dat @@ -11,14 +11,12 @@ # and Michael Tremer (www.ipfire.org) use strict; -use Getopt::Std; # enable only the following on debugging purpose #use warnings; #use CGI::Carp 'fatalsToBrowser'; require '/var/ipfire/general-functions.pl'; -require "${General::swroot}/geoip-functions.pl"; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; From 42564758abc686e69f32e381f871eedd0051860d Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Sun, 6 Mar 2022 20:58:19 +0100 Subject: [PATCH 29/58] Menu: Add ipblocklist entry to log menu. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/menu/70-log.menu | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/menu/70-log.menu b/config/menu/70-log.menu index 2fa0e426e..19add1fb1 100644 --- a/config/menu/70-log.menu +++ b/config/menu/70-log.menu @@ -43,6 +43,11 @@ 'title' => "$Lang::tr{'ids logs'}", 'enabled' => 1 }; + $sublogs->{'53.ipblocklist'} = {'caption' => $Lang::tr{'ipblocklist logs'}, + 'uri' => '/cgi-bin/logs.cgi/ipblocklists.dat', + 'title' => "$Lang::tr{'ipblocklist logs'}", + 'enabled' => 1 + }; $sublogs->{'55.ovpnclients'} = { 'caption' => $Lang::tr{'ovpn rw connection log'}, 'uri' => '/cgi-bin/logs.cgi/ovpnclients.dat', From 1fd351d407daffe30059fd69441249141a9a5186 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Sun, 6 Mar 2022 21:01:44 +0100 Subject: [PATCH 30/58] Menu: Add ipblocklist entry to firewall menu. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/menu/50-firewall.menu | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/menu/50-firewall.menu b/config/menu/50-firewall.menu index aa67d9007..cd2af7cbb 100644 --- a/config/menu/50-firewall.menu +++ b/config/menu/50-firewall.menu @@ -21,6 +21,11 @@ 'title' => "$Lang::tr{'intrusion detection system'}", 'enabled' => 1, }; + $subfirewall->{'50.ipblocklist'} = {'caption' => $Lang::tr{'ipblocklist'}, + 'uri' => '/cgi-bin/ipblocklist.cgi', + 'title' => "$Lang::tr{'ipblocklist'}", + 'enabled' => 1, + }; $subfirewall->{'60.locationblock'} = { 'caption' => $Lang::tr{'locationblock'}, 'uri' => '/cgi-bin/location-block.cgi', From c0472dcf2a4c014a016ff7527859cd80da40c635 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Sun, 6 Mar 2022 21:03:20 +0100 Subject: [PATCH 31/58] logs.cgi/log.dat: Allow to show logged ipblocklist messages. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- html/cgi-bin/logs.cgi/log.dat | 2 ++ 1 file changed, 2 insertions(+) diff --git a/html/cgi-bin/logs.cgi/log.dat b/html/cgi-bin/logs.cgi/log.dat index 3364b7bea..20f61d4ea 100644 --- a/html/cgi-bin/logs.cgi/log.dat +++ b/html/cgi-bin/logs.cgi/log.dat @@ -59,6 +59,7 @@ my %sections = ( 'dhcp' => '(dhcpd: )', 'dma' => '(dma: |dma\[.*\]: |postfix/\w*\[\d*\]: )', 'guardian' => '(guardian\[.*\]: )', + 'ipblocklist' => '(ipblocklist: )', 'ipfire' => '(ipfire: )', 'ipsec' => '(ipsec_[\w_]+: |pluto\[.*\]: |charon: |vpnwatch: )', 'kernel' => '(kernel: (?!DROP_))', @@ -89,6 +90,7 @@ my %trsections = ( 'dhcp' => "$Lang::tr{'dhcp server'}", 'dma' => 'Mail', 'guardian' => "$Lang::tr{'guardian'}", + 'ipblocklist' => "$Lang::tr{'ipblocklist'}", 'ipfire' => 'IPFire', 'ipsec' => 'IPSec', 'kernel' => "$Lang::tr{'kernel'}", From a72c2458c4cac842cf95c43304943a67dac8ea8d Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 6 Mar 2022 21:15:18 +0100 Subject: [PATCH 32/58] ipblocklist.cgi: Add better messages in error case. Signed-off-by: Stefan Schantl --- html/cgi-bin/ipblocklist.cgi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/html/cgi-bin/ipblocklist.cgi b/html/cgi-bin/ipblocklist.cgi index 99ce68d17..b4dd433af 100644 --- a/html/cgi-bin/ipblocklist.cgi +++ b/html/cgi-bin/ipblocklist.cgi @@ -105,11 +105,10 @@ if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") { my $status = &IPblocklist::download_and_create_blocklist($missing_blocklist); # Check if there was an error during download. - # XXX - fill with messages. if ($status eq "dl_error") { - $errormessage = "XXX - dl_error"; + $errormessage = "$Lang::tr{'ipblocklist could not download blocklist'} - $Lang::tr{'ipblocklist download error'}"; } elsif ($status eq "empty_list") { - $errormessage = "XXX - empty"; + $errormessage = "$Lang::tr{'ipblocklist could not download blocklist'} - $Lang::tr{'ipblocklist empty blocklist received'}"; } } } From 3b114903aac1d6258b177b8082354d77885cb883 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 6 Mar 2022 21:16:07 +0100 Subject: [PATCH 33/58] ipblocklist.cgi: Mark and display a notice about a required reload of the firewall. Signed-off-by: Stefan Schantl --- html/cgi-bin/ipblocklist.cgi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/html/cgi-bin/ipblocklist.cgi b/html/cgi-bin/ipblocklist.cgi index b4dd433af..1cd24b68e 100644 --- a/html/cgi-bin/ipblocklist.cgi +++ b/html/cgi-bin/ipblocklist.cgi @@ -118,7 +118,11 @@ if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") { # Write configuration hash. &General::writehash($settings, \%cgiparams); - # XXX display firewall reload stuff + # Call function to mark a required reload of the firewall. + &General::firewall_config_changed(); + + # Display notice about a required reload of the firewall. + $errormessage = "$Lang::tr{'p2p block save notice'}"; } } From ac8e283eb4e194f0fcf255f22663992e6326b428 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Mon, 7 Mar 2022 19:54:44 +0100 Subject: [PATCH 34/58] update-ipblocklist: Add code to reload updated blocklists. Signed-off-by: Stefan Schantl --- src/scripts/update-ipblocklists | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/scripts/update-ipblocklists b/src/scripts/update-ipblocklists index 16ed3da38..96731d449 100644 --- a/src/scripts/update-ipblocklists +++ b/src/scripts/update-ipblocklists @@ -69,6 +69,10 @@ unless (-e "${General::swroot}/red/active") { # Get all available blocklists. my @blocklists = &IPblocklist::get_blocklists(); +# Array to store successfully update blocklists. +# They need to be reloaded. +my @updated_blocklists = (); + # Gather the details, when a list got modified last time. my %modified = (); @@ -120,6 +124,21 @@ foreach my $blocklist (@blocklists) { } else { # Log successfull update. &_log_to_syslog(" Successfully updated $blocklist blocklist."); + + # Add the list to the array of updated blocklists. + push(@updated_blocklists, $blocklist); + } +} + +# Check if a blocklist has been updated and therefore needs to be reloaded. +if (@updated_blocklists) { + # Loop through the array. + foreach my $updated_blocklist (@updated_blocklists) { + # Get the blocklist file. + my $ipset_db_file = &IPblocklist::get_ipset_db_file($updated_blocklist); + + # Call safe system function to reload/update the blocklist. + &General::system("ipset", "restore", "-f", "$ipset_db_file"); } } From bbbea6f9ba548e86e96893232f2f16c3e1875494 Mon Sep 17 00:00:00 2001 From: Rob Brewer Date: Sun, 3 Apr 2022 10:52:56 +0200 Subject: [PATCH 35/58] rules.pl: Add space at the end of the log prefix. This improves the readabiliy when digging through the logs. Signed-off-by: Rob Brewer Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index c578405ba..b800e3063 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -751,7 +751,7 @@ sub ipblocklist () { # Check if logging is enables. if($blocklistsettings{'LOGGING'} eq "on") { # Create logging rule. - run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\""); + run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\" "); } # Create Drop rule. From 98d50c03e71be54dcc29b24a60f042fe3f061688 Mon Sep 17 00:00:00 2001 From: Rob Brewer Date: Sun, 3 Apr 2022 10:55:34 +0200 Subject: [PATCH 36/58] ipblocklist.dat: Do not rely on any theme settings. The support for themes has been removed since ages, so we do not need this anymore and may crash the page. Signed-off-by: Rob Brewer Signed-off-by: Stefan Schantl --- html/cgi-bin/logs.cgi/ipblocklists.dat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/cgi-bin/logs.cgi/ipblocklists.dat b/html/cgi-bin/logs.cgi/ipblocklists.dat index d4b2593a7..2435137b5 100755 --- a/html/cgi-bin/logs.cgi/ipblocklists.dat +++ b/html/cgi-bin/logs.cgi/ipblocklists.dat @@ -295,7 +295,7 @@ print "

$Lang::tr{'ipblocklist hits'} $longmonthstr $daystr: $lines

my %color = (); my %mainsettings = (); &General::readhash("${General::swroot}/main/settings", \%mainsettings); -&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); +&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color); my @lists = sort keys (%lists); From 3e0cb28fc6198fcc192bb3863f03dd8dae7b442e Mon Sep 17 00:00:00 2001 From: Rob Brewer Date: Sat, 5 Mar 2022 21:18:42 +0000 Subject: [PATCH 37/58] showrequestfromblocklist.dat: Modify regex for added space in log-prefix. Signed-off-by: Rob Brewer Signed-off-by: Stefan Schantl --- html/cgi-bin/logs.cgi/showrequestfromblocklist.dat | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat b/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat index d189a78d4..4f8264ace 100755 --- a/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat +++ b/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat @@ -161,8 +161,8 @@ my $blaoklist = $cgiparams{blocklist}; if (!$skip) { while () { - if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)IN=.*/) { - if($1 eq $blocklist){ + if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)\s?IN=.*/) { + if($1 eq $blacklist){ $log[$lines] = $_; $lines++; } @@ -186,8 +186,8 @@ if ($multifile) { } if (!$skip) { while () { - if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)IN=.*/) { - if($1 eq $blocklist){ + if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)\s?IN=.*/) { + if($1 eq $blacklist){ $log[$lines] = $_; $lines++; } @@ -308,9 +308,8 @@ $lines = 0; foreach $_ (@slice) { $a = $_; # Check whether valid ipv4 or ipv6 address - if (($_ =~ /BLKLST_(\w+)IN=/)) { - if($1 eq $blocklist) { - + if (($_ =~ /BLKLST_(\w+)\s?IN=/)) { + if($1 eq $blacklist) { my $in = '-'; my $out = '-'; my $srcaddr = ''; my $dstaddr = ''; my $protostr = ''; From 733267f35accad3de95268b934e6f9fdae13a3f0 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Sun, 3 Apr 2022 13:44:44 +0200 Subject: [PATCH 38/58] firewall: Add ipblocklist related chains. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- src/initscripts/system/firewall | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/initscripts/system/firewall b/src/initscripts/system/firewall index 2597dae10..dfa08d58b 100644 --- a/src/initscripts/system/firewall +++ b/src/initscripts/system/firewall @@ -180,6 +180,14 @@ iptables_init() { iptables -A HOSTILE_DROP -m limit --limit 10/second -j LOG --log-prefix "DROP_HOSTILE " iptables -A HOSTILE_DROP -j DROP -m comment --comment "DROP_HOSTILE" + # IP Address Blocklist chains + iptables -N BLOCKLISTIN + iptables -N BLOCKLISTOUT + iptables -A INPUT ! -p icmp -j BLOCKLISTIN + iptables -A FORWARD ! -p icmp -j BLOCKLISTIN + iptables -A FORWARD ! -p icmp -j BLOCKLISTOUT + iptables -A OUTPUT ! -p icmp -j BLOCKLISTOUT + # IPS (Guardian) chains iptables -N GUARDIAN iptables -A INPUT -j GUARDIAN From 39eba7abab657959a3057a8cc0140f53db328f95 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 3 Apr 2022 14:14:41 +0200 Subject: [PATCH 39/58] rules.pl: Check if the blocklist is part of the settings hash. Otherwise there will pop up some ugly notices on the command line and the logs. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index b800e3063..50feafa3b 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -740,7 +740,7 @@ sub ipblocklist () { # Loop through the array of blocklists. foreach my $blocklist (@blocklists) { # Skip disabled blocklists. - next unless($blocklistsettings{$blocklist} eq "on"); + next unless($blocklistsettings{$blocklist}) && ($blocklistsettings{$blocklist} eq "on")); # Call function to load the blocklist. &ipset_restore($blocklist); From 36330f84fb69c380c29038f22523cf998f18b214 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 3 Apr 2022 14:15:48 +0200 Subject: [PATCH 40/58] rules.pl: Fix typo when creating blocklist drop chains. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 50feafa3b..c12e8fa6e 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -755,7 +755,7 @@ sub ipblocklist () { } # Create Drop rule. - run("$IPTABLES A ${blocklist}_DROP -j DROP"); + run("$IPTABLES -A ${blocklist}_DROP -j DROP"); # Add the rules to check against the set run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP"); From 960608c8b50e711a5409594529744c0705f2dd58 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Mon, 4 Apr 2022 21:43:20 +0200 Subject: [PATCH 41/58] rules.pl: Add function to check if given firewall chain exists. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index c12e8fa6e..1bd292059 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -976,6 +976,14 @@ sub firewall_is_in_subnet { return 0; } +sub firewall_chain_exists ($) { + my ($chain) = @_; + + my $ret = &General::system("iptables", "--wait", "-n", "-L", "$chain"); + + return $ret; +} + sub ipset_get_sets () { my @sets; From aba4e1cd1ecc4620b3d90b2111167b4d3f523a76 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Mon, 4 Apr 2022 21:43:49 +0200 Subject: [PATCH 42/58] rules.pl: Refactor logic to handle the IP blocklist feature. * Fixes that the same chain would be created each time a firewall reload is performed. * Also fixes multiple log and drop rules inside the the BLOCKLIST_DROP chains after doing a firewall reload. * Orphaned BLOCKLIST_DROP chains now will be flushed and removed in case the blocklist gets disabled or the entire feature will be swithed off. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 54 +++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 1bd292059..9198fec1d 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -731,35 +731,43 @@ sub ipblocklist () { run("$IPTABLES -F BLOCKLISTIN"); run("$IPTABLES -F BLOCKLISTOUT"); - # If the blocklist feature is disabled we are finished here. - if($blocklistsettings{'ENABLE'} ne "on") { - # Bye. - return; - } - # Loop through the array of blocklists. foreach my $blocklist (@blocklists) { - # Skip disabled blocklists. - next unless($blocklistsettings{$blocklist}) && ($blocklistsettings{$blocklist} eq "on")); + # Check if the blocklist feature and the current processed blocklist is enabled. + if(($blocklistsettings{'ENABLE'} eq "on") && ($blocklistsettings{$blocklist}) && ($blocklistsettings{$blocklist} eq "on")) { + # Call function to load the blocklist. + &ipset_restore($blocklist); - # Call function to load the blocklist. - &ipset_restore($blocklist); + # Call function to check if the corresponding iptables drop chain already has been created. + if(&firewall_chain_exists("${blocklist}_DROP")) { + # Create iptables chain. + run("$IPTABLES -N ${blocklist}_DROP"); - # Create iptables chain. - run("$IPTABLES -N ${blocklist}_DROP"); + # Check if logging is enabled. + if($blocklistsettings{'LOGGING'} eq "on") { + # Create logging rule. + run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\" "); + } - # Check if logging is enables. - if($blocklistsettings{'LOGGING'} eq "on") { - # Create logging rule. - run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\" "); + # Create Drop rule. + run("$IPTABLES -A ${blocklist}_DROP -j DROP"); + } + + # Add the rules to check against the set + run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP"); + run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -m set --match-set $blocklist dst -j ${blocklist}_DROP"); + + # IP blocklist or the blocklist is disabled. + } else { + # Check if the blocklist related iptables drop chain exits. + unless(&firewall_chain_exists("${blocklist}_DROP")) { + # Flush the chain. + run("$IPTABLES -F ${blocklist}_DROP"); + + # Drop the chain. + run("$IPTABLES -X ${blocklist}_DROP"); + } } - - # Create Drop rule. - run("$IPTABLES -A ${blocklist}_DROP -j DROP"); - - # Add the rules to check against the set - run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP"); - run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -m set --match-set $blocklist dst -j ${blocklist}_DROP"); } } From 82fea6d57533a56eb5fbd091038ff28fc235093f Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 5 Apr 2022 04:57:19 +0200 Subject: [PATCH 43/58] update-ipblocklists: Do not log the pid in syslog. Signed-off-by: Stefan Schantl --- src/scripts/update-ipblocklists | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/update-ipblocklists b/src/scripts/update-ipblocklists index 96731d449..b96bb4f7c 100644 --- a/src/scripts/update-ipblocklists +++ b/src/scripts/update-ipblocklists @@ -46,7 +46,7 @@ if ( $> == 0 ) { } # Establish the connection to the syslog service. -openlog('ipblocklist', 'cons,pid', 'user'); +openlog('ipblocklist', 'cons', 'user'); # Grab the configured providers. &General::readhash("${General::swroot}/ipblocklist/settings", \%settings); From 6223e2b49853169a41d3df7c674878dd4e8ec912 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 5 Apr 2022 05:02:30 +0200 Subject: [PATCH 44/58] showrequestfromblocklist.dat: Fix silly typos. Signed-off-by: Stefan Schantl --- html/cgi-bin/logs.cgi/showrequestfromblocklist.dat | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat b/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat index 4f8264ace..98524614f 100755 --- a/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat +++ b/html/cgi-bin/logs.cgi/showrequestfromblocklist.dat @@ -156,13 +156,13 @@ if (!(open (FILE,($filestr =~ /.gz$/ ? "gzip -dc $filestr |" : $filestr)))) { } my $lines = 0; my @log=(); -my $blaoklist = $cgiparams{blocklist}; +my $blocklist = $cgiparams{blocklist}; if (!$skip) { while () { if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)\s?IN=.*/) { - if($1 eq $blacklist){ + if($1 eq $blocklist){ $log[$lines] = $_; $lines++; } @@ -187,7 +187,7 @@ if ($multifile) { if (!$skip) { while () { if (/^${monthstr} ${daystr} ..:..:.. [\w\-]+ kernel:.*BLKLST_(\w+)\s?IN=.*/) { - if($1 eq $blacklist){ + if($1 eq $blocklist){ $log[$lines] = $_; $lines++; } @@ -309,7 +309,7 @@ foreach $_ (@slice) { $a = $_; # Check whether valid ipv4 or ipv6 address if (($_ =~ /BLKLST_(\w+)\s?IN=/)) { - if($1 eq $blacklist) { + if($1 eq $blocklist) { my $in = '-'; my $out = '-'; my $srcaddr = ''; my $dstaddr = ''; my $protostr = ''; From d8bb2638195a53eee8be36d307ff5fd71e048b0d Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Tue, 5 Apr 2022 05:08:21 +0200 Subject: [PATCH 45/58] backup: Add ipblocklist related files. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/backup/include | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/backup/include b/config/backup/include index d310b8487..aacfaf64a 100644 --- a/config/backup/include +++ b/config/backup/include @@ -41,6 +41,7 @@ var/ipfire/ethernet/aliases var/ipfire/ethernet/wireless var/ipfire/firewall var/ipfire/fwhosts +var/ipfire/ipblocklist/modified var/ipfire/main/* var/ipfire/ovpn var/ipfire/ovpn/collectd.vpn @@ -54,6 +55,7 @@ var/ipfire/*/settings var/ipfire/time/ var/ipfire/urlfilter var/ipfire/vpn +var/lib/ipblocklist var/lib/suricata var/log/ip-acct/* var/log/rrd/* From 4ca678a8577175d6bd9f2e3baf7e717a19e201d9 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Tue, 5 Apr 2022 05:29:03 +0200 Subject: [PATCH 46/58] ipblocklist-sources: New package. Placing the ipblocklist sources file as an own package, easily allows to update this single file during a core update and to keep the vendor details for the blocklists up-to-date. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/rootfiles/common/ipblocklist-sources | 1 + lfs/ipblocklist-sources | 53 +++++++++++++++++++++ make.sh | 1 + 3 files changed, 55 insertions(+) create mode 100644 config/rootfiles/common/ipblocklist-sources create mode 100644 lfs/ipblocklist-sources diff --git a/config/rootfiles/common/ipblocklist-sources b/config/rootfiles/common/ipblocklist-sources new file mode 100644 index 000000000..e1789037b --- /dev/null +++ b/config/rootfiles/common/ipblocklist-sources @@ -0,0 +1 @@ +var/ipfire/ipblocklist/sources diff --git a/lfs/ipblocklist-sources b/lfs/ipblocklist-sources new file mode 100644 index 000000000..9cc1cc8a2 --- /dev/null +++ b/lfs/ipblocklist-sources @@ -0,0 +1,53 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2022 IPFire development team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU 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 General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +############################################################################### +# Definitions +############################################################################### + +include Config + +VER = ipfire + +THISAPP = ipblocklist-sources +TARGET = $(DIR_INFO)/$(THISAPP) + +############################################################################### +# Top-level Rules +############################################################################### + +install : $(TARGET) + +check : + +download : + +md5 : + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : + @$(PREBUILD) + mkdir -p /var/ipfire/ipblocklist + install -v -m 0644 $(DIR_SRC)/config/ipblocklist/sources /var/ipfire/ipblocklist + + @$(POSTBUILD) diff --git a/make.sh b/make.sh index 4c2dc10b5..89bc7ec41 100755 --- a/make.sh +++ b/make.sh @@ -1439,6 +1439,7 @@ buildipfire() { lfsmake2 hyperscan lfsmake2 suricata lfsmake2 ids-ruleset-sources + lfsmake2 ipblocklist-sources lfsmake2 squid lfsmake2 squidguard lfsmake2 calamaris From 52bb9af8978501297ea42ed38ed5579a46de6661 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Tue, 5 Apr 2022 05:32:51 +0200 Subject: [PATCH 47/58] configroot: Create ipblocklist related dir and settings file. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- lfs/configroot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lfs/configroot b/lfs/configroot index 2f3b93324..7a6334cc6 100644 --- a/lfs/configroot +++ b/lfs/configroot @@ -51,7 +51,7 @@ $(TARGET) : # Create all directories for i in addon-lang auth backup ca captive certs connscheduler crls ddns dhcp dhcpc dns dnsforward \ - ethernet extrahd/bin fwlogs fwhosts firewall isdn key langs logging mac main \ + ethernet extrahd/bin fwlogs fwhosts firewall ipblocklist isdn key langs logging mac main \ menu.d modem optionsfw \ ovpn patches pakfire portfw ppp private proxy/advanced/cre \ proxy/calamaris/bin qos/bin red remote sensors suricata time \ @@ -65,7 +65,7 @@ $(TARGET) : captive/settings captive/agb.txt captive/clients captive/voucher_out certs/index.txt certs/index.txt.attr ddns/config ddns/settings ddns/ipcache dhcp/settings \ dhcp/fixleases dhcp/advoptions dhcp/dhcpd.conf.local dns/settings dns/servers dnsforward/config ethernet/aliases ethernet/settings ethernet/known_nics ethernet/scanned_nics \ ethernet/wireless extrahd/scan extrahd/devices extrahd/partitions extrahd/settings firewall/settings firewall/config firewall/locationblock firewall/input firewall/outgoing \ - fwhosts/customnetworks fwhosts/customhosts fwhosts/customgroups fwhosts/customservicegrp fwhosts/customlocationgrp fwlogs/ipsettings fwlogs/portsettings \ + fwhosts/customnetworks fwhosts/customhosts fwhosts/customgroups fwhosts/customservicegrp fwhosts/customlocationgrp fwlogs/ipsettings fwlogs/portsettings ipblocklist/settings \ isdn/settings mac/settings main/hosts main/routing main/security main/settings optionsfw/settings \ ovpn/ccd.conf ovpn/ccdroute ovpn/ccdroute2 pakfire/settings portfw/config ppp/settings-1 ppp/settings-2 ppp/settings-3 ppp/settings-4 \ ppp/settings-5 ppp/settings proxy/settings proxy/squid.conf proxy/advanced/settings proxy/advanced/cre/enable remote/settings qos/settings qos/classes qos/subclasses qos/level7config qos/portconfig \ From 5af16e17dfbaeeb8832a01407c2f105cc1f94002 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Tue, 5 Apr 2022 05:34:00 +0200 Subject: [PATCH 48/58] ipblocklist: Rootfile updates. Signed-off-by: Tim FitzGeorge Signed-off-by: Stefan Schantl --- config/rootfiles/common/aarch64/stage2 | 1 + config/rootfiles/common/armv6l/stage2 | 1 + config/rootfiles/common/configroot | 3 +++ config/rootfiles/common/web-user-interface | 3 +++ config/rootfiles/common/x86_64/stage2 | 1 + 5 files changed, 9 insertions(+) diff --git a/config/rootfiles/common/aarch64/stage2 b/config/rootfiles/common/aarch64/stage2 index e328a4526..c44e79ec9 100644 --- a/config/rootfiles/common/aarch64/stage2 +++ b/config/rootfiles/common/aarch64/stage2 @@ -106,6 +106,7 @@ usr/local/bin/settime usr/local/bin/timecheck usr/local/bin/timezone-transition usr/local/bin/update-ids-ruleset +usr/local/bin/update-ipblocklists usr/local/bin/update-lang-cache usr/local/bin/update-location-database #usr/local/include diff --git a/config/rootfiles/common/armv6l/stage2 b/config/rootfiles/common/armv6l/stage2 index 2bd00d968..5e87822fb 100644 --- a/config/rootfiles/common/armv6l/stage2 +++ b/config/rootfiles/common/armv6l/stage2 @@ -104,6 +104,7 @@ usr/local/bin/settime usr/local/bin/timecheck usr/local/bin/timezone-transition usr/local/bin/update-ids-ruleset +usr/local/bin/update-ipblocklists usr/local/bin/update-lang-cache usr/local/bin/update-location-database #usr/local/include diff --git a/config/rootfiles/common/configroot b/config/rootfiles/common/configroot index fef5ffbcf..088e87f5b 100644 --- a/config/rootfiles/common/configroot +++ b/config/rootfiles/common/configroot @@ -81,6 +81,9 @@ var/ipfire/graphs.pl var/ipfire/header.pl var/ipfire/location-functions.pl var/ipfire/ids-functions.pl +var/ipfire/ipblocklist-functions.pl +var/ipfire/ipblocklist +#var/ipfire/ipblocklist/settings var/ipfire/isdn #var/ipfire/isdn/settings var/ipfire/key diff --git a/config/rootfiles/common/web-user-interface b/config/rootfiles/common/web-user-interface index cae8dde32..33f0d30a7 100644 --- a/config/rootfiles/common/web-user-interface +++ b/config/rootfiles/common/web-user-interface @@ -27,6 +27,7 @@ srv/web/ipfire/cgi-bin/hardwaregraphs.cgi srv/web/ipfire/cgi-bin/hosts.cgi srv/web/ipfire/cgi-bin/ids.cgi srv/web/ipfire/cgi-bin/index.cgi +srv/web/ipfire/cgi-bin/ipblocklist.cgi srv/web/ipfire/cgi-bin/ipinfo.cgi srv/web/ipfire/cgi-bin/iptables.cgi srv/web/ipfire/cgi-bin/location-block.cgi @@ -38,9 +39,11 @@ srv/web/ipfire/cgi-bin/logs.cgi/firewalllogcountry.dat srv/web/ipfire/cgi-bin/logs.cgi/firewalllogip.dat srv/web/ipfire/cgi-bin/logs.cgi/firewalllogport.dat srv/web/ipfire/cgi-bin/logs.cgi/ids.dat +srv/web/ipfire/cgi-bin/logs.cgi/ipblocklists.dat srv/web/ipfire/cgi-bin/logs.cgi/log.dat srv/web/ipfire/cgi-bin/logs.cgi/ovpnclients.dat srv/web/ipfire/cgi-bin/logs.cgi/proxylog.dat +srv/web/ipfire/cgi-bin/logs.cgi/showrequestfromblocklist.dat srv/web/ipfire/cgi-bin/logs.cgi/showrequestfromcountry.dat srv/web/ipfire/cgi-bin/logs.cgi/showrequestfromip.dat srv/web/ipfire/cgi-bin/logs.cgi/showrequestfromport.dat diff --git a/config/rootfiles/common/x86_64/stage2 b/config/rootfiles/common/x86_64/stage2 index 586b88e3d..bb2ed2cb1 100644 --- a/config/rootfiles/common/x86_64/stage2 +++ b/config/rootfiles/common/x86_64/stage2 @@ -106,6 +106,7 @@ usr/local/bin/settime usr/local/bin/timecheck usr/local/bin/timezone-transition usr/local/bin/update-ids-ruleset +usr/local/bin/update-ipblocklists usr/local/bin/update-lang-cache usr/local/bin/update-location-database #usr/local/include From 018a8098314a10a3823cbc61d197c76b4baa6fec Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 10 Apr 2022 11:40:56 +0200 Subject: [PATCH 49/58] crontab: Add job for periodic ipblocklist updates. Signed-off-by: Stefan Schantl --- config/cron/crontab | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/cron/crontab b/config/cron/crontab index c42104626..7762a56ff 100644 --- a/config/cron/crontab +++ b/config/cron/crontab @@ -65,6 +65,9 @@ HOME=/ # Perform a surciata rules update every 12 hours. @ 12h [ -f "/var/ipfire/red/active" ] && /usr/local/bin/update-ids-ruleset >/dev/null 2>&1 +# Update Lists for IP-based blocking. +%hourly,random * [ -f "/var/ipfire/red/active" ] && /usr/local/bin/update-ipblocklists >/dev/null 2>&1 + # Retry sending spooled mails regularly %hourly * /usr/sbin/dma -q From 9759d96e1bbb57b80abd93f5d94d97eb1a174a81 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 10 Apr 2022 11:51:13 +0200 Subject: [PATCH 50/58] stage2: Add database directory for ipblocklist feature. Signed-off-by: Stefan Schantl --- config/rootfiles/common/aarch64/stage2 | 1 + config/rootfiles/common/armv6l/stage2 | 1 + config/rootfiles/common/x86_64/stage2 | 1 + lfs/stage2 | 4 ++++ 4 files changed, 7 insertions(+) diff --git a/config/rootfiles/common/aarch64/stage2 b/config/rootfiles/common/aarch64/stage2 index c44e79ec9..e2ef41869 100644 --- a/config/rootfiles/common/aarch64/stage2 +++ b/config/rootfiles/common/aarch64/stage2 @@ -157,6 +157,7 @@ var/cache/ldconfig var/cache/ldconfig/aux-cache var/empty #var/lib +var/lib/ipblocklist #var/lib/misc #var/local var/lock diff --git a/config/rootfiles/common/armv6l/stage2 b/config/rootfiles/common/armv6l/stage2 index 5e87822fb..fcdc92928 100644 --- a/config/rootfiles/common/armv6l/stage2 +++ b/config/rootfiles/common/armv6l/stage2 @@ -155,6 +155,7 @@ var/cache/ldconfig var/cache/ldconfig/aux-cache var/empty #var/lib +var/lib/ipblocklist #var/lib/misc #var/local var/lock diff --git a/config/rootfiles/common/x86_64/stage2 b/config/rootfiles/common/x86_64/stage2 index bb2ed2cb1..875a0b16c 100644 --- a/config/rootfiles/common/x86_64/stage2 +++ b/config/rootfiles/common/x86_64/stage2 @@ -157,6 +157,7 @@ var/cache/ldconfig var/cache/ldconfig/aux-cache var/empty #var/lib +var/lib/ipblocklist #var/lib/misc #var/local var/lock diff --git a/lfs/stage2 b/lfs/stage2 index 39697a848..9c3207ba6 100644 --- a/lfs/stage2 +++ b/lfs/stage2 @@ -165,4 +165,8 @@ endif -mkdir -pv /opt/pakfire/db/core echo "$(CORE)" > /opt/pakfire/db/core/mine + # IPblocklist. + -mkdir -pv /var/lib/ipblocklist + chown nobody:nobody /var/lib/ipblocklist + @$(POSTBUILD) From 404b513794505ca82d50a173b228d50ac786438a Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Mon, 25 Apr 2022 20:57:04 +0200 Subject: [PATCH 51/58] ipblocklist: Add "v4" as extension to the ipset set names. This easily allows us to swap the sets after updating, without unloading them. Signed-off-by: Stefan Schantl --- config/cfgroot/ipblocklist-functions.pl | 3 +++ config/firewall/rules.pl | 12 ++++++++++++ src/scripts/update-ipblocklists | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/config/cfgroot/ipblocklist-functions.pl b/config/cfgroot/ipblocklist-functions.pl index f0e5ff73f..ecabf42e8 100644 --- a/config/cfgroot/ipblocklist-functions.pl +++ b/config/cfgroot/ipblocklist-functions.pl @@ -249,6 +249,9 @@ sub download_and_create_blocklist($) { # Simply set the limit of list elements to the double of current list elements. my $maxelem = $list_entries *2; + # Add "v4" suffix to the list name. + $list = "$list" . "v4"; + # Write line to create the set. # # We safely can use hash:net as type because it supports single addresses and networks. diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 9198fec1d..799b2667d 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -1060,11 +1060,23 @@ sub ipset_restore ($) { # Check if the given set name is a blocklist. } elsif ($set ~~ @blocklists) { + # IPblocklist sets contains v4 as setname extension. + my $set_name = "$set" . "v4"; + # Get the database file for the given blocklist. my $db_file = &IPblocklist::get_ipset_db_file($set); # Call function to restore/load the set. &ipset_call_restore($db_file); + + # Check if the set is already loaded (has been used before). + if ($set ~~ @ipset_used_sets) { + # Swap the sets. + run("$IPSET swap $set_name $set"); + } else { + # Rename the set to proper use it. + run("$IPSET rename $set_name $set"); + } } # Store the restored set to the hash to prevent from loading it again. diff --git a/src/scripts/update-ipblocklists b/src/scripts/update-ipblocklists index b96bb4f7c..9918cac41 100644 --- a/src/scripts/update-ipblocklists +++ b/src/scripts/update-ipblocklists @@ -139,6 +139,15 @@ if (@updated_blocklists) { # Call safe system function to reload/update the blocklist. &General::system("ipset", "restore", "-f", "$ipset_db_file"); + + # The set name contains a "v4" as suffix. + my $set_name = "$updated_blocklist" . "v4"; + + # Swap the sets to use the new one. + &General::system("ipset", "swap", "$set_name", "$updated_blocklist"); + + # Destroy the old blocklist. + &General::system("ipset", "destroy", "$set_name"); } } From adbd2bd6d467d93e5f17b4fa5c625d5acc52efce Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Mon, 2 May 2022 20:52:42 +0200 Subject: [PATCH 52/58] rules.pl: Flush ipblocklist DROP chains. Flush the DROP chains of the blocklist chains while reloading the firewall. Otherwise the log rules will stay even if logging has been disabled in the meantime. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 799b2667d..62fae8c02 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -742,17 +742,20 @@ sub ipblocklist () { if(&firewall_chain_exists("${blocklist}_DROP")) { # Create iptables chain. run("$IPTABLES -N ${blocklist}_DROP"); - - # Check if logging is enabled. - if($blocklistsettings{'LOGGING'} eq "on") { - # Create logging rule. - run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\" "); - } - - # Create Drop rule. - run("$IPTABLES -A ${blocklist}_DROP -j DROP"); + } else { + # Flush the chain. + run("$IPTABLES -F ${blocklist}_DROP"); } + # Check if logging is enabled. + if($blocklistsettings{'LOGGING'} eq "on") { + # Create logging rule. + run("$IPTABLES -A ${blocklist}_DROP -j LOG -m limit --limit 10/second --log-prefix \"BLKLST_$blocklist\" "); + } + + # Create Drop rule. + run("$IPTABLES -A ${blocklist}_DROP -j DROP"); + # Add the rules to check against the set run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -m set --match-set $blocklist src -j ${blocklist}_DROP"); run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -m set --match-set $blocklist dst -j ${blocklist}_DROP"); From e6928a647283f7a3e1a1804057dcc3e68e1a113e Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sat, 7 May 2022 15:42:48 +0200 Subject: [PATCH 53/58] ipblocklist-sources: Change checksum definition from md5 to b2. Signed-off-by: Stefan Schantl --- lfs/ipblocklist-sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lfs/ipblocklist-sources b/lfs/ipblocklist-sources index 9cc1cc8a2..30b9e94a4 100644 --- a/lfs/ipblocklist-sources +++ b/lfs/ipblocklist-sources @@ -39,7 +39,7 @@ check : download : -md5 : +b2 : ############################################################################### # Installation Details From 6f37368da670f8514ebba3bbd01b376a3c758539 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 8 May 2022 15:15:18 +0200 Subject: [PATCH 54/58] rules.pl: Do not check private networks against ipblocklists. In case some of these private networks are part of an used blocklist this kind of traffic needs to be allowed. Otherwise some services may not work properly. For example: In case one ore more IPSec N2N connections are configured no traffic can be passed through it, if the used networks are part of an blocklist. Signed-off-by: Stefan Schantl --- config/firewall/rules.pl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl index 62fae8c02..e1d7718a8 100644 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -731,6 +731,16 @@ sub ipblocklist () { run("$IPTABLES -F BLOCKLISTIN"); run("$IPTABLES -F BLOCKLISTOUT"); + # Check if the blocklist feature is enabled. + if($blocklistsettings{'ENABLE'} eq "on") { + # Loop through the array of private networks. + foreach my $private_network (@PRIVATE_NETWORKS) { + # Create firewall rules to never block private networks. + run("$IPTABLES -A BLOCKLISTIN -p ALL -i $RED_DEV -s $private_network -j RETURN"); + run("$IPTABLES -A BLOCKLISTOUT -p ALL -o $RED_DEV -d $private_network -j RETURN"); + } + } + # Loop through the array of blocklists. foreach my $blocklist (@blocklists) { # Check if the blocklist feature and the current processed blocklist is enabled. From ce5b2811903468a68f04bb06642f3555d5238899 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Sun, 8 May 2022 15:32:28 +0200 Subject: [PATCH 55/58] fcron: Try to update ipblocklists every 15 min. Signed-off-by: Stefan Schantl --- config/cron/crontab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/cron/crontab b/config/cron/crontab index 7762a56ff..b727531fc 100644 --- a/config/cron/crontab +++ b/config/cron/crontab @@ -65,8 +65,8 @@ HOME=/ # Perform a surciata rules update every 12 hours. @ 12h [ -f "/var/ipfire/red/active" ] && /usr/local/bin/update-ids-ruleset >/dev/null 2>&1 -# Update Lists for IP-based blocking. -%hourly,random * [ -f "/var/ipfire/red/active" ] && /usr/local/bin/update-ipblocklists >/dev/null 2>&1 +# Update Lists for IP-based blocking every 15 minutes. +@ 15 [ -f "/var/ipfire/red/active" ] && /usr/local/bin/update-ipblocklists >/dev/null 2>&1 # Retry sending spooled mails regularly %hourly * /usr/sbin/dma -q From a2e095aff1b8ef9615964b2f8288e23b8045c5e8 Mon Sep 17 00:00:00 2001 From: Tim FitzGeorge Date: Tue, 21 Jun 2022 15:05:29 +0200 Subject: [PATCH 56/58] ipblocklist: Add neccessary files for logwatch. --- config/logwatch/ipblocklist | 91 ++++++++++++++++++++++++++++++++ config/logwatch/ipblocklist.conf | 34 ++++++++++++ config/rootfiles/common/logwatch | 2 + lfs/logwatch | 3 ++ 4 files changed, 130 insertions(+) create mode 100755 config/logwatch/ipblocklist create mode 100644 config/logwatch/ipblocklist.conf diff --git a/config/logwatch/ipblocklist b/config/logwatch/ipblocklist new file mode 100755 index 000000000..8d006377e --- /dev/null +++ b/config/logwatch/ipblocklist @@ -0,0 +1,91 @@ +########################################################################### +# ipblocklist script for Logwatch +# Analyzes the IPFire IP Blocklist log +# +######################################################################### + +######################################################## +## Copyright (c) 2008 Lars Skjærlund +## Covered under the included MIT/X-Consortium License: +## http://www.opensource.org/licenses/mit-license.php +## All modifications and contributions by other persons to +## this script are assumed to have been donated to the +## Logwatch project and thus assume the above copyright +## and licensing terms. If you want to make contributions +## under your own copyright or a different license this +## must be explicitly stated in the contribution and the +## Logwatch project reserves the right to not accept such +## contributions. If you have made significant +## contributions to this script and want to claim +## copyright please contact logwatch-devel@lists.sourceforge.net. +######################################################### + +######################################################################### +# Files - all shown with default paths: +# +# /usr/share/logwatch/default.conf/logfiles/messages.conf +# /usr/share/logwatch/dist.conf/services/blocklist.conf +# /usr/share/logwatch/scripts/services/ipblocklist (this file) +# +# ... and of course +# +# /var/log/messages +######################################################################### + +use Logwatch ':dates'; + +my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'}; + +my $SearchDate; + +my %Updates; +my %Errors; + +$SearchDate = TimeFilter("%b %e"); + +while (defined(my $ThisLine = )) +{ + next unless ($ThisLine =~ m/^\s*\w+\s+\w+\s+(..:..:..) .* ipblocklist: (.*)/); + + my $text = $2; + + if ($text =~ m/Successfully updated (\w+) blocklist/) + { + $Updates{$1}{updates}++; + } + elsif ($text !~ m/Skipping (\w+) blocklist - Too frequent update attempts!/ and + $text !~ m/Skipping (\w+) blocklist - It has not been modified!/ ) + { + $Errors{$text}++; + } +} + +##################################################################### + +if (keys %Updates) +{ + print "\nThe following block lists were updated:\n"; + foreach my $Lists (sort keys %Updates) + { + print " $Lists: $Updates{$Lists}{updates} Time(s)\n"; + } +} + +if (keys %Errors) +{ + print "\nThe following errors were detected:\n"; + + foreach my $Text (keys %Errors) + { + print " $Text: $Errors{$Text} Time(s)\n"; + } +} + +exit(0); + +# vi: shiftwidth=3 tabstop=3 syntax=perl et +# Local Variables: +# mode: perl +# perl-indent-level: 3 +# indent-tabs-mode: nil +# End: diff --git a/config/logwatch/ipblocklist.conf b/config/logwatch/ipblocklist.conf new file mode 100644 index 000000000..a723da350 --- /dev/null +++ b/config/logwatch/ipblocklist.conf @@ -0,0 +1,34 @@ +######################################################################### +# ids-update script for Logwatch +# Analyzes the IPFire IP Blocklist update log +# +# Version: 1.0.0 +# Initial release +# +######################################################################### + +######################################################################### +# This script is subject to the same copyright as Logwatch itself +######################################################################### + +######################################################################### +# Files - all shown with default paths: +# +# /usr/share/logwatch/default.conf/logfiles/messages.conf +# /usr/share/logwatch/dist.conf/services/blocklist.conf (this file) +# /usr/share/logwatch/scripts/services/blocklist +# +# ... and of course +# +# /var/log/messages +######################################################################### + + +Title = "IP Blocklist" + +# Which logfile group... +LogFile = messages + +*applystddate + +# vi: shiftwidth=3 tabstop=3 et diff --git a/config/rootfiles/common/logwatch b/config/rootfiles/common/logwatch index 40d90cd96..91e2d37b3 100644 --- a/config/rootfiles/common/logwatch +++ b/config/rootfiles/common/logwatch @@ -195,6 +195,7 @@ usr/share/logwatch/default.conf/services/zz-sys.conf usr/share/logwatch/dist.conf/logfiles usr/share/logwatch/dist.conf/services usr/share/logwatch/dist.conf/services/dialup.conf +usr/share/logwatch/dist.conf/services/ipblocklist.conf #usr/share/logwatch/lib usr/share/logwatch/lib/Logwatch.pm #usr/share/logwatch/scripts @@ -260,6 +261,7 @@ usr/share/logwatch/scripts/services/http usr/share/logwatch/scripts/services/imapd #usr/share/logwatch/scripts/services/in.qpopper usr/share/logwatch/scripts/services/init +usr/share/logwatch/scripts/services/ipblocklist usr/share/logwatch/scripts/services/ipop3d usr/share/logwatch/scripts/services/iptables usr/share/logwatch/scripts/services/kernel diff --git a/lfs/logwatch b/lfs/logwatch index 8631f4541..5cd79843c 100644 --- a/lfs/logwatch +++ b/lfs/logwatch @@ -98,6 +98,9 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) cp -f $(DIR_SRC)/config/logwatch/dialup /usr/share/logwatch/scripts/services/dialup cp -f $(DIR_SRC)/config/logwatch/dialup.conf /usr/share/logwatch/dist.conf/services/dialup.conf + cp -f $(DIR_SRC)/config/logwatch/ipblocklist /usr/share/logwatch/scripts/services/ipblocklist + cp -f $(DIR_SRC)/config/logwatch/ipblocklist.conf /usr/share/logwatch/dist.conf/services/ipblocklist.conf + -mkdir -p /var/cache/logwatch chmod -v 777 /var/cache/logwatch -mkdir -p /var/log/logwatch From 77af89e59ff9e50b961415d282bbdfe0debf7792 Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 21 Jun 2022 17:32:39 +0200 Subject: [PATCH 57/58] ipblocklist.cgi: Use changed fw reload language string. Signed-off-by: Stefan Schantl --- html/cgi-bin/ipblocklist.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/cgi-bin/ipblocklist.cgi b/html/cgi-bin/ipblocklist.cgi index 1cd24b68e..5b46ded79 100644 --- a/html/cgi-bin/ipblocklist.cgi +++ b/html/cgi-bin/ipblocklist.cgi @@ -122,7 +122,7 @@ if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") { &General::firewall_config_changed(); # Display notice about a required reload of the firewall. - $errormessage = "$Lang::tr{'p2p block save notice'}"; + $errormessage = "$Lang::tr{'fw rules reload notice'}"; } } From 2493c9eabbb30aa55cd24cb817ebff3b6c9da4bb Mon Sep 17 00:00:00 2001 From: Stefan Schantl Date: Tue, 21 Jun 2022 17:52:54 +0200 Subject: [PATCH 58/58] ipblocklist.cgi: Display reload request as notice instead of error. Signed-off-by: Stefan Schantl --- html/cgi-bin/ipblocklist.cgi | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/html/cgi-bin/ipblocklist.cgi b/html/cgi-bin/ipblocklist.cgi index 5b46ded79..431ff1a37 100644 --- a/html/cgi-bin/ipblocklist.cgi +++ b/html/cgi-bin/ipblocklist.cgi @@ -47,6 +47,7 @@ my %cgiparams = ('ACTION' => ''); ############################################################################### my $errormessage = ''; +my $headline = "$Lang::tr{'error message'}"; my $updating = 0; my %mainsettings; my %color; @@ -122,6 +123,7 @@ if ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") { &General::firewall_config_changed(); # Display notice about a required reload of the firewall. + $headline = "$Lang::tr{'notice'}"; $errormessage = "$Lang::tr{'fw rules reload notice'}"; } } @@ -251,7 +253,7 @@ END #------------------------------------------------------------------------------ sub error { - &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); + &Header::openbox('100%', 'left', $headline); print "$errormessage\n"; print " \n"; &Header::closebox();