diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 30f72c9..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,252 +0,0 @@ - - Turtle Firewall - - 2001/11/23 13:25:00 - - Copyright (c) 2001-2024 Andrea Frigido - You may distribute under the terms of either - the GNU General Public License (GPL) - - -CHANGELOG ---------- - -05-12-2001 v.0.91 - - Modificato il nome da fwconf in Turtle Firewall (turtlefw) - -10-01-2002 v.0.92 - - Inserite le regole di accesso da/verso interfaccia lo - che precedentemente impedivano l'accesso a se stesso. - - Impostati i diritti sul file sh generato per l'esecuzione. - - Corretta la definizione delle lan nei file di configurazione - di esempio (samples). -19-03-2002 v.0.93 - - Aggiunto l'uso del modulo turtlefirewall.pm (/usr/lib) - -22-03-2002 v.0.94 - - Aggiunto supporto dell'attributo ACTIVE delle rule. -02-04-2002 v.0.95 - - Aggiunto il file setup al tarball. -17-04-2002 v.0.96 - - Add webmin module languages files for English and Italian. - - Fix Masquerade and NAT bug. -17-05-2002 v.0.97 - - Add franch webmin language file. - - Fix bugs. -23-05-2002 v.0.98 Giampaolo Tomassoni - - Do you need port-based natting? Here it is... - - Fixed the I-Wanna-Reply-To-Pings-But-It-Doesn't bug: when - the fw accepts pings on a => FIREWALL base, - don't turn the /proc/sys/net/ipv4/icmp_echo_ignore_all - kernel flag on... - - Applied few ahestetic make-ups -14-06-2002 v.0.99 - - Fix turtlefirewall privileges bug. - - Use iptables from PATH (iptables directory need to be in PATH env. var.) - - PreLoad modules for ftp connections and NAT. - - Add CVS, NNTP services. -20-06-2002 v.1.00 - - Change SystemV service start/stop order from 00/99 to 08/92. - - Change TurtleFirewall package file name. - - Check if XML::Parser perl module is installed. - - Add Telnet service. -26-06-2002 v.1.10 - - Add description field for rules and items. - - Add experimental H.323 service. - - Fix bugs. -08-07-2002 v.1.11 - - Setup procedure into webmin module, now Turtle Firewall installation is very easy. - - Removed chkconfig command for setup, it isn't availabe in all GNU/Linux distributions. - - Fix bug in "Create Nat" web interface. - - Other minor changes. -09-07-2002 v.1.12 - - Fix bug in XML::Parser module checking. -03-09-2002 v.1.13 - - Add NAT from a zone interface to a real host (etc. modem interface ip to my pc host). - - Add Redirect module (For Transparent Proxy). - - Fix security hole with INVALID packets filter code by Mark Francis. - - Enhanced Log. - - Add firewall rules for IPsec VPN service. - - Add firewall rules for Webmin service. -10-09-2002 v.1.14 - - The configurable options contains now the option to select the logfile (Karl Lovink) - - The dutch language has been added (Karl Lovink). -13-09-2002 v.1.15 - - Fix "DROP INVALID unclean" bug. -26-09-2002 v.1.16 - - Change webmin category from System to Networking. - - Fix a bug on tcp/udp Local Redirection (Soep). -16-10-2002 v.1.17 - - Fix bug with "--log-level info" iptables option. - - Enhanced log report. - - Enhanced interface. - - Add afp-over-tcp service: AFP (Apple Filing Protocol) over TCP. - (Alain Terriault) - - Add nfs (experimental) -13-11-2002 v.1.18 - - Add Firewall Configuration Options. - - Now you can change firewall rules order (more readable). - - Add fwuserdefservices.xml file for userdefined services. With this file you can write your own - services filter without changing official fwservices.xml file. - The structure of this new file is identical of fwservices.xml file structure. - If you write a service with a name used by fwservices.xml, this new service definition overwrite - the original service definition so, if you want, you can rewrite all services. - IMPORTANT: I invite all to send me your userdefined service filter definitions, so I can add them into - the predefined services list (fwservices.xml) for all Turtle Firewall users. -26-11-2002 v.1.19 - - Fix bug in Zone deletion. - - Fix a bug using aliased interfaces (signaled by Torsten) - - Add German translation (Jimmy Collins) - - Add mysql and kazaa services (Jimmy Collins) - - Add pptp (vpn) and rdp services (Joe MacDonald) - - Add PC-Anyware service (Chris Carter) - - Change setup script for Slackware Linux distribution (A.Frigido, Patrik) -15-01-2003 v.1.20 - - Add optional MAC address field in host edit form. - - Add target field (ACCEPT/DROP/REJECT) in rule edit form. - - Fix bug in Log prefix string, it must be up to 29 chars length. - - Add x11: X Window System service. - - Use numerical notation for ports in fwservices.xml. - - Add Active flag to NAT, Masquerade and Redirect rules. -16-01-2003 v.1.21 - - Fix a bug in Redirection. -12-02-2003 v.1.22 - - Firewall and NAT rules with multiple services. - - Change LOG prefix from "TFW DROP" to "TFW". - - Add --start, --stop and --status options to turtlefirewall main script. - - Add stop button in the webmin turtlefirewall index page. - - Translate error messages (english and italian). - - Add icmp_all service for all messages (request+reply). - - Add all icmp messages in the special service "all". -18-02-2003 v.1.23 - - Add proxy, ssh21, dhcp, snmptrap, socks and eDonkey services (Karl Lovink). - - Fix a bug into log viewer (Fredrik Tuomas). - - Add Configuration Backup/Restore. -31-03-2003 v.1.24 - - Change Turtle Firewall stop process, ping will be reenabled. - - Add AIM/ICQ and Soulseek std services (Frank Förster). - - Add Oracle, VNC, VNC-http services. - - Add rip, syslog, icecast, icp, irc (Karl Lovink). - - Local Redirection Improved. - - Now you can rename all firewall items. - - More options. -02-04-2003 v.1.25 - - Fix bugs. -07-05-2003 v.1.26 - - Fix "de" language file (Frank Förster). - - NAT Improved, now you can change rules order. - - NAT rules bugfix. - - Configuration backup download bugfix. -14-05-2003 v.1.27 - - Small Bug-fix. -15-07-2004 v.1.28 - - Add port 445 to netbios service. - - Add jabber and jabber-s2s (server to server) services. - - Add lpr Line Printer Protocol. - - Add rdp - Windows Remote Desktop Protocol. - - Fix bugs. -19-11-2004 v.1.29 - - Set icmp_echo_ignore_all flag to 0. Turtle Firewall use iptables - rules for drop or allow icmp echo packets. This fix a bug in tfw ping. - - Disable tcp_ecn flag. - - In masquerading configuration now you can specify source,destinatio,service, - port and action (masquerade or not masquerade). -21-11-2004 v.1.30 - - Add * option in source and destination field of a firewall rule: all zones except FIREWALL. -30-11-2004 v.1.31 - - Change rules display in turtlefirewall startup. - - Fix bugs. -17-02-2005 v.1.32 - - Use iptables-restore command to speed up firewall start up. -??-??-2005 v.1.33 - - Add source and destination option to the NAT rules. - - Bugfix on rules with target REJECT (from v.1.32). -31-11-2005 v.1.34 - - Add mangle mark rule attribute for QoS (iproute2). - - Bugfix on turtlefirewall stop procedure (signaled by Ulf Seltmann). -11-01-2006 v.1.36 - - Add multisources and multidestinations in firewall rules. - - Add service attribute in filter xml tag of services definition files. - - Eliminate drop_unclean option, doesn't work with kernel 2.6.x - - Bugfix. -02-02-2006 v.1.37 - - New service definitions were added: - igmp (Internet Group Management Protocol). - bpalogin (BPALogin). - Thanks to Rene Cunningham for this two services. - openvpn (OpenVPN protocolo, www.openvpn.net). - - Bugs were fixed. -20-05-2011 v.1.38 - - Debian 6.0 compatibility (chocolateboy). -23-04-2020 v.2.0 - - OS : Systemd support, RPM package, Ensure running via cron. - - Feature : Added Time, GeoIP and nDPI support. - - Feature : Added Optional IP Blacklist. - - Feature : Added NAT Map to Port. - - Feature : Added HostName Set and IP Set items. - - Feature : Added pptp, sip, h323 and tftp kernel module options. - - Feature : Added Flow Statistics. - - Feature : Moved Marking to Mangle Rules. ( Connmark : for use with tc ) - - Feature : Added Preroute Mangle Rules. ( Connmark Preroute : for use with iproute ) - - Logging : Added Logging per rule and Flowinfo logging for target ACCEPT. - - Services : Removed www service. ( duplicate of http service ) - - Services : Added Google QUIC, Ubiquiti Unifi, Whatsapp, Zoom, Teams, etc. - - Bug : Fixed MAC filtering. ( no ip required ) - - Bug : Fixed Mangle table flush on firewall stop. - - Bug : Migrated ip_conntrack_max to nf_conntrack_max. - - Bug : Limit zone name max characters. - - Bug : Fixed zone deletion verification. - - Connection Tracking : Replaced "-m state --state" with "-m conntrack --ctstate". - - Connection Tracking : Enabled automatic helpers. ( Todo : migrate to CT target ) - - Connection Tracking : Enabled connection marking. - - Connection Tracking : Flush conntrack table on firewall stop. - - Connection Tracking : Added conntrack tools. - - Theme : New Webmin support. ( Todo : Translate new features ) -09-10-2022 v.2.1 - - OS : Kernel 6 compatibility. - - Feature : Removed pptp, sip, h323 and tftp kernel module options. - - Feature : Added Preroute Raw Rules. ( Conntrack Preroute : for use with CT helpers ) - - Feature : Added Raw Rules. ( Conntrack : for use with CT helpers ) - - Connection Tracking : Migrated helpers to CT target. -03-06-2023 v.2.2 - - Bug : Code cleanup. - - Bug : Fixed rename and delete of multi select items used in rules. - - Bug : Fixed port or port range verification in rules. - - Bug : Fixed service display wrap in rules. - - Feature : Added Flow Risk support. - - Feature : Added Optional Domain, JA3 and SHA1 Blacklist support. - - Feature : Added Rate Limit support. - - Feature : Added "dport" Flow Statistics option. - - Feature : Removed Blacklist Flow Reports. - - Feature : Improve Blacklist view. -18-02-2024 v.2.3 - - Bug : Code cleanup. - - Bug : Fixed --mac-source masquerade. - - Bug : Removed depreciated HTML , , , and tags. - - Bug : Limit Blacklist sizes. - - Bug : Remove Domain Blacklist wildcard match. - - Bug : Fixed zone name item verification. - - Bug : Fixed Rate Limit apply when used in multiple rules. - - Feature : Rework action log format. - - Feature : Extend nDPI support. - - Logging : Replaced JA3 server with JA4 client. - - Theme : Rework group item selection. - - Theme : Split Port and nDPI service column in rule views. - - Theme : Update edit forms to use ui standard. - - Theme : Standardize Webmin images. -22-08-2024 v.2.4 - - OS : Old fw.xml format fixes in fixconfig.sh. - - OS : Restore setup.cgi for WBM install. - - OS : Support for Debian 12 syslog date format. - - OS : Standardize shebang. - - Bug : Fixed ApplyRule risk variable not initialised. - - Bug : Fixed GeoIP include for Masquerade and Redirect. - - Bug : Include reserved name check on item rename. - - Services : Removed depreciated smtps TCP port 465 service. - - Services : Added DNS over TLS TCP port 853 service. - - Feature : nDPI 4.9.11 support. - - Feature : Add ipset support. - - Feature : Add prefix support for net items. - - Feature : Add item reference lookup support. - - Todo : Translate new features - - Todo : Fix backup.cgi restore upload. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..530ba48 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,321 @@ +# ChangeLog + +## v.2.7 (11-12-2025) +- Feature : nDPI 5.1 support. +- Bug : Fix variable declarations. +- Bug : Add invalid service check. +- Bug : Don't check group membership for * zone during apply of Masquerade and Redirect. +- Bug : Improve expand_item. +- Bug : Rework LoadServices. +- Bug : Enable strict mode. +- Bug : Add invalid use of MAC address check. +- Todo : Translate new features. +- Todo : Fix backup.cgi restore upload. + +## v.2.6 (30-04-2025) +- Feature : nDPI 4.15 support. +- Feature : Remove JA3 logging. +- Feature : Remove JA3 Blacklist. +- Feature : Remove TLS Version logging, already included in JA4. +- Feature : Migrate Flow Statistics query backend to q-text-as-data + and allow multiple log selection. +- Feature : Add static Blacklist include. +- Bug : Fixed translation of HTML character entities. +- Bug : Fixed Flow Statistics flow time reported incorrectly. +- Bug : Removed default variable reference in log views. +- Bug : Standardize library include and table syntax. +- Bug : Fixed missing sort in item selection. +- Bug : Fixed custom config file definition. +- Bug : Fixed connection marking. +- OS : Remove unused iptables_restore_emu. +- OS : Remove depreciated dkms feature: CLEAN +- Theme : Webmin 2.600 support. +- Theme : Update lib to use ui standard. + +## v.2.5 (01-01-2025) +- Services : Make user defined services permanent. +- Services : Removed depreciated kazaa and edonkey services. +- Feature : nDPI 4.13 support. +- Feature : Add clamp_mss_to_pmtu option. +- Feature : Add nDPI ACCEPT support for Hostnames. + +## v.2.4 (22-08-2024) +- OS : Old fw.xml format fixes in fixconfig.sh. +- OS : Restore setup.cgi for WBM install. +- OS : Support for Debian 12 syslog date format. +- OS : Standardize shebang. +- Bug : Fixed ApplyRule risk variable not initialised. +- Bug : Fixed GeoIP include for Masquerade and Redirect. +- Bug : Include reserved name check on item rename. +- Bug : Fixed rule highlighting on move. +- Bug : Fixed rule tcp/udp ALL ports display. +- Services : Removed depreciated smtps TCP port 465 service. +- Services : Added DNS over TLS TCP port 853 service. +- Feature : nDPI 4.11 support. +- Feature : Add ipset support. +- Feature : Add prefix support for net items. +- Feature : Add item reference lookup support. +- Feature : Make rule order configurable. + +## v.2.3 (18-02-2024) +- Bug : Code cleanup. +- Bug : Fixed --mac-source masquerade. +- Bug : Removed depreciated HTML \, \, \, \ and \ tags. +- Bug : Limit Blacklist sizes. +- Bug : Remove Domain Blacklist wildcard match. +- Bug : Fixed zone name item verification. +- Bug : Fixed Rate Limit apply when used in multiple rules. +- Feature : Rework action log format. +- Feature : Extend nDPI support. +- Logging : Replaced JA3 server with JA4 client. +- Theme : Rework group item selection. +- Theme : Split Port and nDPI service column in rule views. +- Theme : Update edit forms to use ui standard. +- Theme : Standardize Webmin images. + +## v.2.2 (03-06-2023) +- Bug : Code cleanup. +- Bug : Fixed rename and delete of multi select items used in rules. +- Bug : Fixed port or port range verification in rules. +- Bug : Fixed service display wrap in rules. +- Feature : Added Flow Risk support. +- Feature : Added Optional Domain, JA3 and SHA1 Blacklist support. +- Feature : Added Rate Limit support. +- Feature : Added "dport" Flow Statistics option. +- Feature : Removed Blacklist Flow Reports. +- Feature : Improve Blacklist view. + +## v.2.1 (09-10-2022) +- OS : Kernel 6 compatibility. +- Feature : Removed pptp, sip, h323 and tftp kernel module options. +- Feature : Added Preroute Raw Rules. ( Conntrack Preroute : for use with CT helpers ) +- Feature : Added Raw Rules. ( Conntrack : for use with CT helpers ) +- Connection Tracking : Migrated helpers to CT target. + +## v.2.0 (23-04-2020) +- OS : Systemd support, RPM package, Ensure running via cron. +- Feature : Added Time, GeoIP and nDPI support. +- Feature : Added Optional IP Blacklist. +- Feature : Added NAT Map to Port. +- Feature : Added HostName Set and IP Set items. +- Feature : Added pptp, sip, h323 and tftp kernel module options. +- Feature : Added Flow Statistics. +- Feature : Moved Marking to Mangle Rules. ( Connmark : for use with tc ) +- Feature : Added Preroute Mangle Rules. ( Connmark Preroute : for use with iproute ) +- Logging : Added Logging per rule and Flowinfo logging for target ACCEPT. +- Services : Removed www service. ( duplicate of http service ) +- Services : Added Google QUIC, Ubiquiti Unifi, Whatsapp, Zoom, Teams, etc. +- Bug : Fixed MAC filtering. ( no ip required ) +- Bug : Fixed Mangle table flush on firewall stop. +- Bug : Migrated ip_conntrack_max to nf_conntrack_max. +- Bug : Limit zone name max characters. +- Bug : Fixed zone deletion verification. +- Connection Tracking : Replaced "-m state --state" with "-m conntrack --ctstate". +- Connection Tracking : Enabled automatic helpers. ( Todo : migrate to CT target ) +- Connection Tracking : Enabled connection marking. +- Connection Tracking : Flush conntrack table on firewall stop. +- Connection Tracking : Added conntrack tools. +- Theme : New Webmin support. + +## v.1.38 (20-05-2011) +- Debian 6.0 compatibility (chocolateboy). + +## v.1.37 (02-02-2006) +- New service definitions were added: + igmp (Internet Group Management Protocol). + bpalogin (BPALogin). + Thanks to Rene Cunningham for this two services. + openvpn (OpenVPN protocolo, www.openvpn.net). +- Bugs were fixed. + +## v.1.36 (11-01-2006) +- Add multisources and multidestinations in firewall rules. +- Add service attribute in filter xml tag of services definition files. +- Eliminate drop_unclean option, doesn't work with kernel 2.6.x +- Bugfix. + +## v.1.34 (31-11-2005) +- Add mangle mark rule attribute for QoS (iproute2). +- Bugfix on turtlefirewall stop procedure (signaled by Ulf Seltmann). + +## v.1.33 (??-??-2005) +- Add source and destination option to the NAT rules. +- Bugfix on rules with target REJECT (from v.1.32). + +## v.1.32 (17-02-2005) +- Use iptables-restore command to speed up firewall start up. + +## v.1.31 (30-11-2004) +- Change rules display in turtlefirewall startup. +- Fix bugs. + +## v.1.30 (21-11-2004) +- Add * option in source and destination field of a firewall rule: all zones except FIREWALL. + +## v.1.29 (19-11-2004) +- Set icmp_echo_ignore_all flag to 0. Turtle Firewall use iptables + rules for drop or allow icmp echo packets. This fix a bug in tfw ping. +- Disable tcp_ecn flag. +- In masquerading configuration now you can specify source,destinatio,service, + port and action (masquerade or not masquerade). + +## v.1.28 (15-07-2004) +- Add port 445 to netbios service. +- Add jabber and jabber-s2s (server to server) services. +- Add lpr Line Printer Protocol. +- Add rdp - Windows Remote Desktop Protocol. +- Fix bugs. + +## v.1.27 (14-05-2003) +- Small Bug-fix. + +## v.1.26 (07-05-2003) +- Fix "de" language file (Frank Förster). +- NAT Improved, now you can change rules order. +- NAT rules bugfix. +- Configuration backup download bugfix. + +## v.1.25 (02-04-2003) +- Fix bugs. + +## v.1.24 (31-03-2003) +- Change Turtle Firewall stop process, ping will be reenabled. +- Add AIM/ICQ and Soulseek std services (Frank Förster). +- Add Oracle, VNC, VNC-http services. +- Add rip, syslog, icecast, icp, irc (Karl Lovink). +- Local Redirection Improved. +- Now you can rename all firewall items. +- More options. + +## v.1.23 (18-02-2003) +- Add proxy, ssh21, dhcp, snmptrap, socks and eDonkey services (Karl Lovink). +- Fix a bug into log viewer (Fredrik Tuomas). +- Add Configuration Backup/Restore. + +## v.1.22 (02-02-2003) +- Firewall and NAT rules with multiple services. +- Change LOG prefix from "TFW DROP" to "TFW". +- Add --start, --stop and --status options to turtlefirewall main script. +- Add stop button in the webmin turtlefirewall index page. +- Translate error messages (english and italian). +- Add icmp_all service for all messages (request+reply). +- Add all icmp messages in the special service "all". + +## v.1.21 (16-01-2003) +- Fix a bug in Redirection. + +## v.1.20 (15-01-2003) +- Add optional MAC address field in host edit form. +- Add target field (ACCEPT/DROP/REJECT) in rule edit form. +- Fix bug in Log prefix string, it must be up to 29 chars length. +- Add x11: X Window System service. +- Use numerical notation for ports in fwservices.xml. +- Add Active flag to NAT, Masquerade and Redirect rules. + +## v.1.19 (26-11-2002) +- Fix bug in Zone deletion. +- Fix a bug using aliased interfaces (signaled by Torsten) +- Add German translation (Jimmy Collins) +- Add mysql and kazaa services (Jimmy Collins) +- Add pptp (vpn) and rdp services (Joe MacDonald) +- Add PC-Anyware service (Chris Carter) +- Change setup script for Slackware Linux distribution (A.Frigido, Patrik) + +## v.1.18 (13-11-2002) +- Add Firewall Configuration Options. +- Now you can change firewall rules order (more readable). +- Add fwuserdefservices.xml file for userdefined services. With this file you can write your own + services filter without changing official fwservices.xml file. + The structure of this new file is identical of fwservices.xml file structure. + If you write a service with a name used by fwservices.xml, this new service definition overwrite + the original service definition so, if you want, you can rewrite all services. + IMPORTANT: I invite all to send me your userdefined service filter definitions, so I can add them into + the predefined services list (fwservices.xml) for all Turtle Firewall users. + +## v.1.17 (16-10-2002) +- Fix bug with "--log-level info" iptables option. +- Enhanced log report. +- Enhanced interface. +- Add afp-over-tcp service: AFP (Apple Filing Protocol) over TCP. + (Alain Terriault) +- Add nfs (experimental) + +## v.1.16 (26-09-2002) +- Change webmin category from System to Networking. +- Fix a bug on tcp/udp Local Redirection (Soep). + +## v.1.15 (13-09-2002) +- Fix "DROP INVALID unclean" bug. + +## v.1.14 (10-09-2002) +- The configurable options contains now the option to select the logfile (Karl Lovink) +- The dutch language has been added (Karl Lovink). + +## v.1.13 (03-09-2002) +- Add NAT from a zone interface to a real host (etc. modem interface ip to my pc host). +- Add Redirect module (For Transparent Proxy). +- Fix security hole with INVALID packets filter code by Mark Francis. +- Enhanced Log. +- Add firewall rules for IPsec VPN service. +- Add firewall rules for Webmin service. + +## v.1.12 (09-07-2002) +- Fix bug in XML::Parser module checking. + +## v.1.11 (08-07-2002) +- Setup procedure into webmin module, now Turtle Firewall installation is very easy. +- Removed chkconfig command for setup, it isn't availabe in all GNU/Linux distributions. +- Fix bug in "Create Nat" web interface. +- Other minor changes. + +## v.1.10 (26-06-2002) +- Add description field for rules and items. +- Add experimental H.323 service. +- Fix bugs. + +## v.1.00 (20-06-2002) +- Change SystemV service start/stop order from 00/99 to 08/92. +- Change TurtleFirewall package file name. +- Check if XML::Parser perl module is installed. +- Add Telnet service. + +## v.0.99 (14-06-2002) +- Fix turtlefirewall privileges bug. +- Use iptables from PATH (iptables directory need to be in PATH env. var.) +- PreLoad modules for ftp connections and NAT. +- Add CVS, NNTP services. + +## v.0.98 (23-05-2002) +- Do you need port-based natting? Here it is... (Giampaolo Tomassoni) +- Fixed the I-Wanna-Reply-To-Pings-But-It-Doesn't bug: when + the fw accepts pings on a => FIREWALL base, + don't turn the /proc/sys/net/ipv4/icmp_echo_ignore_all + kernel flag on... (Giampaolo Tomassoni) +- Applied few ahestetic make-ups (Giampaolo Tomassoni) + +## v.0.97 (17-05-2002) +- Add franch webmin language file. +- Fix bugs. + +## v.0.96 (17-04-2002) +- Add webmin module languages files for English and Italian. +- Fix Masquerade and NAT bug. + +## v.0.95 (02-04-2002) +- Aggiunto il file setup al tarball. + +## v.0.94 (22-03-2002) +- Aggiunto supporto dell'attributo ACTIVE delle rule. + +## v.0.93 (19-03-2002) +- Aggiunto l'uso del modulo turtlefirewall.pm (/usr/lib) + +## v.0.92 (10-01-2002) +- Inserite le regole di accesso da/verso interfaccia lo + che precedentemente impedivano l'accesso a se stesso. +- Impostati i diritti sul file sh generato per l'esecuzione. +- Corretta la definizione delle lan nei file di configurazione + di esempio (samples). + +## v.0.91 (05-12-2001) +- Modificato il nome da fwconf in Turtle Firewall (turtlefw) diff --git a/INSTALL.el10.md b/INSTALL.el10.md new file mode 100644 index 0000000..b46b73a --- /dev/null +++ b/INSTALL.el10.md @@ -0,0 +1,56 @@ +## RHEL 10 + +Activate Repos. +``` +dnf config-manager --set-enabled extras-common +dnf config-manager --set-enabled crb +dnf config-manager --save --setopt=optional_metadata_types=filelists +dnf -y install epel-release +dnf -y install centos-release-hyperscale-kernel +dnf -y install createrepo wget + +wget https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh +sh setup-repos.sh -f + +mkdir -p /var/tmp/tfw +cd /var/tmp/tfw +curl -s https://api.github.com/repos/netcons/turtlefirewall/releases \ +| grep "browser_download_url.*.el10.*rpm" \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| wget -qi - +createrepo ./ + +cd /etc/pki/rpm-gpg +curl -s https://api.github.com/repos/netcons/turtlefirewall/releases \ +| grep "browser_download_url.*RPM-GPG-KEY-tfw" \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| wget -qi - + +echo '[tfw] +name=CentOS Stream $releasever - Turtlefirewall +baseurl=file:/var/tmp/tfw/ +gpgckeck=1 +gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-tfw +enabled=1' > /etc/yum.repos.d/tfw.repo +``` + +Install Turtle Firewall. +``` +dnf -y upgrade kernel +dnf -y install kernel-devel kernel-headers +dnf -y install turtlefirewall +systemctl enable dkms --now +reboot +``` + +Disable Firewalld. +``` +systemctl disable firewalld --now +``` + +Configure */etc/turtlefirewall/fw.xml* or via Webmin and enable Turtle Firewall. +``` +systemctl enable turtlefirewall --now +``` \ No newline at end of file diff --git a/INSTALL.el7.md b/INSTALL.el7.md new file mode 100644 index 0000000..19a6561 --- /dev/null +++ b/INSTALL.el7.md @@ -0,0 +1,60 @@ +## RHEL 7 + +Activate Repos. +``` +sed -i "s/mirror.centos.org/vault.centos.org/g" /etc/yum.repos.d/*.repo +sed -i "s/^#baseurl=/baseurl=/" /etc/yum.repos.d/*.repo +sed -i "s/^mirrorlist=/#mirrorlist=/" /etc/yum.repos.d/*.repo + +yum -y install yum-utils +yum-config-manager --enable repository extras +yum -y install epel-release +yum -y install createrepo wget + +yum -y install centos-release-scl +sed -i "s/mirror.centos.org/vault.centos.org/g" /etc/yum.repos.d/CentOS-SCLo-scl* +sed -i "s/^# baseurl=/baseurl=/" /etc/yum.repos.d/CentOS-SCLo-scl* +sed -i "s/^mirrorlist=/#mirrorlist=/" /etc/yum.repos.d/CentOS-SCLo-scl* + +wget https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh +sh setup-repos.sh -f + +mkdir -p /var/tmp/tfw +cd /var/tmp/tfw +curl -s https://api.github.com/repos/netcons/turtlefirewall/releases \ +| grep "browser_download_url.*.el7.*rpm" \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| wget -qi - +createrepo ./ + +echo '[tfw] +name=CentOS-$releasever - Turtlefirewall +baseurl=file:/var/tmp/tfw/ +gpgckeck=0 +enabled=1' > /etc/yum.repos.d/tfw.repo + +sed -i "s/^gpgcheck=.*$/gpgcheck=0/" /etc/yum.conf +``` + +Install Turtle Firewall. +``` +yum -y upgrade kernel +yum -y install kernel-devel kernel-headers +yum -y upgrade iptables iptables-ebtables +yum -y install turtlefirewall +yum -y install devtoolset-9-* +echo "source /opt/rh/devtoolset-9/enable" >> /etc/dkms/framework.conf +systemctl enable dkms --now +reboot +``` + +Disable Firewalld. +``` +systemctl disable firewalld --now +``` + +Configure */etc/turtlefirewall/fw.xml* or via Webmin and enable Turtle Firewall. +``` +systemctl enable turtlefirewall --now +``` \ No newline at end of file diff --git a/INSTALL.el8.md b/INSTALL.el8.md new file mode 100644 index 0000000..4e663e9 --- /dev/null +++ b/INSTALL.el8.md @@ -0,0 +1,55 @@ +## RHEL 8 + +Activate Repos. +``` +sed -i "s/mirror.centos.org/vault.centos.org/g" /etc/yum.repos.d/*.repo +sed -i "s/^#baseurl=/baseurl=/" /etc/yum.repos.d/*.repo +sed -i "s/^mirrorlist=/#mirrorlist=/" /etc/yum.repos.d/*.repo + +dnf config-manager --set-enabled extras-common +dnf config-manager --set-enabled powertools +dnf -y install epel-release +dnf -y install createrepo wget + +dnf -y install centos-release-hyperscale-experimental +sed -i "s/mirror.centos.org/vault.centos.org/g" /etc/yum.repos.d/CentOS-Stream-Hyperscale* +sed -i "s/^#baseurl=/baseurl=/" /etc/yum.repos.d/CentOS-Stream-Hyperscale* +sed -i "s/^mirrorlist=/#mirrorlist=/" /etc/yum.repos.d/CentOS-Stream-Hyperscale* + +wget https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh +sh setup-repos.sh -f + +mkdir -p /var/tmp/tfw +cd /var/tmp/tfw +curl -s https://api.github.com/repos/netcons/turtlefirewall/releases \ +| grep "browser_download_url.*.el8.*rpm" \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| wget -qi - +createrepo ./ + +echo '[tfw] +name=CentOS Stream $releasever - Turtlefirewall +baseurl=file:/var/tmp/tfw/ +gpgckeck=0 +enabled=1' > /etc/yum.repos.d/tfw.repo +``` + +Install Turtle Firewall. +``` +dnf -y upgrade kernel +dnf -y install kernel-devel kernel-headers +dnf -y install turtlefirewall +systemctl enable dkms --now +reboot +``` + +Disable Firewalld. +``` +systemctl disable firewalld --now +``` + +Configure */etc/turtlefirewall/fw.xml* or via Webmin and enable Turtle Firewall. +``` +systemctl enable turtlefirewall --now +``` \ No newline at end of file diff --git a/INSTALL.el9.md b/INSTALL.el9.md new file mode 100644 index 0000000..07afbb0 --- /dev/null +++ b/INSTALL.el9.md @@ -0,0 +1,47 @@ +## RHEL 9 + +Activate Repos. +``` +dnf config-manager --set-enabled extras-common +dnf config-manager --set-enabled crb +dnf -y install epel-release +dnf -y install centos-release-hyperscale-experimental +dnf -y install createrepo wget + +wget https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh +sh setup-repos.sh -f + +mkdir -p /var/tmp/tfw +cd /var/tmp/tfw +curl -s https://api.github.com/repos/netcons/turtlefirewall/releases \ +| grep "browser_download_url.*.el9.*rpm" \ +| cut -d : -f 2,3 \ +| tr -d \" \ +| wget -qi - +createrepo ./ + +echo '[tfw] +name=CentOS Stream $releasever - Turtlefirewall +baseurl=file:/var/tmp/tfw/ +gpgckeck=0 +enabled=1' > /etc/yum.repos.d/tfw.repo +``` + +Install Turtle Firewall. +``` +dnf -y upgrade kernel +dnf -y install kernel-devel kernel-headers +dnf -y install turtlefirewall +systemctl enable dkms --now +reboot +``` + +Disable Firewalld. +``` +systemctl disable firewalld --now +``` + +Configure */etc/turtlefirewall/fw.xml* or via Webmin and enable Turtle Firewall. +``` +systemctl enable turtlefirewall --now +``` \ No newline at end of file diff --git a/INSTALL.md b/INSTALL.md index 794401c..5a3ef2f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -27,7 +27,7 @@ apt-get install webmin --install-recommends Download source. ``` cd /tmp -wget https://github.com/frisoft/turtlefirewall/archive/master.zip -O turtlefirewall-master.zip +wget https://github.com/netcons/turtlefirewall/archive/master.zip -O turtlefirewall-master.zip unzip turtlefirewall-master.zip cd turtlefirewall-master ``` @@ -39,13 +39,13 @@ Build source. Install RHEL. ``` -dnf -y install perl-XML-Parser perl-Net-CIDR-Lite perl-Text-CSV_XS iptables-nft ipset conntrack-tools rsyslog dos2unix gawk crontabs +dnf -y install perl-XML-Parser perl-Net-CIDR-Lite perl-Text-CSV_XS iptables-nft ipset conntrack-tools rsyslog dos2unix gawk crontabs q-text-as-data /usr/libexec/webmin/install-module.pl /tmp/turtlefirewall-master/build/turtlefirewall-*.wbm.gz ``` Install Debian. ``` -apt-get -y install libxml-parser-perl libnet-cidr-lite-perl libtext-csv-xs-perl iptables ipset conntrack rsyslog dos2unix gawk cron-daemon-common +apt-get -y install libxml-parser-perl libnet-cidr-lite-perl libtext-csv-xs-perl iptables ipset conntrack rsyslog dos2unix gawk cron-daemon-common python3-q-text-as-data /usr/share/webmin/install-module.pl /tmp/turtlefirewall-master/build/turtlefirewall-*.wbm.gz ``` @@ -53,11 +53,20 @@ apt-get -y install libxml-parser-perl libnet-cidr-lite-perl libtext-csv-xs-perl RHEL. ``` -dnf -y install centos-release-hyperscale-experimental +if (grep -w "10" /etc/redhat-release) > /dev/null 2>&1 + then + dnf -y install centos-release-hyperscale-kernel +fi +if (grep -w "9" /etc/redhat-release) > /dev/null 2>&1 + then + dnf -y install centos-release-hyperscale-experimental +fi + dnf -y upgrade kernel reboot dnf -y install kernel-devel kernel-headers +dnf -y install kernel-modules-extra dnf -y install iptables-devel libpcap-devel json-c-devel libgcrypt-devel perl-File-Path dnf -y install autoconf automake libtool dnf -y install dkms @@ -66,6 +75,7 @@ systemctl enable dkms --now Debian. ``` +apt-get -y install linux-headers-$(uname -r) apt-get -y install libxtables-dev libpcap-dev libjson-c-dev libgcrypt-dev libmodule-path-perl apt-get -y install autoconf automake libtool apt-get -y install dkms @@ -75,20 +85,22 @@ apt-get -y install dkms Download source. ``` +VERSION="0.3.3" cd /usr/src wget https://github.com/aabc/ipt-ratelimit/archive/master.zip -O ipt-ratelimit-master.zip unzip ipt-ratelimit-master.zip -mv ipt-ratelimit-master ipt-ratelimit-0.3.3 +mv ipt-ratelimit-master ipt-ratelimit-$VERSION rm -rf ipt-ratelimit-master.zip -cd ipt-ratelimit-0.3.3 +cd ipt-ratelimit-$VERSION ``` Install module. ``` cp /tmp/turtlefirewall-master/dkms/dkms-ipt-ratelimit.conf ./dkms.conf -dkms add -m ipt-ratelimit -v 0.3.3 -dkms build -m ipt-ratelimit -v 0.3.3 -dkms install -m ipt-ratelimit -v 0.3.3 +sed -i "s/^PACKAGE_VERSION=.*$/PACKAGE_VERSION=\"$VERSION\"/" dkms.conf +dkms add -m ipt-ratelimit -v $VERSION +dkms build -m ipt-ratelimit -v $VERSION +dkms install -m ipt-ratelimit -v $VERSION ``` Install library. @@ -100,19 +112,21 @@ make all install Download source. ``` +VERSION="3.30" cd /usr/src -wget https://inai.de/files/xtables-addons/xtables-addons-3.27.tar.xz -O xtables-addons-3.27.tar.xz -tar -xvf xtables-addons-3.27.tar.xz -rm -rf xtables-addons-3.27.tar.xz -cd xtables-addons-3.27 +wget https://codeberg.org/jengelh/xtables-addons/releases/download/v${VERSION}/xtables-addons-${VERSION}.tar.zst +tar --zstd -xvf xtables-addons-${VERSION}.tar.zst +rm -rf xtables-addons-${VERSION}.tar.zst +cd xtables-addons-$VERSION ``` Install module. ``` cp /tmp/turtlefirewall-master/dkms/dkms-xtables-addons.conf ./dkms.conf -dkms add -m xtables-addons -v 3.27 -dkms build -m xtables-addons -v 3.27 -dkms install -m xtables-addons -v 3.27 +sed -i "s/^PACKAGE_VERSION=.*$/PACKAGE_VERSION=\"$VERSION\"/" dkms.conf +dkms add -m xtables-addons -v $VERSION +dkms build -m xtables-addons -v $VERSION +dkms install -m xtables-addons -v $VERSION ``` Install library. @@ -126,26 +140,29 @@ make install Download source. ``` +VERSION="5.1.0" cd /usr/src wget https://github.com/vel21ripn/nDPI/archive/master.zip -O nDPI-flow_info-4.zip unzip nDPI-flow_info-4.zip -mv nDPI-flow_info-4 ndpi-netfilter-4.11.0 +mv nDPI-flow_info-4 ndpi-netfilter-$VERSION rm -rf nDPI-flow_info-4.zip -cd ndpi-netfilter-4.11.0 +cd ndpi-netfilter-$VERSION rm -rf windows ``` Install module. ``` cp /tmp/turtlefirewall-master/dkms/dkms-ndpi-netfilter.conf ./dkms.conf -dkms add -m ndpi-netfilter -v 4.11.0 -dkms build -m ndpi-netfilter -v 4.11.0 -dkms install -m ndpi-netfilter -v 4.11.0 +sed -i "s/^PACKAGE_VERSION=.*$/PACKAGE_VERSION=\"$VERSION\"/" dkms.conf +dkms add -m ndpi-netfilter -v $VERSION +dkms build -m ndpi-netfilter -v $VERSION +dkms install -m ndpi-netfilter -v $VERSION ``` Install library. ``` ./autogen.sh +./configure cd ndpi-netfilter make make install @@ -155,9 +172,10 @@ make install Download source. ``` +VERSION="1.0.0" cd /usr/src -mkdir xtables-time-1.0.0 -cd xtables-time-1.0.0 +mkdir xtables-time-$VERSION +cd xtables-time-$VERSION wget https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/net/netfilter/xt_time.c -O ./xt_time.c cp /tmp/turtlefirewall-master/dkms/Makefile.xt_time ./Makefile ``` @@ -165,24 +183,36 @@ cp /tmp/turtlefirewall-master/dkms/Makefile.xt_time ./Makefile Install module. ``` cp /tmp/turtlefirewall-master/dkms/dkms-xtables-time.conf ./dkms.conf -dkms add -m xtables-time -v 1.0.0 -dkms build -m xtables-time -v 1.0.0 -dkms install -m xtables-time -v 1.0.0 +sed -i "s/^PACKAGE_VERSION=.*$/PACKAGE_VERSION=\"$VERSION\"/" dkms.conf +dkms add -m xtables-time -v $VERSION +dkms build -m xtables-time -v $VERSION +dkms install -m xtables-time -v $VERSION ``` ## Turtlefirewall Setup -First finalise setup via Webmin, then enable service. - -RHEL. +Disable default firewall RHEL. ``` -/etc/cron.daily/xt_geoip_update systemctl disable firewalld --now -systemctl enable turtlefirewall --now +``` +Finalise setup via Webmin or command line RHEL. +``` +cd /usr/libexec/webmin/turtlefirewall/setup +/usr/bin/env perl setup +cd .. +rm -rf setup* ``` -Debian. +Finalise setup via Webmin or command line Debian. +``` +cd /usr/share/webmin/turtlefirewall/setup +/usr/bin/env perl setup +cd .. +rm -rf setup* +``` + +Download GeoIP database and enable service. ``` /etc/cron.daily/xt_geoip_update systemctl enable turtlefirewall --now diff --git a/README.md b/README.md index ab41dad..f949293 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,24 @@ ## Turtle Firewall 2 Turtle Firewall allows you to configure a Linux firewall in a simple and fast way. -It's based on Netfilter iptables. Its operation is easy to understand: you can define the different firewall elements (zones, hosts, networks, geoip) and then set the services (port, dpi) you want to control (allow, deny, ratelimit, log) among the different elements or groups of elements. -You can do this by simply editing a XML file or using the web interface [Webmin](http://www.webmin.com/). +It's based on Netfilter iptables. Its operation is easy to understand: you can define the different firewall elements (zones, hosts, networks, geoips, ipsets) and then set the services (port, dpi) you want to control (allow, deny, ratelimit, log) among the different elements or groups of elements. +You can do this by simply editing a XML file or using the web interface ([Webmin](https://www.webmin.com/)). -Turtle Firewall is an Open Source project written using the perl language and realeased under GPL version 2.0 by Andrea Frigido (Frisoft). +Turtle Firewall is an Open Source project written using the perl language and realeased under GPL version 2.0 +by Andrea Frigido ([frisoft](https://github.com/frisoft)). ## New Features -- Time. -- Geo Location. -- Deep Packet Inspection. -- Risk Detection. -- Rate Limiting. -- Blacklists. -- NAT Map to Port. -- Logging per rule. -- Flow Info logging. -- Flow Statistics. -- Connection Marking. -- Connection Tracking. +- Time, GeoIP and nDPI Support. +- Blacklists and Flow Risks. +- Rate Limit Support. +- Logging per Rule. ( target ACCEPT logs flow, target DROP/REJECT logs action ) +- Flow Statistics. ( via Netflow nDPI classified historical flow data to disk ) +- Connection Marking. ( for use with tc and iproute ) +- Connection Tracking. ( for use with CT helpers ) +- NAT Map to Port. ( for port redirection ) +- Address Lists and CIDR Networks. +- Item Reference Lookup and Rule Order Configuration Support. ## Requirements @@ -31,7 +30,9 @@ Turtle Firewall is an Open Source project written using the perl language and re nf_tables,
nf_conntrack,
xt_connmark,
-xt_time.
+xt_time,
+xt_set,
+xt_tcpmss.
- Extra Netfilter kernel modules :
xt_ndpi, ( https://github.com/vel21ripn/nDPI )
xt_geoip, ( https://codeberg.org/jengelh/xtables-addons )
diff --git a/dkms/Makefile.xt_time b/dkms/Makefile.xt_time index d5a200a..6bcbbe2 100644 --- a/dkms/Makefile.xt_time +++ b/dkms/Makefile.xt_time @@ -1,7 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 # -## Makefile for the linux hfsplus filesystem routines. -# # If KERNELRELEASE is defined, the make command using this Makefile has # been invoked by the kernel build system and so can use its language. # Otherwise, if KERNELRELEASE is null, a make command was issued from diff --git a/dkms/dkms-ipt-ratelimit.conf b/dkms/dkms-ipt-ratelimit.conf index 92a5bb1..b98b53f 100644 --- a/dkms/dkms-ipt-ratelimit.conf +++ b/dkms/dkms-ipt-ratelimit.conf @@ -4,7 +4,6 @@ PACKAGE_VERSION="0.3.3" PACKAGE_NAME="ipt-ratelimit" BDIR="$dkms_tree/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" -CLEAN="make clean" MAKE="make all ; find ${BDIR} -name '*.ko' -exec mv -v {} ${BDIR} \;" AUTOINSTALL="yes" diff --git a/dkms/dkms-ndpi-netfilter.conf b/dkms/dkms-ndpi-netfilter.conf index 39a23d8..d3f4e6b 100644 --- a/dkms/dkms-ndpi-netfilter.conf +++ b/dkms/dkms-ndpi-netfilter.conf @@ -1,12 +1,11 @@ -PACKAGE_VERSION="4.11.0" +PACKAGE_VERSION="5.1.0" # Items below here should not have to change with each driver version PACKAGE_NAME="ndpi-netfilter" BDIR="$dkms_tree/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" PRE_BUILD="autogen.sh" -CLEAN="make clean" -MAKE="make -C ndpi-netfilter; find ${BDIR} -name '*.ko' -exec mv -v {} ${BDIR} \;" +MAKE="./configure; make -C ndpi-netfilter; find ${BDIR} -name '*.ko' -exec mv -v {} ${BDIR} \;" AUTOINSTALL="yes" @@ -15,4 +14,4 @@ AUTOINSTALL="yes" BUILT_MODULE_LOCATION[0]="" BUILT_MODULE_NAME[0]="xt_ndpi" -DEST_MODULE_LOCATION[0]="/extra" +DEST_MODULE_LOCATION[0]="/extra" \ No newline at end of file diff --git a/dkms/dkms-xtables-addons.conf b/dkms/dkms-xtables-addons.conf index 3398dd1..823b8a6 100644 --- a/dkms/dkms-xtables-addons.conf +++ b/dkms/dkms-xtables-addons.conf @@ -1,4 +1,4 @@ -PACKAGE_VERSION="3.26" +PACKAGE_VERSION="3.30" # Items below here should not have to change with each driver version @@ -6,7 +6,6 @@ PACKAGE_NAME="xtables-addons" BDIR="$dkms_tree/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" MAKEARGS=" -C $kernel_source_dir M=${BDIR}/extensions XA_ABSTOPSRCDIR=${BDIR} XA_TOPSRCDIR=${BDIR} V=1" PRE_BUILD="configure" -CLEAN="make ${MAKEARGS} clean" MAKE="make ${MAKEARGS} modules ; find ${BDIR} -name '*.ko' -exec mv -v {} ${BDIR} \;" AUTOINSTALL="yes" @@ -14,94 +13,94 @@ AUTOINSTALL="yes" # Automatically generated rules below #### -BUILT_MODULE_LOCATION[0]="" -BUILT_MODULE_NAME[0]="xt_ACCOUNT" +BUILT_MODULE_LOCATION[0]="" +BUILT_MODULE_NAME[0]="xt_ACCOUNT" DEST_MODULE_LOCATION[0]="/extra" -BUILT_MODULE_LOCATION[1]="" -BUILT_MODULE_NAME[1]="compat_xtables" +BUILT_MODULE_LOCATION[1]="" +BUILT_MODULE_NAME[1]="xt_CHAOS" DEST_MODULE_LOCATION[1]="/extra" -BUILT_MODULE_LOCATION[2]="" -BUILT_MODULE_NAME[2]="xt_pknock" +BUILT_MODULE_LOCATION[2]="" +BUILT_MODULE_NAME[2]="xt_DELUDE" DEST_MODULE_LOCATION[2]="/extra" -BUILT_MODULE_LOCATION[3]="" -BUILT_MODULE_NAME[3]="xt_CHAOS" +BUILT_MODULE_LOCATION[3]="" +BUILT_MODULE_NAME[3]="xt_DHCPMAC" DEST_MODULE_LOCATION[3]="/extra" -BUILT_MODULE_LOCATION[4]="" -BUILT_MODULE_NAME[4]="xt_DELUDE" +BUILT_MODULE_LOCATION[4]="" +BUILT_MODULE_NAME[4]="xt_DNETMAP" DEST_MODULE_LOCATION[4]="/extra" -BUILT_MODULE_LOCATION[5]="" -BUILT_MODULE_NAME[5]="xt_DHCPMAC" +BUILT_MODULE_LOCATION[5]="" +BUILT_MODULE_NAME[5]="xt_ECHO" DEST_MODULE_LOCATION[5]="/extra" -BUILT_MODULE_LOCATION[6]="" -BUILT_MODULE_NAME[6]="xt_DNETMAP" +BUILT_MODULE_LOCATION[6]="" +BUILT_MODULE_NAME[6]="xt_IPMARK" DEST_MODULE_LOCATION[6]="/extra" -BUILT_MODULE_LOCATION[7]="" -BUILT_MODULE_NAME[7]="xt_ECHO" +BUILT_MODULE_LOCATION[7]="" +BUILT_MODULE_NAME[7]="xt_LOGMARK" DEST_MODULE_LOCATION[7]="/extra" -BUILT_MODULE_LOCATION[8]="" -BUILT_MODULE_NAME[8]="xt_IPMARK" +BUILT_MODULE_LOCATION[8]="" +BUILT_MODULE_NAME[8]="xt_PROTO" DEST_MODULE_LOCATION[8]="/extra" -BUILT_MODULE_LOCATION[9]="" -BUILT_MODULE_NAME[9]="xt_LOGMARK" +BUILT_MODULE_LOCATION[9]="" +BUILT_MODULE_NAME[9]="xt_SYSRQ" DEST_MODULE_LOCATION[9]="/extra" -BUILT_MODULE_LOCATION[10]="" -BUILT_MODULE_NAME[10]="xt_PROTO" +BUILT_MODULE_LOCATION[10]="" +BUILT_MODULE_NAME[10]="xt_TARPIT" DEST_MODULE_LOCATION[10]="/extra" -BUILT_MODULE_LOCATION[11]="" -BUILT_MODULE_NAME[11]="xt_SYSRQ" +BUILT_MODULE_LOCATION[11]="" +BUILT_MODULE_NAME[11]="xt_asn" DEST_MODULE_LOCATION[11]="/extra" -BUILT_MODULE_LOCATION[12]="" -BUILT_MODULE_NAME[12]="xt_TARPIT" +BUILT_MODULE_LOCATION[12]="" +BUILT_MODULE_NAME[12]="xt_condition" DEST_MODULE_LOCATION[12]="/extra" -BUILT_MODULE_LOCATION[13]="" -BUILT_MODULE_NAME[13]="xt_condition" +BUILT_MODULE_LOCATION[13]="" +BUILT_MODULE_NAME[13]="xt_fuzzy" DEST_MODULE_LOCATION[13]="/extra" -BUILT_MODULE_LOCATION[14]="" -BUILT_MODULE_NAME[14]="xt_fuzzy" +BUILT_MODULE_LOCATION[14]="" +BUILT_MODULE_NAME[14]="xt_geoip" DEST_MODULE_LOCATION[14]="/extra" -BUILT_MODULE_LOCATION[15]="" -BUILT_MODULE_NAME[15]="xt_geoip" +BUILT_MODULE_LOCATION[15]="" +BUILT_MODULE_NAME[15]="xt_iface" DEST_MODULE_LOCATION[15]="/extra" -BUILT_MODULE_LOCATION[16]="" -BUILT_MODULE_NAME[16]="xt_iface" +BUILT_MODULE_LOCATION[16]="" +BUILT_MODULE_NAME[16]="xt_ipp2p" DEST_MODULE_LOCATION[16]="/extra" -BUILT_MODULE_LOCATION[17]="" -BUILT_MODULE_NAME[17]="xt_ipp2p" +BUILT_MODULE_LOCATION[17]="" +BUILT_MODULE_NAME[17]="xt_ipv4options" DEST_MODULE_LOCATION[17]="/extra" -BUILT_MODULE_LOCATION[18]="" -BUILT_MODULE_NAME[18]="xt_ipv4options" +BUILT_MODULE_LOCATION[18]="" +BUILT_MODULE_NAME[18]="xt_length2" DEST_MODULE_LOCATION[18]="/extra" -BUILT_MODULE_LOCATION[19]="" -BUILT_MODULE_NAME[19]="xt_length2" +BUILT_MODULE_LOCATION[19]="" +BUILT_MODULE_NAME[19]="xt_lscan" DEST_MODULE_LOCATION[19]="/extra" -BUILT_MODULE_LOCATION[20]="" -BUILT_MODULE_NAME[20]="xt_lscan" +BUILT_MODULE_LOCATION[20]="" +BUILT_MODULE_NAME[20]="xt_pknock" DEST_MODULE_LOCATION[20]="/extra" -BUILT_MODULE_LOCATION[21]="" -BUILT_MODULE_NAME[21]="xt_psd" +BUILT_MODULE_LOCATION[21]="" +BUILT_MODULE_NAME[21]="xt_psd" DEST_MODULE_LOCATION[21]="/extra" -BUILT_MODULE_LOCATION[22]="" -BUILT_MODULE_NAME[22]="xt_quota2" +BUILT_MODULE_LOCATION[22]="" +BUILT_MODULE_NAME[22]="xt_quota2" DEST_MODULE_LOCATION[22]="/extra" diff --git a/dkms/dkms-xtables-time.conf b/dkms/dkms-xtables-time.conf index cfac3b6..6465673 100644 --- a/dkms/dkms-xtables-time.conf +++ b/dkms/dkms-xtables-time.conf @@ -5,7 +5,6 @@ PACKAGE_VERSION="1.0.0" PACKAGE_NAME="xtables-time" BDIR="$dkms_tree/${PACKAGE_NAME}/${PACKAGE_VERSION}/build" MAKEARGS=" -C $kernel_source_dir M=${BDIR}" -CLEAN="make ${MAKEARGS} clean" MAKE="make ${MAKEARGS} modules; find ${BDIR} -name '*.ko' -exec mv -v {} ${BDIR} \;" AUTOINSTALL="yes" @@ -15,4 +14,4 @@ AUTOINSTALL="yes" BUILT_MODULE_LOCATION[0]="" BUILT_MODULE_NAME[0]="xt_time" -DEST_MODULE_LOCATION[0]="/extra" +DEST_MODULE_LOCATION[0]="/extra" \ No newline at end of file diff --git a/src/turtlefirewall/backup.cgi b/src/turtlefirewall/backup.cgi index 382050b..7595fa2 100644 --- a/src/turtlefirewall/backup.cgi +++ b/src/turtlefirewall/backup.cgi @@ -3,19 +3,19 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); if( $in{download} ) { &backup_download(); } -&ui_print_header( "$icons{SHIELD}{IMAGE}$text{'backup_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_backup'}", $text{'title'}, "" ); if( $in{upload} ) { # FIXME @@ -24,7 +24,7 @@ if( $in{upload} ) { # FIXME } else { print qq~
- +
@@ -39,7 +39,7 @@ if( $in{upload} ) {
$text{'backup_backuptitle'}
- +
@@ -94,7 +94,7 @@ sub restore_upload { syswrite(TARGZ, $backup, length($backup)); close TARGZ; - print qq~
$text{'backup_restoretitle'}
+ print qq~
diff --git a/src/turtlefirewall/edit_addresslist.cgi b/src/turtlefirewall/edit_addresslist.cgi index ff10c68..08eb600 100644 --- a/src/turtlefirewall/edit_addresslist.cgi +++ b/src/turtlefirewall/edit_addresslist.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -19,7 +19,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_addresslist_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my $addresslist = $in{'addresslist'}; my $newaddresslist = $in{'newaddresslist'}; diff --git a/src/turtlefirewall/edit_connmark.cgi b/src/turtlefirewall/edit_connmark.cgi index 579b834..0373542 100644 --- a/src/turtlefirewall/edit_connmark.cgi +++ b/src/turtlefirewall/edit_connmark.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nConnmarks = $fw->GetConnmarksCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_connmark_title_create'}"; - $idx = ''; + $nConnmarks++; + $idx = $nConnmarks; + $newIdx = ''; $src = ''; $dst = ''; $service = ''; @@ -30,6 +34,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_connmark_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %rule = $fw->GetConnmark($idx); $src = $rule{'SRC'}; $dst = $rule{'DST'}; @@ -43,7 +48,10 @@ if( $new ) { $mark = $rule{'MARK'}; $active = $rule{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_manglerules'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nConnmarks; $i++ ) { push @idxs, $i; } my @selected_src = split(/,/, $src); my @selected_dst = split(/,/, $dst); @@ -75,10 +83,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("src", \@selected_src, \@items, 5, 1); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'rule_src'}", $col ], \@tds); $col = &ui_select("dst", \@selected_dst, \@items, 5, 1); @@ -111,4 +117,4 @@ print "
$text{'backup_restoretitle'}
"; print &ui_form_end(); print "

"; -&ui_print_footer("list_manglerules.cgi?idx=$idx",'Mangle Rules list'); +&ui_print_footer("list_manglerules.cgi?table=connmark&idx=$idx",'Mangle Rules list'); diff --git a/src/turtlefirewall/edit_connmarkpreroute.cgi b/src/turtlefirewall/edit_connmarkpreroute.cgi index f17cf46..93d92de 100644 --- a/src/turtlefirewall/edit_connmarkpreroute.cgi +++ b/src/turtlefirewall/edit_connmarkpreroute.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nConnmarkPreroutes = $fw->GetConnmarkPreroutesCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_connmarkpreroute_title_create'}"; - $idx = ''; + $nConnmarkPreroutes++; + $idx = $nConnmarkPreroutes; + $newIdx = ''; $src = ''; $dst = ''; $service = ''; @@ -30,6 +34,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_connmarkpreroute_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %rule = $fw->GetConnmarkPreroute($idx); $src = $rule{'SRC'}; $dst = $rule{'DST'}; @@ -43,7 +48,10 @@ if( $new ) { $mark = $rule{'MARK'}; $active = $rule{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_manglerules'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nConnmarkPreroutes; $i++ ) { push @idxs, $i; } my @items_src = (); push @items_src, grep(!/FIREWALL/, $fw->GetZoneList()); @@ -79,10 +87,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("src", $src, \@items_src); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'rule_src'}", $col ], \@tds); $col = &ui_select("dst", $dst, \@items_dst); @@ -116,4 +122,4 @@ print ""; print &ui_form_end(); print "

"; -&ui_print_footer("list_manglerules.cgi?idx=$idx",'Mangle Rules list'); +&ui_print_footer("list_manglerules.cgi?table=connmarkpreroute&idx=$idx",'Mangle Rules list'); diff --git a/src/turtlefirewall/edit_conntrack.cgi b/src/turtlefirewall/edit_conntrack.cgi index aa507c9..442f218 100644 --- a/src/turtlefirewall/edit_conntrack.cgi +++ b/src/turtlefirewall/edit_conntrack.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nConntracks = $fw->GetConntracksCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_conntrack_title_create'}"; - $idx = ''; + $nConntracks++; + $idx = $nConntracks; + $newIdx = ''; $src = 'FIREWALL'; $dst = ''; $service = ''; @@ -25,6 +29,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_conntrack_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %rule = $fw->GetConntrack($idx); $src = $rule{'SRC'}; $dst = $rule{'DST'}; @@ -33,7 +38,10 @@ if( $new ) { $helper = $rule{'HELPER'}; $active = $rule{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_rawrules'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nConntracks; $i++ ) { push @idxs, $i; } my @items_dst = ('*'); push @items_dst, grep(!/FIREWALL/, $fw->GetZoneList()); @@ -54,10 +62,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = "$src"; $col .= &ui_hidden("src", $src); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'rule_src'}", $col ], \@tds); @@ -69,7 +75,7 @@ $col .= &ui_textbox("port", $port, 11, 0, 11); $col .= "$text{port_help}"; print &ui_columns_row([ "$icons{SERVICE}{IMAGE}$text{'rule_service'}", $col ], \@tds); $col = &ui_select("helper", $helper, \@helpers); -print &ui_columns_row([ "$icons{NDPISERVICE}{IMAGE}$text{'rule_helper'}", $col ], \@tds); +print &ui_columns_row([ "$icons{HELPER}{IMAGE}$text{'rule_helper'}", $col ], \@tds); $col = &ui_checkbox("active", 1, undef, $active ? 1 : 0); print &ui_columns_row([ "$icons{ACTIVE}{IMAGE}$text{'rule_active'}", $col ], \@tds); print &ui_columns_end(); @@ -86,4 +92,4 @@ print ""; print &ui_form_end(); print "

"; -&ui_print_footer("list_rawrules.cgi?idx=$idx",'Raw Rules list'); +&ui_print_footer("list_rawrules.cgi?table=conntrack&idx=$idx",'Raw Rules list'); diff --git a/src/turtlefirewall/edit_conntrackpreroute.cgi b/src/turtlefirewall/edit_conntrackpreroute.cgi index 9d0b94d..1566628 100644 --- a/src/turtlefirewall/edit_conntrackpreroute.cgi +++ b/src/turtlefirewall/edit_conntrackpreroute.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nConntrackPreroutes = $fw->GetConntrackPreroutesCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_conntrackpreroute_title_create'}"; - $idx = ''; + $nConntrackPreroutes++; + $idx = $nConntrackPreroutes; + $newIdx = ''; $src = ''; $dst = ''; $service = ''; @@ -25,6 +29,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_conntrackpreroute_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %rule = $fw->GetConntrackPreroute($idx); $src = $rule{'SRC'}; $dst = $rule{'DST'}; @@ -33,7 +38,10 @@ if( $new ) { $helper = $rule{'HELPER'}; $active = $rule{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_rawrules'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nConntrackPreroutes; $i++ ) { push @idxs, $i; } my @items_src = ('*'); push @items_src, grep(!/FIREWALL/, $fw->GetZoneList()); @@ -61,10 +69,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("src", $src, \@items_src); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'rule_src'}", $col ], \@tds); $col = &ui_select("dst", $dst, \@items_dst); @@ -76,7 +82,7 @@ $col .= &ui_textbox("port", $port, 11, 0, 11); $col .= "$text{port_help}"; print &ui_columns_row([ "$icons{SERVICE}{IMAGE}$text{'rule_service'}", $col ], \@tds); $col = &ui_select("helper", $helper, \@helpers); -print &ui_columns_row([ "$icons{NDPISERVICE}{IMAGE}$text{'rule_helper'}", $col ], \@tds); +print &ui_columns_row([ "$icons{HELPER}{IMAGE}$text{'rule_helper'}", $col ], \@tds); $col = &ui_checkbox("active", 1, undef, $active ? 1 : 0); print &ui_columns_row([ "$icons{ACTIVE}{IMAGE}$text{'rule_active'}", $col ], \@tds); print &ui_columns_end(); @@ -93,4 +99,4 @@ print ""; print &ui_form_end(); print "

"; -&ui_print_footer("list_rawrules.cgi?idx=$idx",'Raw Rules list'); +&ui_print_footer("list_rawrules.cgi?table=conntrackpreroute&idx=$idx",'Raw Rules list'); diff --git a/src/turtlefirewall/edit_flowstat.cgi b/src/turtlefirewall/edit_flowstat.cgi index c8ab92c..6ea7b21 100644 --- a/src/turtlefirewall/edit_flowstat.cgi +++ b/src/turtlefirewall/edit_flowstat.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; use Tie::File; -&ui_print_header( "$icons{CREATE}{IMAGE}$text{'edit_flowstat_title_create'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_flowstat'}", $text{'title'}, "" ); &reportFlowStat(); print "

"; @@ -22,36 +22,58 @@ print "

"; sub reportFlowStat { - my $log = $FlowLogFile; - + my @items_type = (); my @types = sort keys %flowreports; - my @maxs = ( 'all', '100', '1000', '10000', '100000' ); - my @tops = ( '5', '10', '15', '20' ); + for my $k (@types) { + my @opts = ( "$k", "$text{$flowreports{$k}{NAMEIDX}}" ); + push(@items_type, \@opts); + } + + my @items_target_op = (); + my @target_ops = sort keys %sqloperators; + for my $k (@target_ops) { + my @opts = ( "$k", "$text{$sqloperators{$k}{DESCIDX}}" ); + push(@items_target_op, \@opts); + } + + my @tops = ( '5', '10', '25', '50' ); - #my $type = $types[0]; + my $is_log = '1'; + my $log = ''; my $type = 'protocol'; - my $max = $maxs[1]; - my $top = $tops[0]; - my $string = ''; + my $top = '5'; + my $is_target = 0; + my $target_type = 'source'; + my $target_op = '='; + my $target = ''; - my @logs = glob("${log}*"); + my @logs = (); + push @logs, sort { $b cmp $a } glob("${FlowLogFile}-*"); + my $selected_log = $logs[0]; print &ui_subheading("$icons{CREATE}{IMAGE}$text{'edit_flowstat_title_create'}"); print &ui_form_start("list_flowstat.cgi", "post"); - my @tds = ( "width=20% style=white-space:nowrap ", "width=80%" ); + my @tds = ( "width=20% style=white-space:nowrap", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; - $col = &ui_select("log", $log, \@logs); + my @opts = ( [ 0, "$text{'flowlog_all'}
" ], [ 1, "".&ui_select("log", $selected_log, \@logs, 5, 1)."
" ], [ 2, "$text{'flowlog_current'}" ] ); + $col = &ui_radio("is_log", $is_log, \@opts); print &ui_columns_row([ "$icons{LOG}{IMAGE}$text{'edit_flowstat_log'}", $col ], \@tds); - $col = &ui_select("type", $type, \@types); + $col = &ui_select("type", $type, \@items_type); print &ui_columns_row([ "$icons{OPTION}{IMAGE}$text{'edit_flowstat_type'}", $col ], \@tds); - $col = &ui_select("max", $max, \@maxs); - $col .= "$text{flowstat_max_help}"; - print &ui_columns_row([ "$icons{RATELIMIT}{IMAGE}$text{'edit_flowstat_max'}", $col ], \@tds); $col = &ui_select("top", $top, \@tops); print &ui_columns_row([ "$icons{FLOWSTAT}{IMAGE}$text{'edit_flowstat_top'}", $col ], \@tds); - $col = &ui_textbox("string", $string, 60, 0, 60); - print &ui_columns_row([ "$icons{TARGET}{IMAGE}$text{'edit_flowstat_string'}", $col ], \@tds); + + my @opts = ( [ 0, "$text{NO}
" ], [ 1, "$text{YES}" ] ); + $col = &ui_radio("is_target", $is_target ? 1 : 0, \@opts); + $col .= "  where  "; + $col .= &ui_select("target_type", $target_type, \@items_type); + $col .= " "; + $col .= &ui_select("target_op", $target_op, \@items_target_op); + $col .= " "; + $col .= &ui_textbox("target", $target, 60, 0, 60); + print &ui_columns_row([ "$icons{TARGET}{IMAGE}$text{'edit_flowstat_target'}", $col ], \@tds); + print &ui_columns_end(); print ""; diff --git a/src/turtlefirewall/edit_geoip.cgi b/src/turtlefirewall/edit_geoip.cgi index ad5de36..3563072 100644 --- a/src/turtlefirewall/edit_geoip.cgi +++ b/src/turtlefirewall/edit_geoip.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -19,7 +19,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_geoip_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my $geoip = $in{'geoip'}; my $newgeoip = $in{'newgeoip'}; @@ -32,8 +32,7 @@ my @zones = grep(!/FIREWALL/, $fw->GetZoneList()); &LoadCountryCodes($fw); my @items_countrycode = (); -my @countrycodes = $fw->GetCountryCodesList(); -for my $k (@countrycodes) { +for my $k ($fw->GetCountryCodesList()) { my %country = $fw->GetCountryCode($k); my @opts = ( "$k", "$k - $country{DESCRIPTION}" ); push(@items_countrycode, \@opts); diff --git a/src/turtlefirewall/edit_group.cgi b/src/turtlefirewall/edit_group.cgi index 740305c..6dbec5a 100644 --- a/src/turtlefirewall/edit_group.cgi +++ b/src/turtlefirewall/edit_group.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -21,7 +21,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_group_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my %g = $fw->GetGroup($group); my @selected_items = @{$g{ITEMS}}; diff --git a/src/turtlefirewall/edit_host.cgi b/src/turtlefirewall/edit_host.cgi index 8b3bef9..cd07886 100644 --- a/src/turtlefirewall/edit_host.cgi +++ b/src/turtlefirewall/edit_host.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -19,7 +19,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_host_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my $host = $in{'host'}; my %h = $fw->GetHost($host); diff --git a/src/turtlefirewall/edit_hostnameset.cgi b/src/turtlefirewall/edit_hostnameset.cgi index 33dca48..e441a5d 100644 --- a/src/turtlefirewall/edit_hostnameset.cgi +++ b/src/turtlefirewall/edit_hostnameset.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -21,7 +21,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_hostnameset_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my %h = $fw->GetHostNameSet($hostnameset); my $hostnames = $h{'HOSTNAMES'}; diff --git a/src/turtlefirewall/edit_ipset.cgi b/src/turtlefirewall/edit_ipset.cgi index 06d97c2..46a4984 100644 --- a/src/turtlefirewall/edit_ipset.cgi +++ b/src/turtlefirewall/edit_ipset.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -19,7 +19,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_ipset_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my $ipset = $in{'ipset'}; my $newipset = $in{'newipset'}; diff --git a/src/turtlefirewall/edit_masquerade.cgi b/src/turtlefirewall/edit_masquerade.cgi index 02c255c..f26a466 100644 --- a/src/turtlefirewall/edit_masquerade.cgi +++ b/src/turtlefirewall/edit_masquerade.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nMasq = $fw->GetMasqueradesCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_masq_title_create'}"; - $idx = ''; + $nMasq++; + $idx = $nMasq; + $newIdx = ''; $src = ''; $dst = ''; $service = ''; @@ -25,6 +29,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_masq_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %masq = $fw->GetMasquerade($idx); $src = $masq{'SRC'}; $dst = $masq{'DST'}; @@ -33,7 +38,10 @@ if( $new ) { $is_masquerade = $masq{'MASQUERADE'} ne 'NO'; $active = $masq{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_nat'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nMasq; $i++ ) { push @idxs, $i; } my @items_src = ('*'); push @items_src, grep(!/FIREWALL/, $fw->GetZoneList()); @@ -59,17 +67,15 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("src", $src, \@items_src); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'masq_src'}", $col ], \@tds); $col = &ui_select("dst", $dst, \@items_dst); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'masq_dst'}", $col ], \@tds); $col = &formService($service, $port, 1); print &ui_columns_row([ "$icons{SERVICE}{IMAGE}$text{'rule_service'}", $col ], \@tds); -my @opts = ( [ 0, "$text{NO}
" ], [ 1, $text{YES} ] ); +my @opts = ( [ 0, "$text{NO}
" ], [ 1, "$text{YES}" ] ); $col = &ui_radio("masquerade", $is_masquerade ? 1 : 0, \@opts); print &ui_columns_row([ "$icons{MASQUERADE}{IMAGE}$text{'masq_masquerade'}", $col ], \@tds); $col = &ui_checkbox("active", 1, undef, $active ? 1 : 0); @@ -88,4 +94,4 @@ print "
"; print &ui_form_end(); print "

"; -&ui_print_footer('list_nat.cgi','NAT list'); +&ui_print_footer("list_nat.cgi?table=masquerade&idx=$idx",'NAT list'); diff --git a/src/turtlefirewall/edit_nat.cgi b/src/turtlefirewall/edit_nat.cgi index 83fdb3b..0026d41 100644 --- a/src/turtlefirewall/edit_nat.cgi +++ b/src/turtlefirewall/edit_nat.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +$nNat = $fw->GetNatsCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_nat_title_create'}"; - $idx = ''; + $nNat++; + $idx = $nNat; + $newIdx = ''; $virtual = ''; $real = ''; $service = ''; @@ -25,6 +29,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_nat_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %nat = $fw->GetNat($idx); $virtual = $nat{'VIRTUAL'}; $real = $nat{'REAL'}; @@ -33,16 +38,19 @@ if( $new ) { $toport = $nat{'TOPORT'}; $active = $nat{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_nat'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nNat; $i++ ) { push @idxs, $i; } my @items_virtual = (); my @virtuals = (); push @virtuals, grep(!/FIREWALL/, $fw->GetZoneList()); push @virtuals, $fw->GetHostList(); -for my $k (@virtuals) { +for my $k (sort @virtuals) { my @opts = (); my %zone = $fw->GetZone($k); - if( $zone{IF} ne '' ) { + if( $zone{IF} ne '' ) { @opts = ( "$k", "$k ($zone{IF})" ); } else { @opts = ( "$k", "$k" ); @@ -59,10 +67,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("virtual", $virtual, \@items_virtual); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'virtual_host'}", $col ], \@tds); $col = &ui_select("real", $real, \@items_real); @@ -90,4 +96,4 @@ print ""; print &ui_form_end(); print "

"; -&ui_print_footer('list_nat.cgi','NAT list'); +&ui_print_footer("list_nat.cgi?table=nat&idx=$idx",'NAT list'); diff --git a/src/turtlefirewall/edit_net.cgi b/src/turtlefirewall/edit_net.cgi index ed5dd05..536fb78 100644 --- a/src/turtlefirewall/edit_net.cgi +++ b/src/turtlefirewall/edit_net.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -19,7 +19,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_net_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my $net = $in{'net'}; my $newnet = $in{'newnet'}; diff --git a/src/turtlefirewall/edit_options.cgi b/src/turtlefirewall/edit_options.cgi index cfe06f0..e5f7b09 100644 --- a/src/turtlefirewall/edit_options.cgi +++ b/src/turtlefirewall/edit_options.cgi @@ -3,14 +3,14 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; -&ui_print_header( "$icons{EDIT}{IMAGE}$text{'edit_options_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_options'}", $text{'title'}, "" ); &getOptionsList(); diff --git a/src/turtlefirewall/edit_ratelimit.cgi b/src/turtlefirewall/edit_ratelimit.cgi index 57f1680..51fb422 100644 --- a/src/turtlefirewall/edit_ratelimit.cgi +++ b/src/turtlefirewall/edit_ratelimit.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -21,7 +21,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_ratelimit_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my %r = $fw->GetRateLimit($ratelimit); my $rate = $r{'RATE'}; diff --git a/src/turtlefirewall/edit_redirect.cgi b/src/turtlefirewall/edit_redirect.cgi index 4d4bbd6..0b669c7 100644 --- a/src/turtlefirewall/edit_redirect.cgi +++ b/src/turtlefirewall/edit_redirect.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nRedirect = $fw->GetRedirectCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_redirect_title_create'}"; - $idx = ''; + $nRedirect++; + $idx = $nRedirect; + $newIdx = ''; $src = ''; $dst = ''; $service = ''; @@ -26,6 +30,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_redirect_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %redirect = $fw->GetRedirect($idx); $src = $redirect{'SRC'}; $dst = $redirect{'DST'}; @@ -35,7 +40,10 @@ if( $new ) { $is_redirect = $redirect{'REDIRECT'} ne 'NO'; $active = $redirect{'ACTIVE'} ne 'NO'; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_nat'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nRedirect; $i++ ) { push @idxs, $i; } my @items_src = (); push @items_src, grep(!/FIREWALL/, $fw->GetZoneList()); @@ -62,10 +70,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("src", $src, \@items_src); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'redirect_src'}", $col ], \@tds); $col = &ui_select("dst", $dst, \@items_dst); @@ -94,4 +100,4 @@ print ""; print &ui_form_end(); print "

"; -&ui_print_footer('list_nat.cgi','NAT list'); +&ui_print_footer("list_nat.cgi?table=redirect&idx=$idx",'NAT list'); diff --git a/src/turtlefirewall/edit_riskset.cgi b/src/turtlefirewall/edit_riskset.cgi index 6a410e4..5776db8 100644 --- a/src/turtlefirewall/edit_riskset.cgi +++ b/src/turtlefirewall/edit_riskset.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -21,7 +21,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_riskset_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my %r = $fw->GetRiskSet($riskset); my $risks = $r{'RISKS'}; diff --git a/src/turtlefirewall/edit_rule.cgi b/src/turtlefirewall/edit_rule.cgi index 46f0004..375097f 100644 --- a/src/turtlefirewall/edit_rule.cgi +++ b/src/turtlefirewall/edit_rule.cgi @@ -3,19 +3,23 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); +my $nRules = $fw->GetRulesCount(); + $new = $in{'new'}; if( $new ) { $heading = "$icons{CREATE}{IMAGE}$text{'edit_rule_title_create'}"; - $idx = ''; + $nRules++; + $idx = $nRules; + $newIdx = ''; $src = ''; $dst = ''; $service = ''; @@ -33,6 +37,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_rule_title_edit'}"; $idx = $in{'idx'}; + $newIdx = ''; %rule = $fw->GetRule($idx); $src = $rule{'SRC'}; $dst = $rule{'DST'}; @@ -49,7 +54,10 @@ if( $new ) { $log = $rule{'LOG'} eq 'YES'; $description = $rule{'DESCRIPTION'}; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_rules'}", $text{'title'}, "" ); + +my @idxs = (); +for( my $i=1; $i<=$nRules; $i++ ) { push @idxs, $i; } my @selected_src = split(/,/, $src); my @selected_dst = split(/,/, $dst); @@ -87,10 +95,8 @@ print &ui_hidden("idx", $idx); my @tds = ( "width=20%", "width=80%" ); print &ui_columns_start(undef, 100, 0, \@tds); my $col = ''; -if( !$new ) { - $col = "$idx"; - print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); -} +$col = &ui_select("newIdx", $idx, \@idxs); +print &ui_columns_row([ "$icons{ID}{IMAGE}ID", $col ], \@tds); $col = &ui_select("src", \@selected_src, \@items, 5, 1); print &ui_columns_row([ "$icons{ZONE}{IMAGE}$text{'rule_src'}", $col ], \@tds); $col = &ui_select("dst", \@selected_dst, \@items, 5, 1); diff --git a/src/turtlefirewall/edit_time.cgi b/src/turtlefirewall/edit_time.cgi index e24aa8a..96702f1 100644 --- a/src/turtlefirewall/edit_time.cgi +++ b/src/turtlefirewall/edit_time.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -21,7 +21,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_time_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my @aWeekdays = ('Mon','Tue','Wed','Thu','Fri','Sat','Sun'); diff --git a/src/turtlefirewall/edit_timegroup.cgi b/src/turtlefirewall/edit_timegroup.cgi index 8f59935..1bac97f 100644 --- a/src/turtlefirewall/edit_timegroup.cgi +++ b/src/turtlefirewall/edit_timegroup.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $new = $in{'new'}; @@ -21,7 +21,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_timegroup_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my %g = $fw->GetTimeGroup($timegroup); my @selected_items = @{$g{ITEMS}}; diff --git a/src/turtlefirewall/edit_zone.cgi b/src/turtlefirewall/edit_zone.cgi index 0ec1cd5..35447e0 100644 --- a/src/turtlefirewall/edit_zone.cgi +++ b/src/turtlefirewall/edit_zone.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); if( $in{'zone'} eq 'FIREWALL' ) { @@ -23,7 +23,7 @@ if( $new ) { } else { $heading = "$icons{EDIT}{IMAGE}$text{'edit_zone_title_edit'}"; } -&ui_print_header( $heading, $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); my %z = $fw->GetZone($in{'zone'}); my $if = $z{'IF'}; diff --git a/src/turtlefirewall/images/hostnameset.png b/src/turtlefirewall/images/hostnameset.png index ed53304..c644686 100644 Binary files a/src/turtlefirewall/images/hostnameset.png and b/src/turtlefirewall/images/hostnameset.png differ diff --git a/src/turtlefirewall/images/icon.gif b/src/turtlefirewall/images/icon.gif index b7d7d49..9ff2a64 100644 Binary files a/src/turtlefirewall/images/icon.gif and b/src/turtlefirewall/images/icon.gif differ diff --git a/src/turtlefirewall/images/shield.png b/src/turtlefirewall/images/shield.png deleted file mode 100644 index 8260d4e..0000000 Binary files a/src/turtlefirewall/images/shield.png and /dev/null differ diff --git a/src/turtlefirewall/index.cgi b/src/turtlefirewall/index.cgi index 08cd2de..0742df9 100644 --- a/src/turtlefirewall/index.cgi +++ b/src/turtlefirewall/index.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); -&ui_print_header( "$icons{SHIELD}{IMAGE} v ".$fw->Version(), $text{'title'}, "", undef, 1, 1, 0, +&ui_print_header( "$icons{ICON}{IMAGE} v ".$fw->Version(), $text{'title'}, "", undef, 1, 1, 0, &help_search_link("iptables", "man", "doc")); my @olinks = ('list_items.cgi', @@ -21,12 +21,12 @@ my @olinks = ('list_items.cgi', 'list_countrycodes.cgi', 'edit_options.cgi', 'backup.cgi'); -my @otitles = ($text{'index_icon_firewall_items'}, - $text{'index_icon_firewall_services'}, - $text{'index_icon_firewall_ndpiprotocols'}, - $text{'index_icon_firewall_ndpirisks'}, - $text{'index_icon_firewall_countrycodes'}, - $text{'index_icon_edit_options'}, +my @otitles = ($text{'index_icon_items'}, + $text{'index_icon_services'}, + $text{'index_icon_ndpiprotocols'}, + $text{'index_icon_ndpirisks'}, + $text{'index_icon_countrycodes'}, + $text{'index_icon_options'}, $text{'index_icon_backup'}); my @oicons = ('images/items.png', 'images/services.png', @@ -42,10 +42,10 @@ my @rlinks = ('list_rules.cgi', 'list_nat.cgi', 'list_manglerules.cgi', 'list_rawrules.cgi'); -my @rtitles = ($text{'index_icon_firewall_rules'}, - $text{'index_icon_firewall_nat'}, - $text{'index_icon_firewall_manglerules'}, - $text{'index_icon_firewall_rawrules'}); +my @rtitles = ($text{'index_icon_rules'}, + $text{'index_icon_nat'}, + $text{'index_icon_manglerules'}, + $text{'index_icon_rawrules'}); my @ricons = ('images/rules.png', 'images/nats.png', 'images/manglerules.png', @@ -105,7 +105,7 @@ print ''; print &ui_form_end(); if( $in{showiptfilter} ne '' ) { - print "
+ print "
FILTER
"; print "
";
@@ -116,7 +116,7 @@ if( $in{showiptfilter} ne '' ) {
 }
 
 if( $in{showiptnat} ne '' ) {
-	print "
+ print "
NAT
"; print "
";
@@ -127,7 +127,7 @@ if( $in{showiptnat} ne '' ) {
 }
 
 if( $in{showiptmangle} ne '' ) {
-	print "
+ print "
MANGLE
"; print "
";
@@ -138,7 +138,7 @@ if( $in{showiptmangle} ne '' ) {
 }
 
 if( $in{showiptraw} ne '' ) {
-	print "
+ print "
RAW
"; print "
";
@@ -149,7 +149,7 @@ if( $in{showiptraw} ne '' ) {
 }
 
 if( $in{showconntrack} ne '' ) {
-	print "
+ print "
CONNTRACK
"; print "
";
@@ -159,7 +159,7 @@ if( $in{showconntrack} ne '' ) {
 }
 
 if( $in{flushconntrack} ne '' ) {
-	print "
+ print "
CONNTRACK
"; print "
";
diff --git a/src/turtlefirewall/install_check.pl b/src/turtlefirewall/install_check.pl
index fee82ae..03d7923 100644
--- a/src/turtlefirewall/install_check.pl
+++ b/src/turtlefirewall/install_check.pl
@@ -1,6 +1,6 @@
 # install_check.pl
 
-do 'turtlefirewall-lib.pl';
+require './turtlefirewall-lib.pl';
 
 # is_installed(mode)
 # For mode 1, returns 2 if the server is installed and configured for use by
diff --git a/src/turtlefirewall/lang/de b/src/turtlefirewall/lang/de
index 9cf538e..711f986 100644
--- a/src/turtlefirewall/lang/de
+++ b/src/turtlefirewall/lang/de
@@ -32,6 +32,7 @@ time=Time
 timeitems=Weekdays
 name=Name
 id=ID
+rule=Filter
 nat=NAT
 masquerade=Masquerade
 connmark_preroute=Connmark Preroute
@@ -82,6 +83,7 @@ items=Items
 reference=Ref
 references=References
 file=File
+flag=DPI
 category=Category
 index=Turtle Firewall index
 index_start=Start
@@ -93,22 +95,21 @@ index_showiptmangle=Show MANGLE Table
 index_showiptraw=Show RAW Table
 index_showconntrack=Show CONNTRACK Table
 index_flushconntrack=Flush CONNTRACK Table
-index_icon_firewall_items=Objekte
-index_icon_firewall_rules=Regeln
-index_icon_firewall_nat=NAT und Masquerading
-index_icon_firewall_manglerules=Mangle Rules
-index_icon_firewall_rawrules=Raw Rules
-index_icon_firewall_services=Dienste
-index_icon_firewall_countrycodes=Country Codes
-index_icon_firewall_ndpiprotocols=nDPI Services
-index_icon_firewall_ndpirisks=nDPI Risks
-index_icon_edit_options=Optionen
-index_icon_log=Log
+index_icon_items=Objekte
+index_icon_rules=Regeln
+index_icon_nat=NAT und Masquerading
+index_icon_manglerules=Mangle Rules
+index_icon_rawrules=Raw Rules
+index_icon_services=Dienste
+index_icon_countrycodes=Country Codes
+index_icon_ndpiprotocols=nDPI Services
+index_icon_ndpirisks=nDPI Risks
+index_icon_options=Optionen
+index_icon_log=Action Log
 index_icon_flowlog=Flow Log
 index_icon_flowstat=Flow Statistics
 index_icon_backup=Backup
 list_itemreferences_title=Item References
-list_items_title=Firewall Objekte
 list_items_create_zone=neue Zone erstellen
 list_items_create_geoip=create new geoip
 list_items_create_net=neues Netz erstellen
@@ -145,14 +146,12 @@ edit_addresslist_title_create=Create new AddressList
 edit_addresslist_title_edit=Edit AddressList
 edit_ipset_title_create=Create new IPSet
 edit_ipset_title_edit=Edit IPSet
-list_nat_title=NAT und Masquerading
 list_nat_create_nat=neues NAT erstellen
 list_nat_create_masq=neues Masquerading erstellen
 edit_nat_title_create=NAT erstellen
 edit_nat_title_edit=NAT bearbeiten
 edit_masq_title_create=Masquerading erstellen
 edit_masq_title_edit=Masquerading bearbeiten
-list_rules_title=Firewall-Regeln
 list_rules_create_rule=neue Regel erstellen
 list_connmarkpreroutes_create_rule=create new Connmark Preroute
 list_connmarks_create_rule=create new Connmark
@@ -160,7 +159,6 @@ list_conntrackpreroutes_create_rule=create new Conntrack Preroute
 list_conntracks_create_rule=create new Conntrack
 edit_rule_title_create=Regel erstellen
 edit_rule_title_edit=Regel bearbeiten
-list_manglerules_title=Mangle Rules
 edit_conntrackpreroute_title_create=Create new Conntrack Preroute
 edit_conntrack_title_create=Create new Conntrack
 edit_connmarkpreroute_title_create=Create new Connmark Preroute
@@ -169,11 +167,7 @@ edit_conntrackpreroute_title_edit=Edit Conntrack Preroute
 edit_conntrack_title_edit=Edit Conntrack
 edit_connmarkpreroute_title_edit=Edit Connmark Preroute
 edit_connmark_title_edit=Edit Connmark
-list_rawrules_title=Raw Rules
-list_services_title=Dienste
 list_countrycodes_title=Country Codes
-list_ndpiprotocols_title=nDPI Services
-list_ndpirisks_title=nDPI Risks
 redirect_src=Quelle
 redirect_dst=Ziel
 redirect_service=Dienst
@@ -190,26 +184,38 @@ host_help=Note: not required for mac only host
 zone_help=Note: range eg. ppp0-ppp10 or ppp+
 port_help=Note: range eg. 6000:6010
 log_help=Note: target accept logs flow, target drop/reject logs action
-flowstat_max_help=Note: analysing all flows is resource intensive
 preroute_help=Note: zone as destination invalid during prerouting
 log_update=Aktualisieren
 log_title=Action Log
 flowlog_title=Flow Log
+flowlog_current=Current Flow Log
+flowlog_all=All Historical Flow Logs
 report_flowstat_title=Flow Statistics Report
-flowstat_type_source=Top Sources
-flowstat_type_destination=Top Destinations
-flowstat_type_dport=Top Destination Ports
-flowstat_type_protocol=Top Protocols
-flowstat_type_hostname=Top Hostnames
-flowstat_type_risk=Top Risks
+flowstat_type_source_desc=Top Sources
+flowstat_type_destination_desc=Top Destinations
+flowstat_type_dport_desc=Top Ports
+flowstat_type_protocol_desc=Top Protocols
+flowstat_type_hostname_desc=Top Hostnames
+flowstat_type_risk_desc=Top Risks
+flowstat_type_source_name=Source
+flowstat_type_destination_name=Destination
+flowstat_type_dport_name=Port
+flowstat_type_protocol_name=Protocol
+flowstat_type_hostname_name=Hostname
+flowstat_type_risk_name=Risk
 flowstat_percent=Percentage
 flowstat_traffic=Traffic
+sql_operator_equal_desc=is equal to
+sql_operator_like_desc=contains
 edit_flowstat_title_create=Create Flow Statistics Report
 edit_flowstat_log=Log
 edit_flowstat_type=Type
 edit_flowstat_max=Max Flows
-edit_flowstat_top=Display the Top
-edit_flowstat_string=Only Flows that Contain
+edit_flowstat_top=Top
+edit_flowstat_target=Target
+item_ip_blacklist_desc=IP Address
+item_domain_blacklist_desc=DNS Domain Name
+item_sha1_blacklist_desc=SSL Certificate Fingerprint
 edit_options_title=Edit Options
 options_rp_filter_name=rp_filter
 options_rp_filter_desc=Route überprüfen: discarding packets received on an interface which does not expect to those handle traffic from the given source address. Wenn Sie VPN verwenden, müssen Sie diese Option deaktivieren.
@@ -233,12 +239,12 @@ options_drop_ip_blacklist_name=drop_ip_blacklist
 options_drop_ip_blacklist_desc=Drop IP blacklist ( globally )
 options_drop_domain_blacklist_name=drop_domain_blacklist
 options_drop_domain_blacklist_desc=Drop domain blacklist ( globally )
-options_drop_ja3_blacklist_name=drop_ja3_blacklist
-options_drop_ja3_blacklist_desc=Drop ja3 blacklist - SSL handshake fingerprint ( globally )
 options_drop_sha1_blacklist_name=drop_sha1_blacklist
 options_drop_sha1_blacklist_desc=Drop sha1 blacklist - SSL certificate fingerprint ( globally )
 options_nf_conntrack_max_name=nf_conntrack_max
 options_nf_conntrack_max_desc=Maximum number of sessions in conntrack table.
+options_clamp_mss_to_pmtu_name=clamp_mss_to_pmtu
+options_clamp_mss_to_pmtu_desc=Automatically set MSS for TCP SYN packets outgoing on any ppp interface.
 options_log_limit_name=log_limit
 options_log_limit_desc=Maximum average matching rate: number of logs per hour.
 options_log_limit_burst_name=log_limit_burst
@@ -421,9 +427,8 @@ save_rule_error1=Invalid port (1-65535) or port range (1-65535:1-65535).
 save_rule_error2=port is valid only for tcp and udp services.
 save_rule_error3=source and destination cannot both be "FIREWALL".
 save_rule_error4=source and destination are required.
-save_rule_error5=All nDPI Services, Hostname and Risk, only valid for DROP or REJECT target.
-save_rule_error6=Rate only valid for DROP target.
-save_rule_error7=Log not valid for Rate Limit.
+save_rule_error5=Rate only valid for DROP target.
+save_rule_error6=Log not valid for Rate Limit.
 
 save_connmark_error_title1=Fail to delete Connmark Rule
 save_connmark_error_title2=Fail to create new Connmark Rule
@@ -448,3 +453,5 @@ save_conntrack_error9=irc helper only supports tcp.
 save_conntrack_error10=sane helper only supports tcp.
 save_conntrack_error11=snmp helper only supports udp.
 save_conntrack_error12=netbios-ns helper only supports udp.
+
+list_flowstat_error1=target is required.
diff --git a/src/turtlefirewall/lang/en b/src/turtlefirewall/lang/en
index 732a6c7..de2385f 100644
--- a/src/turtlefirewall/lang/en
+++ b/src/turtlefirewall/lang/en
@@ -32,6 +32,7 @@ time=Time
 timeitems=Weekdays
 name=Name
 id=ID
+rule=Filter
 nat=NAT
 masquerade=Masquerade
 connmark_preroute=Connmark Preroute
@@ -82,6 +83,7 @@ items=Items
 reference=Ref
 references=References
 file=File
+flag=DPI
 category=Category
 index=Turtle Firewall index
 index_start=Start
@@ -93,22 +95,21 @@ index_showiptmangle=Show MANGLE Table
 index_showiptraw=Show RAW Table
 index_showconntrack=Show CONNTRACK Table
 index_flushconntrack=Flush CONNTRACK Table
-index_icon_firewall_items=Items
-index_icon_firewall_rules=Filter Rules
-index_icon_firewall_nat=NAT Rules
-index_icon_firewall_manglerules=Mangle Rules
-index_icon_firewall_rawrules=Raw Rules
-index_icon_firewall_services=Port Services
-index_icon_firewall_countrycodes=Country Codes
-index_icon_firewall_ndpiprotocols=nDPI Services
-index_icon_firewall_ndpirisks=nDPI Risks
-index_icon_edit_options=Options
+index_icon_items=Items
+index_icon_rules=Filter Rules
+index_icon_nat=NAT Rules
+index_icon_manglerules=Mangle Rules
+index_icon_rawrules=Raw Rules
+index_icon_services=Port Services
+index_icon_countrycodes=Country Codes
+index_icon_ndpiprotocols=nDPI Services
+index_icon_ndpirisks=nDPI Risks
+index_icon_options=Options
 index_icon_log=Action Log
 index_icon_flowlog=Flow Log
 index_icon_flowstat=Flow Statistics
 index_icon_backup=Backup
 list_itemreferences_title=Item References
-list_items_title=Items
 list_items_create_zone=create new zone
 list_items_create_geoip=create new geoip
 list_items_create_net=create new net
@@ -145,14 +146,12 @@ edit_addresslist_title_create=Create new AddressList
 edit_addresslist_title_edit=Edit AddressList
 edit_ipset_title_create=Create new IPSet
 edit_ipset_title_edit=Edit IPSet
-list_nat_title=NAT Rules
 list_nat_create_nat=create new NAT
 list_nat_create_masq=create new Masquerade
 edit_nat_title_create=Create new NAT
 edit_nat_title_edit=Edit NAT
 edit_masq_title_create=Create new Masquerade
 edit_masq_title_edit=Edit Masquerade
-list_rules_title=Filter Rules
 list_rules_create_rule=create new Rule
 list_connmarkpreroutes_create_rule=create new Connmark Preroute
 list_connmarks_create_rule=create new Connmark
@@ -160,7 +159,6 @@ list_conntrackpreroutes_create_rule=create new Conntrack Preroute
 list_conntracks_create_rule=create new Conntrack
 edit_rule_title_create=Create new Rule
 edit_rule_title_edit=Edit Rule
-list_manglerules_title=Mangle Rules
 edit_conntrackpreroute_title_create=Create new Conntrack Preroute
 edit_conntrack_title_create=Create new Conntrack
 edit_connmarkpreroute_title_create=Create new Connmark Preroute
@@ -169,11 +167,6 @@ edit_conntrackpreroute_title_edit=Edit Conntrack Preroute
 edit_conntrack_title_edit=Edit Conntrack
 edit_connmarkpreroute_title_edit=Edit Connmark Preroute
 edit_connmark_title_edit=Edit Connmark
-list_rawrules_title=Raw Rules
-list_services_title=Port Services
-list_countrycodes_title=Country Codes
-list_ndpiprotocols_title=nDPI Services
-list_ndpirisks_title=nDPI Risks
 redirect_src=Source
 redirect_dst=Destination
 redirect_service=Port Service
@@ -190,26 +183,38 @@ host_help=Note: not required for mac only host
 zone_help=Note: range eg. ppp0-ppp10 or ppp+
 port_help=Note: range eg. 6000:6010
 log_help=Note: target accept logs flow, target drop/reject logs action
-flowstat_max_help=Note: analysing all flows is resource intensive
 preroute_help=Note: zone as destination invalid during prerouting
 log_update=Refresh
 log_title=Action Log
 flowlog_title=Flow Log
+flowlog_current=Current Flow Log
+flowlog_all=All Historical Flow Logs
 report_flowstat_title=Flow Statistics Report
-flowstat_type_source=Top Sources
-flowstat_type_destination=Top Destinations
-flowstat_type_dport=Top Destination Ports
-flowstat_type_protocol=Top Protocols
-flowstat_type_hostname=Top Hostnames
-flowstat_type_risk=Top Risks
+flowstat_type_source_desc=Top Sources
+flowstat_type_destination_desc=Top Destinations
+flowstat_type_dport_desc=Top Ports
+flowstat_type_protocol_desc=Top Protocols
+flowstat_type_hostname_desc=Top Hostnames
+flowstat_type_risk_desc=Top Risks
+flowstat_type_source_name=Source
+flowstat_type_destination_name=Destination
+flowstat_type_dport_name=Port
+flowstat_type_protocol_name=Protocol
+flowstat_type_hostname_name=Hostname
+flowstat_type_risk_name=Risk
 flowstat_percent=Percentage
 flowstat_traffic=Traffic
+sql_operator_equal_desc=is equal to
+sql_operator_like_desc=contains
 edit_flowstat_title_create=Create Flow Statistics Report
 edit_flowstat_log=Log
 edit_flowstat_type=Type
 edit_flowstat_max=Max Flows
-edit_flowstat_top=Display the Top
-edit_flowstat_string=Only Flows that Contain
+edit_flowstat_top=Top
+edit_flowstat_target=Target
+item_ip_blacklist_desc=IP Address
+item_domain_blacklist_desc=DNS Domain Name
+item_sha1_blacklist_desc=SSL Certificate Fingerprint
 edit_options_title=Edit Options
 options_rp_filter_name=rp_filter
 options_rp_filter_desc=Route verification: discarding packets received on an interface which does not expect to handle traffic from the given source address. If you are using VPN you need to disable this option.
@@ -233,12 +238,12 @@ options_drop_ip_blacklist_name=drop_ip_blacklist
 options_drop_ip_blacklist_desc=Drop IP blacklist ( globally )
 options_drop_domain_blacklist_name=drop_domain_blacklist
 options_drop_domain_blacklist_desc=Drop domain blacklist ( globally )
-options_drop_ja3_blacklist_name=drop_ja3_blacklist
-options_drop_ja3_blacklist_desc=Drop ja3 blacklist - SSL handshake fingerprint ( globally )
 options_drop_sha1_blacklist_name=drop_sha1_blacklist
 options_drop_sha1_blacklist_desc=Drop sha1 blacklist - SSL certificate fingerprint ( globally )
 options_nf_conntrack_max_name=nf_conntrack_max
 options_nf_conntrack_max_desc=Maximum number of sessions in conntrack table.
+options_clamp_mss_to_pmtu_name=clamp_mss_to_pmtu
+options_clamp_mss_to_pmtu_desc=Automatically set MSS for TCP SYN packets outgoing on any ppp interface.
 options_log_limit_name=log_limit
 options_log_limit_desc=Maximum average matching rate: number of logs per hour.
 options_log_limit_burst_name=log_limit_burst
@@ -421,9 +426,8 @@ save_rule_error1=Invalid port (1-65535) or port range (1-65535:1-65535).
 save_rule_error2=port is valid only for tcp and udp services.
 save_rule_error3=source and destination cannot both be "FIREWALL".
 save_rule_error4=source and destination are required.
-save_rule_error5=All nDPI Services, Hostname and Risk, only valid for DROP or REJECT target.
-save_rule_error6=Rate only valid for DROP target.
-save_rule_error7=Log not valid for Rate Limit.
+save_rule_error5=Rate only valid for DROP target.
+save_rule_error6=Log not valid for Rate Limit.
 
 save_connmark_error_title1=Fail to delete Connmark Rule
 save_connmark_error_title2=Fail to create new Connmark Rule
@@ -448,3 +452,5 @@ save_conntrack_error9=irc helper only supports tcp.
 save_conntrack_error10=sane helper only supports tcp.
 save_conntrack_error11=snmp helper only supports udp.
 save_conntrack_error12=netbios-ns helper only supports udp.
+
+list_flowstat_error1=target is required.
diff --git a/src/turtlefirewall/lang/fr b/src/turtlefirewall/lang/fr
index 5284e63..91dc6dd 100644
--- a/src/turtlefirewall/lang/fr
+++ b/src/turtlefirewall/lang/fr
@@ -32,6 +32,7 @@ time=Time
 timeitems=Weekdays
 name=Nom
 id=ID
+rule=Filter
 nat=NAT
 masquerade=Masquerade
 connmark_preroute=Connmark Preroute
@@ -82,6 +83,7 @@ items=Items
 reference=Ref
 references=References
 file=File
+flag=DPI
 category=Category
 index=Turtle Firewall index
 index_start=Start
@@ -93,22 +95,21 @@ index_showiptmangle=Show MANGLE Table
 index_showiptraw=Show RAW Table
 index_showconntrack=Show CONNTRACK Table
 index_flushconntrack=Flush CONNTRACK Table
-index_icon_firewall_items=Eléments
-index_icon_firewall_rules=Règles
-index_icon_firewall_nat=NAT et Masquerade
-index_icon_firewall_manglerules=Mangle Rules
-index_icon_firewall_rawrules=Raw Rules
-index_icon_firewall_services=Services
-index_icon_firewall_countrycodes=Country Codes
-index_icon_firewall_ndpiprotocols=nDPI Services
-index_icon_firewall_ndpirisks=nDPI Risks
-index_icon_edit_options=Options
-index_icon_log=Log
+index_icon_items=Eléments
+index_icon_rules=Règles
+index_icon_nat=NAT et Masquerade
+index_icon_manglerules=Mangle Rules
+index_icon_rawrules=Raw Rules
+index_icon_services=Services
+index_icon_countrycodes=Country Codes
+index_icon_ndpiprotocols=nDPI Services
+index_icon_ndpirisks=nDPI Risks
+index_icon_options=Options
+index_icon_log=Action Log
 index_icon_flowlog=Flow Log
 index_icon_flowstat=Flow Statistics
 index_icon_backup=Backup
 list_itemreferences_title=Item References
-list_items_title=Eléments du Firewall
 list_items_create_zone=créer une nouvelle zone
 list_items_create_geoip=create new geoip
 list_items_create_net=créer un nouveau réseau
@@ -145,14 +146,12 @@ edit_addresslist_title_create=Create new AddressList
 edit_addresslist_title_edit=Edit AddressList
 edit_ipset_title_create=Create new IPSet
 edit_ipset_title_edit=Edit IPSet
-list_nat_title=NAT et Masquerade
 list_nat_create_nat=créer un nouveau NAT
 list_nat_create_masq=créer un nouveau Masquerade
 edit_nat_title_create=Créer NAT
 edit_nat_title_edit=Editer NAT
 edit_masq_title_create=Créer Masquerade
 edit_masq_title_edit=Editer Masquerade
-list_rules_title=Règles du Firewall
 list_rules_create_rule=créer une nouvelle règle
 list_connmarkpreroutes_create_rule=create new Connmark Preroute
 list_connmarks_create_rule=create new Connmark
@@ -160,7 +159,6 @@ list_conntrackpreroutes_create_rule=create new Conntrack Preroute
 list_conntracks_create_rule=create new Conntrack
 edit_rule_title_create=Créer la règle
 edit_rule_title_edit=Editer la règle
-list_manglerules_title=Mangle Rules
 edit_conntrackpreroute_title_create=Create new Conntrack Preroute
 edit_conntrack_title_create=Create new Conntrack
 edit_connmarkpreroute_title_create=Create new Connmark Preroute
@@ -169,11 +167,7 @@ edit_conntrackpreroute_title_edit=Edit Conntrack Preroute
 edit_conntrack_title_edit=Edit Conntrack
 edit_connmarkpreroute_title_edit=Edit Connmark Preroute
 edit_connmark_title_edit=Edit Connmark
-list_rawrules_title=Raw Rules
-list_services_title=Services
 list_countrycodes_title=Country Codes
-list_ndpiprotocols_title=nDPI Services
-list_ndpirisks_title=nDPI Risks
 redirect_src=Source
 redirect_dst=Destination
 redirect_service=Port Service
@@ -190,26 +184,38 @@ host_help=Note: not required for mac only host
 zone_help=Note: range eg. ppp0-ppp10 or ppp+
 port_help=Note: range eg. 6000:6010
 log_help=Note: target accept logs flow, target drop/reject logs action
-flowstat_max_help=Note: analysing all flows is resource intensive
 preroute_help=Note: zone as destination invalid during prerouting
 log_update=Refresh
 log_title=Action Log
 flowlog_title=Flow Log
+flowlog_current=Current Flow Log
+flowlog_all=All Historical Flow Logs
 report_flowstat_title=Flow Statistics Report
-flowstat_type_source=Top Sources
-flowstat_type_destination=Top Destinations
-flowstat_type_dport=Top Destination Ports
-flowstat_type_protocol=Top Protocols
-flowstat_type_hostname=Top Hostnames
-flowstat_type_risk=Top Risks
+flowstat_type_source_desc=Top Sources
+flowstat_type_destination_desc=Top Destinations
+flowstat_type_dport_desc=Top Ports
+flowstat_type_protocol_desc=Top Protocols
+flowstat_type_hostname_desc=Top Hostnames
+flowstat_type_risk_desc=Top Risks
+flowstat_type_source_name=Source
+flowstat_type_destination_name=Destination
+flowstat_type_dport_name=Port
+flowstat_type_protocol_name=Protocol
+flowstat_type_hostname_name=Hostname
+flowstat_type_risk_name=Risk
 flowstat_percent=Percentage
 flowstat_traffic=Traffic
+sql_operator_equal_desc=is equal to
+sql_operator_like_desc=contains
 edit_flowstat_title_create=Create Flow Statistics Report
 edit_flowstat_log=Log
 edit_flowstat_type=Type
 edit_flowstat_max=Max Flows
-edit_flowstat_top=Display the Top
-edit_flowstat_string=Only Flows that Contain
+edit_flowstat_top=Top
+edit_flowstat_target=Target
+item_ip_blacklist_desc=IP Address
+item_domain_blacklist_desc=DNS Domain Name
+item_sha1_blacklist_desc=SSL Certificate Fingerprint
 edit_options_title=Edit Options
 options_rp_filter_name=rp_filter
 options_rp_filter_desc=Route verification: discarding packets received on an interface which does not expect to handle traffic from the given source address. If you are using VPN you need to disable this option.
@@ -233,12 +239,12 @@ options_drop_ip_blacklist_name=drop_ip_blacklist
 options_drop_ip_blacklist_desc=Drop IP blacklist ( globally )
 options_drop_domain_blacklist_name=drop_domain_blacklist
 options_drop_domain_blacklist_desc=Drop domain blacklist ( globally )
-options_drop_ja3_blacklist_name=drop_ja3_blacklist
-options_drop_ja3_blacklist_desc=Drop ja3 blacklist - SSL handshake fingerprint ( globally )
 options_drop_sha1_blacklist_name=drop_sha1_blacklist
 options_drop_sha1_blacklist_desc=Drop sha1 blacklist - SSL certificate fingerprint ( globally )
 options_nf_conntrack_max_name=nf_conntrack_max
 options_nf_conntrack_max_desc=Maximum number of sessions in conntrack table.
+options_clamp_mss_to_pmtu_name=clamp_mss_to_pmtu
+options_clamp_mss_to_pmtu_desc=Automatically set MSS for TCP SYN packets outgoing on any ppp interface.
 options_log_limit_name=log_limit
 options_log_limit_desc=Maximum average matching rate: number of logs per hour.
 options_log_limit_burst_name=log_limit_burst
@@ -421,9 +427,8 @@ save_rule_error1=Invalid port (1-65535) or port range (1-65535:1-65535).
 save_rule_error2=port is valid only for tcp and udp services.
 save_rule_error3=source and destination cannot both be "FIREWALL".
 save_rule_error4=source and destination are required.
-save_rule_error5=All nDPI Services, Hostname and Risk, only valid for DROP or REJECT target.
-save_rule_error6=Rate only valid for DROP target.
-save_rule_error7=Log not valid for Rate Limit.
+save_rule_error5=Rate only valid for DROP target.
+save_rule_error6=Log not valid for Rate Limit.
 
 save_connmark_error_title1=Fail to delete Connmark Rule
 save_connmark_error_title2=Fail to create new Connmark Rule
@@ -448,3 +453,5 @@ save_conntrack_error9=irc helper only supports tcp.
 save_conntrack_error10=sane helper only supports tcp.
 save_conntrack_error11=snmp helper only supports udp.
 save_conntrack_error12=netbios-ns helper only supports udp.
+
+list_flowstat_error1=target is required.
diff --git a/src/turtlefirewall/lang/it b/src/turtlefirewall/lang/it
index 9e7c5c4..aeb04ae 100644
--- a/src/turtlefirewall/lang/it
+++ b/src/turtlefirewall/lang/it
@@ -32,6 +32,7 @@ time=Time
 timeitems=Weekdays
 name=Nome
 id=ID
+rule=Filter
 nat=NAT
 masquerade=Mascheramento
 connmark_preroute=Connmark Preroute
@@ -82,6 +83,7 @@ items=Items
 reference=Ref
 references=References
 file=File
+flag=DPI
 category=Category
 index=Turtle Firewall index
 index_start=Attiva Firewall
@@ -93,22 +95,21 @@ index_showiptmangle=Show MANGLE Table
 index_showiptraw=Show RAW Table
 index_showconntrack=Show CONNTRACK Table
 index_flushconntrack=Flush CONNTRACK Table
-index_icon_firewall_items=Elementi
-index_icon_firewall_rules=Regole
-index_icon_firewall_nat=NAT, Mascheramento e Redirezione
-index_icon_firewall_manglerules=Mangle Rules
-index_icon_firewall_rawrules=Raw Rules
-index_icon_firewall_services=Servizi
-index_icon_firewall_countrycodes=Country Codes
-index_icon_firewall_ndpiprotocols=nDPI Services
-index_icon_firewall_ndpirisks=nDPI Risks
-index_icon_edit_options=Opzioni
-index_icon_log=Log
+index_icon_items=Elementi
+index_icon_rules=Regole
+index_icon_nat=NAT, Mascheramento e Redirezione
+index_icon_manglerules=Mangle Rules
+index_icon_rawrules=Raw Rules
+index_icon_services=Servizi
+index_icon_countrycodes=Country Codes
+index_icon_ndpiprotocols=nDPI Services
+index_icon_ndpirisks=nDPI Risks
+index_icon_options=Opzioni
+index_icon_log=Action Log
 index_icon_flowlog=Flow Log
 index_icon_flowstat=Flow Statistics
 index_icon_backup=Backup Configurazione
 list_itemreferences_title=Item References
-list_items_title=Elementi del firewall
 list_items_create_zone=crea una nuova zona
 list_items_create_geoip=create new geoip
 list_items_create_net=crea una nuova rete
@@ -145,14 +146,12 @@ edit_addresslist_title_create=Create new AddressList
 edit_addresslist_title_edit=Edit AddressList
 edit_ipset_title_create=Create new IPSet
 edit_ipset_title_edit=Edit IPSet
-list_nat_title=NAT, Mascheramento e Redirezione
 list_nat_create_nat=crea una nuova regola NAT
 list_nat_create_masq=crea un nuovo mascheramento
 edit_nat_title_create=Crea NAT
 edit_nat_title_edit=Modifica NAT
 edit_masq_title_create=Crea nuovo Mascheramento
 edit_masq_title_edit=Modifica Mascheramento
-list_rules_title=Regole del Firewall
 list_rules_create_rule=crea una nuova regola
 list_connmarkpreroutes_create_rule=create new Connmark Preroute
 list_connmarks_create_rule=create new Connmark
@@ -160,7 +159,6 @@ list_conntrackpreroutes_create_rule=create new Conntrack Preroute
 list_conntracks_create_rule=create new Conntrack
 edit_rule_title_create=Crea una regola
 edit_rule_title_edit=Modifica una regola
-list_manglerules_title=Mangle Rules
 edit_conntrackpreroute_title_create=Create new Conntrack Preroute
 edit_conntrack_title_create=Create new Conntrack
 edit_connmarkpreroute_title_create=Create new Connmark Preroute
@@ -169,11 +167,7 @@ edit_conntrackpreroute_title_edit=Edit Conntrack Preroute
 edit_conntrack_title_edit=Edit Conntrack
 edit_connmarkpreroute_title_edit=Edit Connmark Preroute
 edit_connmark_title_edit=Edit Connmark
-list_rawrules_title=Raw Rules
-list_services_title=Servizi
 list_countrycodes_title=Country Codes
-list_ndpiprotocols_title=nDPI Services
-list_ndpirisks_title=nDPI Risks
 redirect_src=Sorgente
 redirect_dst=Destinazione
 redirect_service=Servizio
@@ -190,26 +184,38 @@ host_help=Note: not required for mac only host
 zone_help=Note: range eg. ppp0-ppp10 or ppp+
 port_help=Note: range eg. 6000:6010
 log_help=Note: target accept logs flow, target drop/reject logs action
-flowstat_max_help=Note: analysing all flows is resource intensive
 preroute_help=Note: zone as destination invalid during prerouting
 log_update=Aggiorna
 log_title=Action Log
 flowlog_title=Flow Log
+flowlog_current=Current Flow Log
+flowlog_all=All Historical Flow Logs
 report_flowstat_title=Flow Statistics Report
-flowstat_type_source=Top Sources
-flowstat_type_destination=Top Destinations
-flowstat_type_dport=Top Destination Ports
-flowstat_type_protocol=Top Protocols
-flowstat_type_hostname=Top Hostnames
-flowstat_type_risk=Top Risks
+flowstat_type_source_desc=Top Sources
+flowstat_type_destination_desc=Top Destinations
+flowstat_type_dport_desc=Top Ports
+flowstat_type_protocol_desc=Top Protocols
+flowstat_type_hostname_desc=Top Hostnames
+flowstat_type_risk_desc=Top Risks
+flowstat_type_source_name=Source
+flowstat_type_destination_name=Destination
+flowstat_type_dport_name=Port
+flowstat_type_protocol_name=Protocol
+flowstat_type_hostname_name=Hostname
+flowstat_type_risk_name=Risk
 flowstat_percent=Percentage
 flowstat_traffic=Traffic
+sql_operator_equal_desc=is equal to
+sql_operator_like_desc=contains
 edit_flowstat_title_create=Create Flow Statistics Report
 edit_flowstat_log=Log
 edit_flowstat_type=Type
 edit_flowstat_max=Max Flows
-edit_flowstat_top=Display the Top
-edit_flowstat_string=Only Flows that Contain
+edit_flowstat_top=Top
+edit_flowstat_target=Target
+item_ip_blacklist_desc=IP Address
+item_domain_blacklist_desc=DNS Domain Name
+item_sha1_blacklist_desc=SSL Certificate Fingerprint
 edit_options_title=Opzioni
 options_rp_filter_name=rp_filter
 options_rp_filter_desc=Blocco dei pacchetti provenienti da interfacce inaspettate, se stai implementando una VPN probabilmente hai bisogno che sia off o unchange.
@@ -233,12 +239,12 @@ options_drop_ip_blacklist_name=drop_ip_blacklist
 options_drop_ip_blacklist_desc=Drop IP blacklist ( globally )
 options_drop_domain_blacklist_name=drop_domain_blacklist
 options_drop_domain_blacklist_desc=Drop domain blacklist ( globally )
-options_drop_ja3_blacklist_name=drop_ja3_blacklist
-options_drop_ja3_blacklist_desc=Drop ja3 blacklist - SSL handshake fingerprint ( globally )
 options_drop_sha1_blacklist_name=drop_sha1_blacklist
 options_drop_sha1_blacklist_desc=Drop sha1 blacklist - SSL certificate fingerprint ( globally )
 options_nf_conntrack_max_name=nf_conntrack_max
 options_nf_conntrack_max_desc=Maximum number of sessions in conntrack table.
+options_clamp_mss_to_pmtu_name=clamp_mss_to_pmtu
+options_clamp_mss_to_pmtu_desc=Automatically set MSS for TCP SYN packets outgoing on any ppp interface.
 options_log_limit_name=log_limit
 options_log_limit_desc=Numero medio di log generati in un ora per una singola catena (zona->zona).
 options_log_limit_burst_name=log_limit_burst
@@ -421,9 +427,8 @@ save_rule_error1=numero porta errato (0-65535 o nessuno).
 save_rule_error2=il valore della porta è valido solo per i servizi tcp e udp.
 save_rule_error3=sorgente e destinazione non possono essere entrambi "FIREWALL".
 save_rule_error4=mark deve essere un numero decimale o esadecimale (es.: 10, 0x0A).
-save_rule_error5=All nDPI Services, Hostname and Risk, only valid for DROP or REJECT target.
-save_rule_error6=Rate only valid for DROP target.
-save_rule_error7=Log not valid for Rate Limit.
+save_rule_error5=Rate only valid for DROP target.
+save_rule_error6=Log not valid for Rate Limit.
 
 save_connmark_error_title1=Fail to delete Connmark Rule
 save_connmark_error_title2=Fail to create new Connmark Rule
@@ -448,3 +453,5 @@ save_conntrack_error9=irc helper only supports tcp.
 save_conntrack_error10=sane helper only supports tcp.
 save_conntrack_error11=snmp helper only supports udp.
 save_conntrack_error12=netbios-ns helper only supports udp.
+
+list_flowstat_error1=target is required.
diff --git a/src/turtlefirewall/lang/nl b/src/turtlefirewall/lang/nl
index 7fda1be..09c6058 100644
--- a/src/turtlefirewall/lang/nl
+++ b/src/turtlefirewall/lang/nl
@@ -32,6 +32,7 @@ time=Time
 timeitems=Weekdays
 name=Naam
 id=ID
+rule=Filter
 nat=NAT
 masquerade=Verbergen
 connmark_preroute=Connmark Preroute
@@ -82,6 +83,7 @@ items=Items
 reference=Ref
 references=References
 file=File
+flag=DPI
 category=Category
 index=Turtle Firewall index
 index_start=Start
@@ -93,22 +95,21 @@ index_showiptmangle=Show MANGLE Table
 index_showiptraw=Show RAW Table
 index_showconntrack=Show CONNTRACK Table
 index_flushconntrack=Flush CONNTRACK Table
-index_icon_firewall_items=Objecten
-index_icon_firewall_rules=Regels
-index_icon_firewall_nat=NAT en Masquerading
-index_icon_firewall_manglerules=Mangle Rules
-index_icon_firewall_rawrules=Raw Rules
-index_icon_firewall_services=Diensten
-index_icon_firewall_countrycodes=Country Codes
-index_icon_firewall_ndpiprotocols=nDPI Services
-index_icon_firewall_ndpirisks=nDPI Risks
-index_icon_edit_options=Options
-index_icon_log=Log
+index_icon_items=Objecten
+index_icon_rules=Regels
+index_icon_nat=NAT en Masquerading
+index_icon_manglerules=Mangle Rules
+index_icon_rawrules=Raw Rules
+index_icon_services=Diensten
+index_icon_countrycodes=Country Codes
+index_icon_ndpiprotocols=nDPI Services
+index_icon_ndpirisks=nDPI Risks
+index_icon_options=Options
+index_icon_log=Action Log
 index_icon_flowlog=Flow Log
 index_icon_flowstat=Flow Statistics
 index_icon_backup=Backup
 list_itemreferences_title=Item References
-list_items_title=Firewall Objecten
 list_items_create_zone=Toevoegen nieuwe zone
 list_items_create_geoip=create new geoip
 list_items_create_net=Toevoegen nieuw netwerk
@@ -145,14 +146,12 @@ edit_addresslist_title_create=Create new AddressList
 edit_addresslist_title_edit=Edit AddressList
 edit_ipset_title_create=Create new IPSet
 edit_ipset_title_edit=Edit IPSet
-list_nat_title=NAT en Masquerading
 list_nat_create_nat=Toevoegen NAT regel
 list_nat_create_masq=Toevoegen Masquerade regel
 edit_nat_title_create=NAT toevoegen
 edit_nat_title_edit=NAT wijzigen
 edit_masq_title_create=Masquerade toevoegen
 edit_masq_title_edit=Masquerade wijzigen
-list_rules_title=Firewall regels
 list_rules_create_rule=Regel toevoegen
 list_connmarkpreroutes_create_rule=create new Connmark Preroute
 list_connmarks_create_rule=create new Connmark
@@ -160,7 +159,6 @@ list_conntrackpreroutes_create_rule=create new Conntrack Preroute
 list_conntracks_create_rule=create new Conntrack
 edit_rule_title_create=Regel toevoegen
 edit_rule_title_edit=Regel wijzigen
-list_manglerules_title=Mangle Rules
 edit_conntrackpreroute_title_create=Create new Conntrack Preroute
 edit_conntrack_title_create=Create new Conntrack
 edit_connmarkpreroute_title_create=Create new Connmark Preroute
@@ -169,11 +167,7 @@ edit_conntrackpreroute_title_edit=Edit Conntrack Preroute
 edit_conntrack_title_edit=Edit Conntrack
 edit_connmarkpreroute_title_edit=Edit Connmark Preroute
 edit_connmark_title_edit=Edit Connmark
-list_rawrules_title=Raw Rules
-list_services_title=Diensten
 list_countrycodes_title=Country Codes
-list_ndpiprotocols_title=nDPI Services
-list_ndpirisks_title=nDPI Risks
 redirect_src=Bron
 redirect_dst=Doel
 redirect_service=Dienst
@@ -190,26 +184,38 @@ host_help=Note: not required for mac only host
 zone_help=Note: range eg. ppp0-ppp10 or ppp+
 port_help=Note: range eg. 6000:6010
 log_help=Note: target accept logs flow, target drop/reject logs action
-flowstat_max_help=Note: analysing all flows is resource intensive
 preroute_help=Note: zone as destination invalid during prerouting
 log_update=Refresh
 log_title=Action Log
 flowlog_title=Flow Log
+flowlog_current=Current Flow Log
+flowlog_all=All Historical Flow Logs
 report_flowstat_title=Flow Statistics Report
-flowstat_type_source=Top Sources
-flowstat_type_destination=Top Destinations
-flowstat_type_dport=Top Destination Ports
-flowstat_type_protocol=Top Protocols
-flowstat_type_hostname=Top Hostnames
-flowstat_type_risk=Top Risks
+flowstat_type_source_desc=Top Sources
+flowstat_type_destination_desc=Top Destinations
+flowstat_type_dport_desc=Top Ports
+flowstat_type_protocol_desc=Top Protocols
+flowstat_type_hostname_desc=Top Hostnames
+flowstat_type_risk_desc=Top Risks
+flowstat_type_source_name=Source
+flowstat_type_destination_name=Destination
+flowstat_type_dport_name=Port
+flowstat_type_protocol_name=Protocol
+flowstat_type_hostname_name=Hostname
+flowstat_type_risk_name=Risk
 flowstat_percent=Percentage
 flowstat_traffic=Traffic
+sql_operator_equal_desc=is equal to
+sql_operator_like_desc=contains
 edit_flowstat_title_create=Create Flow Statistics Report
 edit_flowstat_log=Log
 edit_flowstat_type=Type
 edit_flowstat_max=Max Flows
-edit_flowstat_top=Display the Top
-edit_flowstat_string=Only Flows that Contain
+edit_flowstat_top=Top
+edit_flowstat_target=Target
+item_ip_blacklist_desc=IP Address
+item_domain_blacklist_desc=DNS Domain Name
+item_sha1_blacklist_desc=SSL Certificate Fingerprint
 edit_options_title=Edit Options
 options_rp_filter_name=rp_filter
 options_rp_filter_desc=Route verification: discarding packets received on an interface which does not expect to handle traffic from the given source address. If you are using VPN you need to disable this option.
@@ -233,12 +239,12 @@ options_drop_ip_blacklist_name=drop_ip_blacklist
 options_drop_ip_blacklist_desc=Drop IP blacklist ( globally )
 options_drop_domain_blacklist_name=drop_domain_blacklist
 options_drop_domain_blacklist_desc=Drop domain blacklist ( globally )
-options_drop_ja3_blacklist_name=drop_ja3_blacklist
-options_drop_ja3_blacklist_desc=Drop ja3 blacklist - SSL handshake fingerprint ( globally )
 options_drop_sha1_blacklist_name=drop_sha1_blacklist
 options_drop_sha1_blacklist_desc=Drop sha1 blacklist - SSL certificate fingerprint ( globally )
 options_nf_conntrack_max_name=nf_conntrack_max
 options_nf_conntrack_max_desc=Maximum number of sessions in conntrack table.
+options_clamp_mss_to_pmtu_name=clamp_mss_to_pmtu
+options_clamp_mss_to_pmtu_desc=Automatically set MSS for TCP SYN packets outgoing on any ppp interface.
 options_log_limit_name=log_limit
 options_log_limit_desc=Maximum average matching rate: number of logs per hour.
 options_log_limit_burst_name=log_limit_burst
@@ -421,9 +427,8 @@ save_rule_error1=Invalid port (1-65535) or port range (1-65535:1-65535).
 save_rule_error2=port is valid only for tcp and udp services.
 save_rule_error3=source and destination cannot both be "FIREWALL".
 save_rule_error4=source and destination are required.
-save_rule_error5=All nDPI Services, Hostname and Risk, only valid for DROP or REJECT target.
-save_rule_error6=Rate only valid for DROP target.
-save_rule_error7=Log not valid for Rate Limit.
+save_rule_error5=Rate only valid for DROP target.
+save_rule_error6=Log not valid for Rate Limit.
 
 save_connmark_error_title1=Fail to delete Connmark Rule
 save_connmark_error_title2=Fail to create new Connmark Rule
@@ -448,3 +453,5 @@ save_conntrack_error9=irc helper only supports tcp.
 save_conntrack_error10=sane helper only supports tcp.
 save_conntrack_error11=snmp helper only supports udp.
 save_conntrack_error12=netbios-ns helper only supports udp.
+
+list_flowstat_error1=target is required.
diff --git a/src/turtlefirewall/list_actionlog.cgi b/src/turtlefirewall/list_actionlog.cgi
index 874592d..9152f0e 100644
--- a/src/turtlefirewall/list_actionlog.cgi
+++ b/src/turtlefirewall/list_actionlog.cgi
@@ -3,15 +3,15 @@
 #======================================================================
 # Turtle Firewall webmin module
 #
-# Copyright (c) Andrea Frigido
+# Copyright (c) 2001-2026 Andrea Frigido 
 # You may distribute under the terms of either the GNU General Public
 # License
 #======================================================================
 
-do 'turtlefirewall-lib.pl';
+require './turtlefirewall-lib.pl';
 &ReadParse();
 
-&ui_print_header( "$icons{LOG}{IMAGE}$text{'log_title'}", $text{'title'}, "" );
+&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_log'}", $text{'title'}, "" );
 
 &showLog();
 
@@ -38,9 +38,8 @@ sub showLog {
 	my %dpt_list = ('*' => undef);
 
 	open( LOG, "<", $SysLogFile );
-	while(  ) {
-		if( $_ =~ /TFW=/ ) {
-			my $l = $_;
+	while (my $l = ) {
+		if( $l =~ /TFW=/ ) {
 
 			my $time = '';
 			my $action = '';
@@ -112,7 +111,7 @@ sub showLog {
 	}
 
 	print &ui_form_start("list_actionlog.cgi", "post");
-	print "
$pageindex
\n"; + print "
$pageindex
\n"; my $opz; @@ -202,7 +201,7 @@ sub showLog { print &ui_form_end(); - print "
$pageindex
\n"; + print "
$pageindex
\n"; } sub showTD { diff --git a/src/turtlefirewall/list_countrycodes.cgi b/src/turtlefirewall/list_countrycodes.cgi index 06db042..c78f4c1 100644 --- a/src/turtlefirewall/list_countrycodes.cgi +++ b/src/turtlefirewall/list_countrycodes.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); -&ui_print_header( "$icons{COUNTRYCODE}{IMAGE}$text{'list_countrycodes_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_countrycodes'}", $text{'title'}, "" ); &LoadCountryCodes($fw); &showCountryCodes(); diff --git a/src/turtlefirewall/list_flowlog.cgi b/src/turtlefirewall/list_flowlog.cgi index bd22829..a99aca7 100644 --- a/src/turtlefirewall/list_flowlog.cgi +++ b/src/turtlefirewall/list_flowlog.cgi @@ -3,16 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); use Time::Piece; -&ui_print_header( "$icons{LOG}{IMAGE}$text{'flowlog_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_flowlog'}", $text{'title'}, "" ); &LoadNdpiRisks($fw); &showLog(); @@ -29,39 +29,36 @@ sub showLog { my $pagelen = 20; my @buffer = (); - #my %l3proto_list = ('*'=>'x'); - #my %l4proto_list = ('*'=>'x'); - my %src_list = ('*' => undef); - #my %sport_list = ('*'=>'x'); - #my %dst_list = ('*'=>'x'); - #my %dport_list = ('*'=>'x'); - #my %ubytes_list = ('*'=>'x'); - #my %dbytes_list = ('*'=>'x'); - #my %upackets_list = ('*'=>'x'); - #my %dpackets_list = ('*'=>'x'); - #my %ifindex_list = ('*'=>'x'); - #my %connmark_list = ('*'=>'x'); - #my %srcnat_list = ('*'=>'x'); - #my %dstnat_list = ('*'=>'x'); - #my %proto_list = ('*'=>'x'); - #my %host_list = ('*'=>'x'); - #my %ja4c_list = ('*'=>'x'); - #my %ja3c_list = ('*'=>'x'); - #my %tlsfp_list = ('*'=>'x'); - #my %tlsv_list = ('*'=>'x'); - #my %risk_list = ('*'=>'x'); + #my %l3proto_list = ('*' => undef); + #my %l4proto_list = ('* '=> undef); + my %source_list = ('*' => undef); + #my %sport_list = ('*' => undef); + #my %destination_list = ('*' => undef); + #my %dport_list = ('*' => undef); + #my %ubytes_list = ('*' => undef); + #my %dbytes_list = ('*' => undef); + #my %upackets_list = ('*' => undef); + #my %dpackets_list = ('*' => undef); + #my %ifindex_list = ('*' => undef); + #my %connmark_list = ('*' => undef); + #my %srcnat_list = ('*' => undef); + #my %dstnat_list = ('*' => undef); + #my %protocol_list = ('*' => undef); + #my %hostname_list = ('*' => undef); + #my %ja4c_list = ('*' => undef); + #my %tlsfp_list = ('*' => undef); + #my %risk_list = ('*' => undef); open( LOG, "<", $FlowLogFile ); - while( ) { - my $l = $_; + while (my $l = ) { my $stime = ''; my $etime = ''; my $l3proto = ''; my $l4proto = ''; - my $src = ''; + my $source = ''; my $sport = ''; - my $dst = ''; + my $destination = ''; my $dport = ''; my $ubytes = ''; my $dbytes = ''; @@ -71,12 +68,10 @@ sub showLog { my $connmark = ''; my $srcnat = ''; my $dstnat = ''; - my $proto = ''; - my $host = ''; + my $protocol = ''; + my $hostname = ''; my $ja4c = ''; - my $ja3c = ''; my $tlsfp = ''; - my $tlsv = ''; my $risk = ''; if( $l =~ /^(.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) / ) { @@ -84,9 +79,9 @@ sub showLog { $etime = $2; $l3proto = $3; $l4proto = $4; - $src = $5; + $source = $5; $sport = $6; - $dst = $7; + $destination = $7; $dport = $8; $ubytes = $9; $dbytes = $10; @@ -98,41 +93,37 @@ sub showLog { if( $l =~ /CM=(.*?)( |$)/ ) { $connmark = $1; } if( $l =~ /SN=(.*?)( |$)/ ) { $srcnat = $1; } if( $l =~ /DN=(.*?)( |$)/ ) { $dstnat = $1; } - if( $l =~ /P=(.*?)( |$)/ ) { $proto = $1; } - if( $l =~ /H=(.*?)( |$)/ ) { $host = $1; } + if( $l =~ /P=(.*?)( |$)/ ) { $protocol = $1; } + if( $l =~ /H=(.*?)( |$)/ && $l !~ /H=\"(.*?)\"( |$)/ ) { $hostname = $1; } if( $l =~ /c=(.*?)( |$)/ ) { $ja4c = $1; } - if( $l =~ /C=(.*?)( |$)/ ) { $ja3c = $1; } if( $l =~ /F=(.*?)( |$)/ ) { $tlsfp = $1; } - if( $l =~ /V=(.*?)( |$)/ ) { $tlsv = $1; } if( $l =~ /R=(.*?)( |$)/ ) { $risk = $1; } - #if( $l3proto ne '' ) {$l3proto_list{$l3proto} = 'x';} - #if( $l4proto ne '' ) {$l4proto_list{$l4proto} = 'x';} - if( $src ne '' ) {$src_list{$src} = undef;} - #if( $sport ne '' ) {$sport_list{$sport} = 'x';} - #if( $dst ne '' ) {$dst_list{$dst} = 'x';} - #if( $dport ne '' ) {$dport_list{$dport} = 'x';} - #if( $ubytes ne '' ) {$ubytes_list{$ubytes} = 'x';} - #if( $dbytes ne '' ) {$dbytes_list{$dbytes} = 'x';} - #if( $upackets ne '' ) {$upackets_list{$upackets} = 'x';} - #if( $dpackets ne '' ) {$dpackets_list{$dpackets} = 'x';} - #if( $ifindex ne '' ) {$ifindex_list{$ifindex} = 'x';} - #if( $connmark ne '' ) {$connmark_list{$connmark} = 'x';} - #if( $srcnat ne '' ) {$srcnat_list{$srcnat} = 'x';} - #if( $dstnat ne '' ) {$dstnat_list{$dstnat} = 'x';} - #if( $proto ne '') {$proto_list{$proto} = 'x';} - #if( $host ne '') {$host_list{$host} = 'x';} - #if( $ja4c ne '') {$ja4c_list{$ja4c} = 'x';} - #if( $ja3c ne '') {$ja3c_list{$ja3c} = 'x';} - #if( $tlsfp ne '') {$tlsfp_list{$tlsfp} = 'x';} - #if( $tlsv ne '') {$tlsv_list{$tlsv} = 'x';} - #if( $risk ne '') {$risk_list{$risk} = 'x';} + #if( $l3proto ne '' ) {$l3proto_list{$l3proto} = undef;} + #if( $l4proto ne '' ) {$l4proto_list{$l4proto} = undef;} + if( $source ne '' ) {$source_list{$source} = undef;} + #if( $sport ne '' ) {$sport_list{$sport} = undef;} + #if( $destination ne '' ) {$destination_list{$destination} = undef;} + #if( $dport ne '' ) {$dport_list{$dport} = undef;} + #if( $ubytes ne '' ) {$ubytes_list{$ubytes} = undef;} + #if( $dbytes ne '' ) {$dbytes_list{$dbytes} = undef;} + #if( $upackets ne '' ) {$upackets_list{$upackets} = undef;} + #if( $dpackets ne '' ) {$dpackets_list{$dpackets} = undef;} + #if( $ifindex ne '' ) {$ifindex_list{$ifindex} = undef;} + #if( $connmark ne '' ) {$connmark_list{$connmark} = undef;} + #if( $srcnat ne '' ) {$srcnat_list{$srcnat} = undef;} + #if( $dstnat ne '' ) {$dstnat_list{$dstnat} = undef;} + #if( $protocol ne '') {$protocol_list{$protocol} = undef;} + #if( $hostname ne '') {$hostname_list{$hostname} = undef;} + #if( $ja4c ne '') {$ja4c_list{$ja4c} = undef;} + #if( $tlsfp ne '') {$tlsfp_list{$tlsfp} = undef;} + #if( $risk ne '') {$risk_list{$risk} = undef;} if( ($in{l3proto} eq '' || $in{l3proto} eq '*' || $in{l3proto} eq $l3proto) && ($in{l4proto} eq '' || $in{l4proto} eq '*' || $in{l4proto} eq $l4proto) && - ($in{src} eq '' || $in{src} eq '*' || $in{src} eq $src) && + ($in{source} eq '' || $in{source} eq '*' || $in{source} eq $source) && ($in{sport} eq '' || $in{sport} eq '*' || $in{sport} eq $sport) && - ($in{dst} eq '' || $in{dst} eq '*' || $in{dst} eq $dst) && + ($in{destination} eq '' || $in{destination} eq '*' || $in{destination} eq $destination) && ($in{dport} eq '' || $in{dport} eq '*' || $in{dport} eq $dport) && ($in{ubytes} eq '' || $in{ubytes} eq '*' || $in{ubytes} eq $ubytes) && ($in{dbytes} eq '' || $in{dbytes} eq '*' || $in{dbytes} eq $dbytes) && @@ -142,20 +133,18 @@ sub showLog { ($in{connmark} eq '' || $in{connmark} eq '*' || $in{connmark} eq $connmark) && ($in{srcnat} eq '' || $in{srcnat} eq '*' || $in{srcnat} eq $srcnat) && ($in{dstnat} eq '' || $in{dstnat} eq '*' || $in{dstnat} eq $dstnat) && - ($in{proto} eq '' || $in{proto} eq '*' || $in{proto} eq $proto) && - ($in{host} eq '' || $in{host} eq '*' || $in{host} eq $host) && + ($in{protocol} eq '' || $in{protocol} eq '*' || $in{protocol} eq $protocol) && + ($in{hostname} eq '' || $in{hostname} eq '*' || $in{hostname} eq $hostname) && ($in{ja4c} eq '' || $in{ja4c} eq '*' || $in{ja4c} eq $ja4c) && - ($in{ja3c} eq '' || $in{ja3c} eq '*' || $in{ja3c} eq $ja3c) && ($in{tlsfp} eq '' || $in{tlsfp} eq '*' || $in{tlsfp} eq $tlsfp) && - ($in{tlsv} eq '' || $in{tlsv} eq '*' || $in{tlsv} eq $tlsv) && ($in{risk} eq '' || $in{risk} eq '*' || $in{risk} eq $risk) ) { $count++; if( $count >= ($pag-1) * $pagelen && $count < $pag * $pagelen) { - push @buffer, [$stime, $etime, $l3proto, $l4proto, $src, $sport, $dst, $dport, + push @buffer, [$stime, $etime, $l3proto, $l4proto, $source, $sport, $destination, $dport, $ubytes, $dbytes, $upackets, $dpackets, $ifindex, - $connmark, $srcnat, $dstnat, $proto, $host, - $ja4c, $ja3c, $tlsfp, $tlsv, $risk]; + $connmark, $srcnat, $dstnat, $protocol, $hostname, + $ja4c, $tlsfp, $risk]; } } } @@ -163,11 +152,11 @@ sub showLog { # Pages index my $urlparam = 'stime='.$in{stime}.'&etime='.$in{etime}.'&l3proto='.$in{l3proto}.'&l4proto='.$in{l4proto}. - '&src='.$in{src}.'&sport='.$in{sport}.'&dst='.$in{dst}.'&dport='.$in{dport}.'&ubytes='.$in{ubytes}.'&dbytes='.$in{dbytes}. + '&source='.$in{source}.'&sport='.$in{sport}.'&destination='.$in{destination}.'&dport='.$in{dport}.'&ubytes='.$in{ubytes}.'&dbytes='.$in{dbytes}. '&upackets='.$in{upackets}.'&dpackets='.$in{dpackets}.'&ifindex='.$in{ifindex}. '&connmark='.$in{connmark}.'&srcnat='.$in{srcnat}.'&dstnat='.$in{dstnat}. - '&proto='.$in{proto}.'&host='.$in{host}.'&ja4c='.$in{ja4c}.'&ja3c='.$in{ja3c}. - '&tlsfp='.$in{tlsfp}.'&tlsv='.$in{tlsv}.'&risk='.$in{risk}; + '&protocol='.$in{protocol}.'&hostname='.$in{hostname}.'&ja4c='.$in{ja4c}. + '&tlsfp='.$in{tlsfp}.'&risk='.$in{risk}; my $pageindex = ''; if( $pag > 1 ) { $pageindex .= " << "; @@ -181,7 +170,7 @@ sub showLog { } print &ui_form_start("list_flowlog.cgi", "post"); - print "
$pageindex
\n"; + print "
$pageindex
\n"; my $opz; @@ -203,27 +192,27 @@ sub showLog { $hl4proto .= "L4PROTO
"; push(@head, $hl4proto ); - local $hproto; - $hproto .= "ndpiPROTO
"; - push(@head, $hproto ); + local $hprotocol; + $hprotocol .= "L7PROTO
"; + push(@head, $hprotocol ); - local $hhost; - $hhost .= "HOSTNAME
"; - push(@head, $hhost ); + local $hhostname; + $hhostname .= "hostNAME
"; + push(@head, $hhostname ); - local $hsrc; - $hsrc .= "srcADDR
"; - push(@head, $hsrc ); + local $hsource; + $hsource .= "srcADDR
"; + push(@head, $hsource ); local $hsport; $hsport .= "srcPORT
"; push(@head, $hsport ); - local $hdst; - $hdst .= "dstADDR
"; - push(@head, $hdst ); + local $hdestination; + $hdestination .= "dstADDR
"; + push(@head, $hdestination ); local $hdport; $hdport .= "dstPORT
"; @@ -273,18 +262,10 @@ sub showLog { $hja4c .= "ja4cFINGERPRINT
"; push(@head, $hja4c ); - local $hja3c; - $hja3c .= "ja3cFINGERPRINT
"; - push(@head, $hja3c ); - local $htlsfp; $htlsfp .= "tlsFINGERPRINT
"; push(@head, $htlsfp ); - local $htlsv; - $htlsv .= "tlsVERSION
"; - push(@head, $htlsv ); - local $hrisk; $hrisk .= "RISK
"; push(@head, $hrisk ); @@ -311,24 +292,22 @@ sub showLog { "style=white-space:nowrap", "style=white-space:nowrap", "style=white-space:nowrap", - "style=white-space:nowrap", - "style=text-align:center", "style=white-space:nowrap" ); print &ui_columns_start(\@head, 100, 0, \@tds); foreach my $l (@buffer) { local @cols; - my ($stime, $etime, $l3proto, $l4proto, $src, $sport, $dst, $dport, $ubytes, $dbytes, $upackets, $dpackets, $ifindex, - $connmark, $srcnat, $dstnat, $proto, $host, $ja4c, $ja3c, $tlsfp, $tlsv, $risk) = @$l; + my ($stime, $etime, $l3proto, $l4proto, $source, $sport, $destination, $dport, $ubytes, $dbytes, $upackets, $dpackets, $ifindex, + $connmark, $srcnat, $dstnat, $protocol, $hostname, $ja4c, $tlsfp, $risk) = @$l; &showTD(localtime($stime)->strftime('%b %d %X')); &showTD(localtime($etime)->strftime('%b %d %X')); &showTD(&l3protoname($l3proto)); &showTD(&l4protoname($l4proto)); - &showTD($proto); - &showTD($host); - &showTD($src); + &showTD($protocol); + &showTD($hostname); + &showTD($source); &showTD($sport); - &showTD($dst); + &showTD($destination); &showTD($dport); &showTD(&roundbytes($ubytes + $dbytes)); &showTD(&roundbytes($ubytes)); @@ -344,9 +323,7 @@ sub showLog { &showTD($srcnat); &showTD($dstnat); &showTD($ja4c); - &showTD($ja3c); &showTD($tlsfp); - &showTD($tlsv); &showTD(&getrisknames($risk)); print &ui_columns_row(\@cols, \@tds); } @@ -358,7 +335,7 @@ sub showLog { print &ui_form_end(); - print "
$pageindex
\n"; + print "
$pageindex
\n"; } sub showTD { diff --git a/src/turtlefirewall/list_flowstat.cgi b/src/turtlefirewall/list_flowstat.cgi index 691e3a9..1160191 100644 --- a/src/turtlefirewall/list_flowstat.cgi +++ b/src/turtlefirewall/list_flowstat.cgi @@ -3,172 +3,155 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); use Tie::File; use Time::Piece; -&ui_print_header( "$icons{FLOWSTAT}{IMAGE}$text{'report_flowstat_title'}", $text{'title'}, "" ); - my $log = $in{'log'}; + +my $is_log = $in{'is_log'}; +if( $is_log eq '0' ) { + $log = join("\0", glob("${FlowLogFile}-*")); +} elsif( $is_log eq '2' ) { + $log = "/var/log/flowinfo.tmp"; + system("cp -f $FlowLogFile $log > /dev/null 2>&1"); + system("convertflowinfo.pl --log=$log > /dev/null 2>&1"); +} +$log =~ s/\0/ UNION ALL select * from /g; +$log = "(select * from $log)"; + my $type = $in{'type'}; -my $max = $in{'max'}; my $top = $in{'top'}; -my $string = $in{'string'}; +my $is_target = $in{'is_target'}; +my $target_type = $in{'target_type'}; +my $target_op = $in{'target_op'}; +my $target = $in{'target'}; + +if( $target_op eq 'like' ) { $target = "%$target%"; } + +if( $is_target ) { + if( $target eq '' ) { &error( $text{list_flowstat_error1} ); } +} + +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_flowstat'}", $text{'title'}, "" ); if( $type eq 'risk' ) { &LoadNdpiRisks($fw); } +my $logflowtotal = 0; my $flowtotal = 0; -my ($type_list, $flows) = &getflows($log); +my $logflowcount = 0; +my $flowcount = 0; -my @stats = &getstats($flowreports{$type}{LOGIDX},$type_list,$flows); +my $firstflowtime = ''; +my $lastflowtime = ''; -&showstats($flowreports{$type}{TXTIDX},$flowreports{$type}{ICOIDX},@stats); +my $query = ''; -&ui_print_footer("edit_flowstat.cgi",'flow statistics'); +$query = "select count(*) from $log"; +$logflowcount = qx{q -Hp "$query" 2>/dev/null}; +$logflowcount =~ s/\n//; -#============================================================================ - -sub getflows { +$query = "select sum(ubytes+dbytes) from $log"; +$logflowtotal = qx{q -Hp "$query" 2>/dev/null}; +$logflowtotal =~ s/\n//; - my $log = shift; - my %type_list = (); +if( $is_target ) { + $query = "select sum(ubytes+dbytes) from $log where $target_type $target_op '$target'"; + $flowtotal = qx{q -Hp "$query" 2>/dev/null}; + $flowtotal =~ s/\n//; - my @last_log_lines = (); + $query = "select count(*) from $log where $target_type $target_op '$target'"; + $flowcount = qx{q -Hp "$query" 2>/dev/null}; + $flowcount =~ s/\n//; - use Fcntl 'O_RDONLY'; - tie @log_lines, 'Tie::File', $log, mode => O_RDONLY; - if( $max ne 'all' ) { - @last_log_lines = ($max >= @log_lines) ? @log_lines : @log_lines[-$max..-1]; - } else { - @last_log_lines = @log_lines; - } - untie @log_lines; + $query = "select stime from $log where $target_type $target_op '$target' order by stime asc limit 1"; + $firstflowtime = qx{q -Hp "$query" 2>/dev/null}; - my @log_lines = (); + $query = "select etime from $log where $target_type $target_op '$target' order by etime desc limit 1"; + $lastflowtime = qx{q -Hp "$query" 2>/dev/null}; +} else { + $flowtotal = $logflowtotal; + $flowcount = $logflowcount; - if( $string ne '' ) { - @log_lines = grep(/$string/, @last_log_lines); - } else { - @log_lines = @last_log_lines; - } - - my @flows = (); - - foreach my $l (@log_lines) { - - my $stime = ''; - my $etime = ''; - my $l3proto = ''; - my $l4proto = ''; - my $source = ''; - my $sport = ''; - my $destination = ''; - my $dport = ''; - my $ubytes = ''; - my $dbytes = ''; - my $upackets = ''; - my $dpackets = ''; - my $ifindex = ''; - my $connmark = ''; - my $srcnat = ''; - my $dstnat = ''; - my $protocol = ''; - my $hostname = ''; - my $ja4c = ''; - my $ja3c = ''; - my $tlsfp = ''; - my $tlsv = ''; - my $risk = ''; - - if( $l =~ /^(.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) / ) { - $stime = $1; - $etime = $2; - $l3proto = $3; - $l4proto = $4; - $source = $5; - $sport = $6; - $destination = $7; - $dport = $8; - $ubytes = $9; - $dbytes = $10; - $upackets = $11; - $dpackets = $12; - $ifindex = $13; - } + $query = "select stime from $log order by stime asc limit 1"; + $firstflowtime = qx{q -Hp "$query" 2>/dev/null}; - if( $l =~ /CM=(.*?)( |$)/ ) { $connmark = $1; } - if( $l =~ /SN=(.*?)( |$)/ ) { $srcnat = $1; } - if( $l =~ /DN=(.*?)( |$)/ ) { $dstnat = $1; } - if( $l =~ /P=(.*?)( |$)/ ) { $protocol = $1; } - if( $l =~ /H=(.*?)( |$)/ ) { $hostname = $1; } - if( $l =~ /c=(.*?)( |$)/ ) { $ja4c = $1; } - if( $l =~ /C=(.*?)( |$)/ ) { $ja3c = $1; } - if( $l =~ /F=(.*?)( |$)/ ) { $tlsfp = $1; } - if( $l =~ /V=(.*?)( |$)/ ) { $tlsv = $1; } - if( $l =~ /R=(.*?)( |$)/ ) { $risk = $1; } - - if( $type eq 'source' && $source ne '' ) {$type_list{$source} = '0';} - if( $type eq 'destination' && $destination ne '' ) {$type_list{$destination} = '0';} - if( $type eq 'dport' && $dport ne '' ) {$type_list{$dport} = '0';} - if( $type eq 'protocol' && $protocol ne '') {$type_list{$protocol} = '0';} - if( $type eq 'hostname' && $hostname ne '') {$type_list{$hostname} = '0';} - if( $type eq 'risk' && $risk ne '') {$type_list{$risk} = '0';} - - $flowtotal = ($flowtotal + $ubytes + $dbytes); - - push @flows, [$stime, $etime, $l3proto, $l4proto, $source, $sport, $destination, $dport, - $ubytes, $dbytes, $upackets, $dpackets, $ifindex, - $connmark, $srcnat, $dstnat, $protocol, $hostname, - $ja4c, $ja3c, $tlsfp, $tlsv, $risk]; - } - return (\%type_list, \@flows); + $query = "select etime from $log order by etime desc limit 1"; + $lastflowtime = qx{q -Hp "$query" 2>/dev/null}; } +$firstflowtime =~ s/\n//; +$firstflowtime = localtime($firstflowtime)->strftime('%b %d %X'); + +$lastflowtime =~ s/\n//; +$lastflowtime = localtime($lastflowtime)->strftime('%b %d %X'); + +my @stats = &getstats($log,$type,$top,$is_target,$target_type,$target_op,$target); +my $txtindex = $flowreports{$type}{DESCIDX}; +my $icoindex = $flowreports{$type}{ICOIDX}; + +print &ui_subheading($icons{FLOWSTAT}{IMAGE},$text{'report_flowstat_title'}); +&showstats($type,$is_target,$target_type,$target_op,$in{'target'},$flowcount,$flowtotal,$logflowcount,$firstflowtime,$lastflowtime,$txtindex,$icoindex,@stats); + +unlink "/var/log/flowinfo.tmp"; + +&ui_print_footer("edit_flowstat.cgi",'flow statistics'); + +#============================================================================ + sub getstats { - - my $logindex = shift; - my ($type_list,$flows) = @_; + + my $log = shift; + my $type = shift; + my $top = shift; + my $is_target = shift; + my $target_type = shift; + my $target_op = shift; + my $target = shift; + my $query = ''; my @stats = (); - # Sum bytes per Type - foreach my $f (@{$flows}) { - foreach $t (sort keys %{$type_list}) { - if( $f->[$logindex] eq $t ) { $type_list{$t} = ($type_list{$t} + $f->[8] + $f->[9]); } - } + if( $is_target ) { + $query = "select $type,sum(ubytes+dbytes) from $log where $type != '' and $target_type $target_op '$target' group by $type order by sum(ubytes+dbytes) desc limit $top"; + } else { + $query = "select $type,sum(ubytes+dbytes) from $log where $type != '' group by $type order by sum(ubytes+dbytes) desc limit $top"; } - # Sort Items by bytes - my $count = 0; - foreach $t (sort { $type_list{$b} <=> $type_list{$a} } keys %{$type_list}) { - push(@stats, [$t,$type_list{$t}]); - $count++; - last if($count == $top); + foreach my $l (qx{q -Hp "$query" 2>/dev/null}) { + $l =~ s/\n//; + my @t = split(/\|/, $l); + push(@stats, \@t); } + return @stats; } sub showstats { + my $type = shift; + my $is_target = shift; + my $target_type = shift; + my $target_op = shift; + my $target = shift; + my $flowcount = shift; + my $flowtotal = shift; + my $logflowcount = shift; + my $firstflowtime = shift; + my $lastflowtime = shift; my $txtindex = shift; my $icoindex = shift; my @stats = @_; my $graphwidth = 300; - my $logflowcount = qx{wc -l < $log 2>/dev/null}; - my $flowcount = @flows; - - my $firstflowtime = localtime($flows[0][0])->strftime('%b %d %X'); - my $lastflowtime = localtime($flows[$#flows][1])->strftime('%b %d %X'); - - print "Using $flowcount of $logflowcount flows from $log"; - if( $string ne '' ) { print " containing ".&ui_text_color($string, 'info').""; } + print "Using $flowcount of $logflowcount flows"; + if( $is_target ) { print " where $text{$flowreports{$target_type}{NAMEIDX}} $text{$sqloperators{$target_op}{DESCIDX}} ".&ui_text_color($target, 'info').""; } print " ( $firstflowtime --> $lastflowtime )"; @tds = ( "style=white-space:nowrap", "width=$graphwidth", "", "width=1% style=text-align:right;white-space:nowrap" ); diff --git a/src/turtlefirewall/list_itemreferences.cgi b/src/turtlefirewall/list_itemreferences.cgi index f486154..91922d6 100644 --- a/src/turtlefirewall/list_itemreferences.cgi +++ b/src/turtlefirewall/list_itemreferences.cgi @@ -3,17 +3,17 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $item = $in{'item'}; -&ui_print_header( "$icons{SHIELD}{IMAGE}$text{'list_itemreferences_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'list_itemreferences_title'}", $text{'title'}, "" ); &showItemReferences(); diff --git a/src/turtlefirewall/list_items.cgi b/src/turtlefirewall/list_items.cgi index d24a91f..6e54ecd 100644 --- a/src/turtlefirewall/list_items.cgi +++ b/src/turtlefirewall/list_items.cgi @@ -3,14 +3,14 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; -&ui_print_header( "$icons{SHIELD}{IMAGE}$text{'list_items_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_items'}", $text{'title'}, "" ); $form = 0; &showAddressList(); @@ -94,7 +94,7 @@ sub showAddressList { if( $blacklistcount eq '' ) { $blacklistcount = '0'; } push(@cols, $blacklistcount); push(@cols, "$icons{OPTION}{IMAGE}$blacklists{$b}{TYPE}" ); - push(@cols, "$icons{DESCRIPTION}{IMAGE}$blacklists{$b}{DESCRIPTION}"); + push(@cols, "$icons{DESCRIPTION}{IMAGE}$text{$blacklists{$b}{DESCIDX}}"); my $href = &ui_link("edit_options.cgi","".($fw->GetOption("drop_$b") eq 'on' ? "1" : '0').""); push(@cols, $href ); print &ui_checked_columns_row(\@cols, \@tds, "d", $k); @@ -358,7 +358,7 @@ sub showGroup { push(@cols, "$icons{GROUP}{IMAGE}$href" ); my $grouplist; my $type = ''; - for my $item (@{$group{ITEMS}}) { + for my $item (sort @{$group{ITEMS}}) { $type = $fw->GetItemType($item); $grouplist .= "$icons{$type}{IMAGE}$item
"; } @@ -563,7 +563,7 @@ sub showTimeGroup { my $href = &ui_link("edit_timegroup.cgi?timegroup=$k",$k); push(@cols, "$icons{TIMEGROUP}{IMAGE}$href" ); my $timegrouplist; - for my $item (@{$timegroup{ITEMS}}) { + for my $item (sort @{$timegroup{ITEMS}}) { $timegrouplist .= "$icons{TIME}{IMAGE}$item
"; } push(@cols, $timegrouplist ); diff --git a/src/turtlefirewall/list_manglerules.cgi b/src/turtlefirewall/list_manglerules.cgi index 740c746..bb525cd 100644 --- a/src/turtlefirewall/list_manglerules.cgi +++ b/src/turtlefirewall/list_manglerules.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); -&ui_print_header( "$icons{MARK}{IMAGE}$text{'list_manglerules_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_manglerules'}", $text{'title'}, "" ); $form = 0; &showConnmarkPreroute(); @@ -57,8 +57,8 @@ sub showConnmarkPreroute { my $nConnmarkPreroutes = $fw->GetConnmarkPreroutesCount(); + my $idx = $in{idx}; if( $in{table} eq 'connmarkpreroute' ) { - my $idx = $in{idx}; if( $in{down} > 0 || $in{up} > 0 ) { my $newIdx = $idx; if( $in{down} > 0 && $idx > 0 && $idx < $nConnmarkPreroutes ) { @@ -79,8 +79,8 @@ sub showConnmarkPreroute { my %attr = $fw->GetConnmarkPreroute($i); local @cols; if( $attr{'TARGET'} eq '' ) { $attr{'TARGET'} = 'ACCEPT'; } - my $bb = $idx == $i ? '' : ''; # BoldBegin - my $be = $idx == $i ? '' : ''; # BoldEnd + my $bb = $idx == $i && $in{table} eq 'connmarkpreroute' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'connmarkpreroute' ? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd my $href = &ui_link("edit_connmarkpreroute.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); @@ -100,7 +100,7 @@ sub showConnmarkPreroute { } else { my @services = split(/,/, $attr{'SERVICE'}); foreach my $s (@services) { - $servicelist .= "$icons{SERVICE}{IMAGE}${s}
"; + $servicelist .= "$icons{SERVICE}{IMAGE}$s
"; } } push(@cols, "${sb}${bb}${servicelist}${be}${se}"); @@ -135,11 +135,6 @@ sub showConnmarkPreroute { push(@cols, "${mimage}${sb}${bb}${cb}".($attr{'MARK'} ne '' ? $attr{'MARK'} : ' ')."${ce}${be}${se}" ); local $mover; $mover .= ""; - # if( $i < $nConnmarkPreroutes-1 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } if( $i < $nConnmarkPreroutes ) { $mover .= ""; } - # if( $i > 2 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } $mover .= "
V     v @@ -158,11 +153,6 @@ sub showConnmarkPreroute {    A  
"; push(@cols, $mover); print &ui_checked_columns_row(\@cols, \@tds, "d", $i); @@ -208,8 +198,8 @@ sub showConnmark { my $nConnmarks = $fw->GetConnmarksCount(); + my $idx = $in{idx}; if( $in{table} eq 'connmark' ) { - my $idx = $in{idx}; if( $in{down} > 0 || $in{up} > 0 ) { my $newIdx = $idx; if( $in{down} > 0 && $idx > 0 && $idx < $nConnmarks ) { @@ -230,8 +220,8 @@ sub showConnmark { my %attr = $fw->GetConnmark($i); local @cols; if( $attr{'TARGET'} eq '' ) { $attr{'TARGET'} = 'ACCEPT'; } - my $bb = $idx == $i ? '' : ''; # BoldBegin - my $be = $idx == $i ? '' : ''; # BoldEnd + my $bb = $idx == $i && $in{table} eq 'connmark' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'connmark' ? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd my $href = &ui_link("edit_connmark.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); @@ -261,7 +251,7 @@ sub showConnmark { } else { my @services = split(/,/, $attr{'SERVICE'}); foreach my $s (@services) { - $servicelist .= "$icons{SERVICE}{IMAGE}${s}
"; + $servicelist .= "$icons{SERVICE}{IMAGE}$s
"; } } push(@cols, "${sb}${bb}${servicelist}${be}${se}"); @@ -296,11 +286,6 @@ sub showConnmark { push(@cols, "${mimage}${sb}${bb}${cb}".($attr{'MARK'} ne '' ? $attr{'MARK'} : ' ')."${ce}${be}${se}" ); local $mover; $mover .= ""; - # if( $i < $nConnmarks-1 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } if( $i < $nConnmarks ) { $mover .= ""; } - # if( $i > 2 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } $mover .= "
V     v @@ -319,11 +304,6 @@ sub showConnmark {    A  
"; push(@cols, $mover); print &ui_checked_columns_row(\@cols, \@tds, "d", $i); diff --git a/src/turtlefirewall/list_nat.cgi b/src/turtlefirewall/list_nat.cgi index e79e879..c3d0f3e 100644 --- a/src/turtlefirewall/list_nat.cgi +++ b/src/turtlefirewall/list_nat.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); -&ui_print_header( "$icons{NAT}{IMAGE}$text{'list_nat_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_nat'}", $text{'title'}, "" ); $form = 0; &showNat(); @@ -54,55 +54,60 @@ sub showNat { $nNat = $fw->GetNatsCount(); + my $idx = $in{idx}; if( $in{table} eq 'nat' ) { - my $idx = $in{idx}; - if( $in{down} ne '' && $idx > 0 && $idx < $nNat ) { - my %appo = $fw->GetNat($idx+1); - $fw->AddNatAttr($idx+1, $fw->GetNat($idx)); - $fw->AddNatAttr($idx, %appo); - } - if( $in{up} ne '' && $idx > 1 && $idx <= $nNat ) { - my %appo = $fw->GetNat($idx-1); - $fw->AddNatAttr($idx-1, $fw->GetNat($idx)); - $fw->AddNatAttr($idx, %appo); + if( $in{down} > 0 || $in{up} > 0 ) { + my $newIdx = $idx; + if( $in{down} > 0 && $idx > 0 && $idx < $nNat ) { + $newIdx = $idx + $in{down}; + if( $newIdx > $nNat ) { $newIdx = $nNat; } + } + if( $in{up} > 0 && $idx > 1 && $idx <= $nNat ) { + $newIdx = $idx - $in{up}; + if( $newIdx < 1 ) { $newIdx = 1; } + } + $fw->MoveNat( $idx, $newIdx ); + $fw->SaveFirewall(); + $idx=$newIdx; } - $fw->SaveFirewall(); } for( my $i=1; $i<=$nNat; $i++ ) { my %attr = $fw->GetNat( $i ); local @cols; + my $bb = $idx == $i && $in{table} eq 'nat' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'nat'? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd - my $href = &ui_link("edit_nat.cgi?idx=$i","${sb}${i}${se}"); + my $href = &ui_link("edit_nat.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); push(@cols, $href ); my %zone = $fw->GetZone($attr{'VIRTUAL'}); if( $zone{IF} ne '' ) { - push(@cols, "$icons{ZONE}{IMAGE}${sb}$attr{'VIRTUAL'} ($zone{'IF'})${se}" ); + push(@cols, "$icons{ZONE}{IMAGE}${sb}${bb}$attr{'VIRTUAL'} ($zone{'IF'})${be}${se}" ); } else { - push(@cols, "$icons{HOST}{IMAGE}${sb}$attr{'VIRTUAL'}${se}" ); + push(@cols, "$icons{HOST}{IMAGE}${sb}${bb}$attr{'VIRTUAL'}${be}${se}" ); } - push(@cols, "$icons{HOST}{IMAGE}${sb}$attr{'REAL'}${se}" ); + push(@cols, "$icons{HOST}{IMAGE}${sb}${bb}$attr{'REAL'}${be}${se}" ); my $servicelist = ''; if( $attr{'SERVICE'} eq 'tcp' || $attr{'SERVICE'} eq 'udp' ) { if( $attr{'PORT'} ne '' ) { $servicelist .= "$icons{SERVICE}{IMAGE}$attr{'SERVICE'}/$attr{'PORT'}"; } else { - $servicelist .= "$icons{SERVICE}{IMAGE}{'SERVICE'}/all"; + $servicelist .= "$icons{SERVICE}{IMAGE}$attr{'SERVICE'}/all"; } } else { my @services = split(/,/, $attr{'SERVICE'}); foreach my $s (@services) { - $servicelist .= "$icons{SERVICE}{IMAGE}${s}
"; + $servicelist .= "$icons{SERVICE}{IMAGE}$s
"; } } - push(@cols, "${sb}${servicelist}${se}"); + push(@cols, "${sb}${bb}${servicelist}${be}${se}"); my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $nimage = $attr{'ACTIVE'} eq 'NO' ? $icons{NAT}{IMAGE} : $icons{NAT_A}{IMAGE}; - push(@cols, "${nimage}${sb}${cb}$text{YES}${ce}${se}" ); + push(@cols, "${nimage}${sb}${bb}${cb}$text{YES}${ce}${be}${se}" ); my $timage = $attr{'TOPORT'} eq '' ? '' : $icons{TOPORT}{IMAGE}; - push(@cols, "${timage}${sb}$attr{'TOPORT'}${se}" ); + push(@cols, "${timage}${sb}${bb}$attr{'TOPORT'}${be}${se}" ); local $mover; $mover .= ""; @@ -160,33 +165,38 @@ sub showMasquerade { my $nMasq = $fw->GetMasqueradesCount(); + my $idx = $in{idx}; if( $in{table} eq 'masquerade' ) { - my $idx = $in{idx}; - if( $in{down} ne '' && $idx > 0 && $idx < $nMasq ) { - my %appo = $fw->GetMasquerade($idx+1); - $fw->AddMasqueradeAttr($idx+1, $fw->GetMasquerade($idx)); - $fw->AddMasqueradeAttr($idx, %appo); - } - if( $in{up} ne '' && $idx > 1 && $idx <= $nMasq ) { - my %appo = $fw->GetMasquerade($idx-1); - $fw->AddMasqueradeAttr($idx-1, $fw->GetMasquerade($idx)); - $fw->AddMasqueradeAttr($idx, %appo); + if( $in{down} > 0 || $in{up} > 0 ) { + my $newIdx = $idx; + if( $in{down} > 0 && $idx > 0 && $idx < $nMasq ) { + $newIdx = $idx + $in{down}; + if( $newIdx > $nMasq ) { $newIdx = $nMasq; } + } + if( $in{up} > 0 && $idx > 1 && $idx <= $nMasq ) { + $newIdx = $idx - $in{up}; + if( $newIdx < 1 ) { $newIdx = 1; } + } + $fw->MoveMasquerade( $idx, $newIdx ); + $fw->SaveFirewall(); + $idx=$newIdx; } - $fw->SaveFirewall(); - } - + } + for( my $i=1; $i<=$nMasq; $i++ ) { my %attr = $fw->GetMasquerade( $i ); local @cols; + my $bb = $idx == $i && $in{table} eq 'masquerade' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'masquerade' ? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd - my $href = &ui_link("edit_masquerade.cgi?idx=$i","${sb}${i}${se}"); + my $href = &ui_link("edit_masquerade.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); push(@cols, $href ); my $type = ''; $type = $fw->GetItemType($attr{'SRC'}); - push(@cols, "$icons{$type}{IMAGE}${sb}$attr{'SRC'}${se}" ); + push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'SRC'}${be}${se}" ); $type = $fw->GetItemType($attr{'DST'}); - push(@cols, "$icons{$type}{IMAGE}${sb}$attr{'DST'}${se}" ); + push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'DST'}${be}${se}" ); my $servicelist = ''; if( $attr{'SERVICE'} eq 'tcp' || $attr{'SERVICE'} eq 'udp' ) { if( $attr{'PORT'} ne '' ) { @@ -197,20 +207,20 @@ sub showMasquerade { } else { my @services = split(/,/, $attr{'SERVICE'}); foreach my $s (@services) { - $servicelist .= "$icons{SERVICE}{IMAGE}${s}
"; + $servicelist .= "$icons{SERVICE}{IMAGE}$s
"; } } - push(@cols, "${sb}${servicelist}${se}"); + push(@cols, "${sb}${bb}${servicelist}${be}${se}"); if( $attr{'MASQUERADE'} eq 'NO' ) { my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $dimage = $attr{'ACTIVE'} eq 'NO' ? $icons{MASQUERADE}{IMAGE} : $icons{MASQUERADE_NO}{IMAGE}; - push(@cols, "${dimage}${sb}${cb}$text{NO}${ce}${se}" ); + push(@cols, "${dimage}${sb}${bb}${cb}$text{NO}${ce}${be}${se}" ); } else { my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $aimage = $attr{'ACTIVE'} eq 'NO' ? $icons{MASQUERADE}{IMAGE} : $icons{MASQUERADE_A}{IMAGE}; - push(@cols, "${aimage}${sb}${cb}$text{YES}${ce}${se}" ); + push(@cols, "${aimage}${sb}${bb}${cb}$text{YES}${ce}${be}${se}" ); } local $mover; $mover .= "
"; @@ -269,33 +279,39 @@ sub showRedirect { "$text{'redirect_move'}" ], 100, 0, \@tds); my $nRedirect = $fw->GetRedirectCount(); + + my $idx = $in{idx}; if( $in{table} eq 'redirect' ) { - my $idx = $in{idx}; - if( $in{down} ne '' && $idx > 0 && $idx < $nRedirect ) { - my %appo = $fw->GetRedirect($idx+1); - $fw->AddRedirectAttr($idx+1, $fw->GetRedirect($idx)); - $fw->AddRedirectAttr($idx, %appo); - } - if( $in{up} ne '' && $idx > 1 && $idx <= $nRedirect ) { - my %appo = $fw->GetRedirect($idx-1); - $fw->AddRedirectAttr($idx-1, $fw->GetRedirect($idx)); - $fw->AddRedirectAttr($idx, %appo); + if( $in{down} > 0 || $in{up} > 0 ) { + my $newIdx = $idx; + if( $in{down} > 0 && $idx > 0 && $idx < $nRedirect ) { + $newIdx = $idx + $in{down}; + if( $newIdx > $nRedirect ) { $newIdx = $nRedirect; } + } + if( $in{up} > 0 && $idx > 1 && $idx <= $nRedirect ) { + $newIdx = $idx - $in{up}; + if( $newIdx < 1 ) { $newIdx = 1; } + } + $fw->MoveRedirect( $idx, $newIdx ); + $fw->SaveFirewall(); + $idx=$newIdx; } - $fw->SaveFirewall(); } for( my $i=1; $i<=$nRedirect; $i++ ) { my %attr = $fw->GetRedirect( $i ); local @cols; + my $bb = $idx == $i && $in{table} eq 'redirect' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'redirect' ? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd - my $href = &ui_link("edit_redirect.cgi?idx=$i","${sb}${i}${se}"); + my $href = &ui_link("edit_redirect.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); push(@cols, $href ); my $type = ''; $type = $fw->GetItemType($attr{'SRC'}); - push(@cols, "$icons{$type}{IMAGE}${sb}$attr{'SRC'}${se}" ); + push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'SRC'}${be}${se}" ); $type = $fw->GetItemType($attr{'DST'}); - push(@cols, "$icons{$type}{IMAGE}${sb}$attr{'DST'}${se}" ); + push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'DST'}${be}${se}" ); my $servicelist = ''; if( $attr{'SERVICE'} eq 'tcp' || $attr{'SERVICE'} eq 'udp' ) { if( $attr{'PORT'} ne '' ) { @@ -306,23 +322,23 @@ sub showRedirect { } else { my @services = split(/,/, $attr{'SERVICE'}); foreach my $s (@services) { - $servicelist .= "$icons{SERVICE}{IMAGE}${s}
"; + $servicelist .= "$icons{SERVICE}{IMAGE}$s
"; } } - push(@cols, "${sb}${servicelist}${se}"); + push(@cols, "${sb}${bb}${servicelist}${be}${se}"); if( $attr{'REDIRECT'} eq 'NO' ) { my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $dimage = $attr{'ACTIVE'} eq 'NO' ? $icons{REDIRECT}{IMAGE} : $icons{REDIRECT_NO}{IMAGE}; - push(@cols, "${dimage}${sb}${cb}$text{NO}${ce}${se}" ); + push(@cols, "${dimage}${sb}${bb}${cb}$text{NO}${ce}${be}${se}" ); push(@cols, "" ); } else { my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $aimage = $attr{'ACTIVE'} eq 'NO' ? $icons{REDIRECT}{IMAGE} : $icons{REDIRECT_A}{IMAGE}; - push(@cols, "${aimage}${sb}${cb}$text{YES}${ce}${se}" ); + push(@cols, "${aimage}${sb}${bb}${cb}$text{YES}${ce}${be}${se}" ); my $timage = $attr{'TOPORT'} eq '' ? '' : $icons{TOPORT}{IMAGE}; - push(@cols, "${timage}${sb}$attr{'TOPORT'}${se}" ); + push(@cols, "${timage}${sb}${bb}$attr{'TOPORT'}${be}${se}" ); } local $mover; $mover .= "
"; diff --git a/src/turtlefirewall/list_ndpiprotocols.cgi b/src/turtlefirewall/list_ndpiprotocols.cgi index 2959fbc..217de4a 100644 --- a/src/turtlefirewall/list_ndpiprotocols.cgi +++ b/src/turtlefirewall/list_ndpiprotocols.cgi @@ -3,14 +3,14 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; -&ui_print_header( "$icons{NDPISERVICE}{IMAGE}$text{'list_ndpiprotocols_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_ndpiprotocols'}", $text{'title'}, "" ); &LoadNdpiProtocols($fw); &showNdpiProtocols(); @@ -21,12 +21,12 @@ print "

"; #============================================================================ sub showNdpiProtocols { - @tds = ( "width=20%", "width=80%" ); - print &ui_columns_start([ "$text{'name'}", "$text{'category'}" ], 100, 0, \@tds); + @tds = ( "width=20%", "width=20%", "width=60%" ); + print &ui_columns_start([ "$text{'name'}", "$text{'category'}", "$text{'flag'}" ], 100, 0, \@tds); my @ndpiprotocols = $fw->GetNdpiProtocolsList(); foreach my $name (@ndpiprotocols) { my %ndpiprotocol = $fw->GetNdpiProtocol($name); - print &ui_columns_row([ "$icons{NDPISERVICE}{IMAGE}$name", "$icons{DESCRIPTION}{IMAGE}$ndpiprotocol{'CATEGORY'}" ], \@tds); + print &ui_columns_row([ "$icons{NDPISERVICE}{IMAGE}$name", "$icons{DESCRIPTION}{IMAGE}$ndpiprotocol{'CATEGORY'}", "$ndpiprotocol{'DPI'}" ], \@tds); } print &ui_columns_end(); } diff --git a/src/turtlefirewall/list_ndpirisks.cgi b/src/turtlefirewall/list_ndpirisks.cgi index 9b53724..3976e7f 100644 --- a/src/turtlefirewall/list_ndpirisks.cgi +++ b/src/turtlefirewall/list_ndpirisks.cgi @@ -3,14 +3,14 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; -&ui_print_header( "$icons{RISK}{IMAGE}$text{'list_ndpirisks_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_ndpirisks'}", $text{'title'}, "" ); &LoadNdpiRisks($fw); &showNdpiRisks(); diff --git a/src/turtlefirewall/list_rawrules.cgi b/src/turtlefirewall/list_rawrules.cgi index b247a0c..bf6898b 100644 --- a/src/turtlefirewall/list_rawrules.cgi +++ b/src/turtlefirewall/list_rawrules.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); -&ui_print_header( "$icons{HELPER}{IMAGE}$text{'list_rawrules_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_rawrules'}", $text{'title'}, "" ); $form = 0; showConntrackPreroute(); @@ -49,8 +49,8 @@ sub showConntrackPreroute { my $nConntrackPreroutes = $fw->GetConntrackPreroutesCount(); + my $idx = $in{idx}; if( $in{table} eq 'conntrackpreroute' ) { - my $idx = $in{idx}; if( $in{down} > 0 || $in{up} > 0 ) { my $newIdx = $idx; if( $in{down} > 0 && $idx > 0 && $idx < $nConntrackPreroutes ) { @@ -71,8 +71,8 @@ sub showConntrackPreroute { my %attr = $fw->GetConntrackPreroute($i); local @cols; if( $attr{'TARGET'} eq '' ) { $attr{'TARGET'} = 'ACCEPT'; } - my $bb = $idx == $i ? '' : ''; # BoldBegin - my $be = $idx == $i ? '' : ''; # BoldEnd + my $bb = $idx == $i && $in{table} eq 'conntrackpreroute' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'conntrackpreroute' ? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd my $href = &ui_link("edit_conntrackpreroute.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); @@ -82,18 +82,17 @@ sub showConntrackPreroute { push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'SRC'}${be}${se}" ); $type = $fw->GetItemType($attr{'DST'}); push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'DST'}${be}${se}" ); - push(@cols, "$icons{SERVICE}{IMAGE}${sb}${bb}$attr{'SERVICE'}/$attr{'PORT'}${be}${se}"); + if( $attr{'PORT'} ne '' ) { + push(@cols, "$icons{SERVICE}{IMAGE}${sb}${bb}$attr{'SERVICE'}/$attr{'PORT'}${be}${se}"); + } else { + push(@cols, "$icons{SERVICE}{IMAGE}${sb}${bb}$attr{'SERVICE'}/all${be}${se}"); + } my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $himage = $attr{'ACTIVE'} eq 'NO' ? $icons{HELPER}{IMAGE} : $icons{HELPER_A}{IMAGE}; push(@cols, "${himage}${sb}${bb}${cb}".($attr{'HELPER'} ne '' ? $attr{'HELPER'} : ' ')."${ce}${be}${se}" ); local $mover; $mover .= "
"; - # if( $i < $nConntrackPreroutes-1 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } if( $i < $nConntrackPreroutes ) { $mover .= ""; } - # if( $i > 2 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } $mover .= "
V     v @@ -112,11 +111,6 @@ sub showConntrackPreroute {    A  
"; push(@cols, $mover); print &ui_checked_columns_row(\@cols, \@tds, "d", $i); @@ -154,8 +148,8 @@ sub showConntrack { my $nConntracks = $fw->GetConntracksCount(); + my $idx = $in{idx}; if( $in{table} eq 'conntrack' ) { - my $idx = $in{idx}; if( $in{down} > 0 || $in{up} > 0 ) { my $newIdx = $idx; if( $in{down} > 0 && $idx > 0 && $idx < $nConntracks ) { @@ -176,8 +170,8 @@ sub showConntrack { my %attr = $fw->GetConntrack($i); local @cols; if( $attr{'TARGET'} eq '' ) { $attr{'TARGET'} = 'ACCEPT'; } - my $bb = $idx == $i ? '' : ''; # BoldBegin - my $be = $idx == $i ? '' : ''; # BoldEnd + my $bb = $idx == $i && $in{table} eq 'conntrack' ? '' : ''; # BoldBegin + my $be = $idx == $i && $in{table} eq 'conntrack' ? '' : ''; # BoldEnd my $sb = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeBegin my $se = $attr{'ACTIVE'} eq 'NO' ? '' : ''; # StrikeEnd my $href = &ui_link("edit_conntrack.cgi?idx=$i","${sb}${bb}${i}${be}${se}"); @@ -187,18 +181,17 @@ sub showConntrack { push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'SRC'}${be}${se}" ); $type = $fw->GetItemType($attr{'DST'}); push(@cols, "$icons{$type}{IMAGE}${sb}${bb}$attr{'DST'}${be}${se}" ); - push(@cols, "$icons{SERVICE}{IMAGE}${sb}${bb}$attr{'SERVICE'}/$attr{'PORT'}${be}${se}"); + if( $attr{'PORT'} ne '' ) { + push(@cols, "$icons{SERVICE}{IMAGE}${sb}${bb}$attr{'SERVICE'}/$attr{'PORT'}${be}${se}"); + } else { + push(@cols, "$icons{SERVICE}{IMAGE}${sb}${bb}$attr{'SERVICE'}/all${be}${se}"); + } my $cb = $sb eq '' ? '' : ''; # ColourBegin my $ce = $se eq '' ? '' : ''; # ColourEnd my $himage = $attr{'ACTIVE'} eq 'NO' ? $icons{HELPER}{IMAGE} : $icons{HELPER_A}{IMAGE}; push(@cols, "${himage}${sb}${bb}${cb}".($attr{'HELPER'} ne '' ? $attr{'HELPER'} : ' ')."${ce}${be}${se}" ); local $mover; $mover .= ""; - # if( $i < $nConntracks-1 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } if( $i < $nConntracks ) { $mover .= ""; } - # if( $i > 2 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } $mover .= "
V     v @@ -217,11 +210,6 @@ sub showConntrack {    A  
"; push(@cols, $mover); print &ui_checked_columns_row(\@cols, \@tds, "d", $i); diff --git a/src/turtlefirewall/list_rules.cgi b/src/turtlefirewall/list_rules.cgi index 0da45ab..a5b29a5 100644 --- a/src/turtlefirewall/list_rules.cgi +++ b/src/turtlefirewall/list_rules.cgi @@ -3,15 +3,15 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); -&ui_print_header( "$icons{RULE}{IMAGE}$text{'list_rules_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_rules'}", $text{'title'}, "" ); &showRule(); @@ -20,6 +20,7 @@ do 'turtlefirewall-lib.pl'; #============================================================================ sub showRule { + print &ui_subheading($icons{RULE}{IMAGE},$text{'rule'}); print &ui_form_start("save_rule.cgi", "post"); @links = ( &select_all_link("d"), &select_invert_link("d"), @@ -63,19 +64,10 @@ sub showRule { if( $in{down} > 0 && $idx > 0 && $idx < $nRules ) { $newIdx = $idx + $in{down}; if( $newIdx > $nRules ) { $newIdx = $nRules; } - - #my %appo = $fw->GetRule($newIdx); - #$fw->AddRuleAttr($newIdx, $fw->GetRule($idx)); - #$fw->AddRuleAttr($idx, %appo); - #$idx=$newIdx; - #$fw->SaveFirewall(); } if( $in{up} > 0 && $idx > 1 && $idx <= $nRules ) { $newIdx = $idx - $in{up}; if( $newIdx < 1 ) { $newIdx = 1; } - #my %appo = $fw->GetRule($newIdx); - #$fw->AddRuleAttr($newIdx, $fw->GetRule($idx)); - #$fw->AddRuleAttr($idx, %appo); } $fw->MoveRule( $idx, $newIdx ); $fw->SaveFirewall(); @@ -176,11 +168,6 @@ sub showRule { push(@cols, "${iimage}${sb}${bb}".($attr{'DESCRIPTION'} ne '' ? $attr{'DESCRIPTION'} : ' ')."${be}${se}" ); local $mover; $mover .= ""; - # if( $i < $nRules-1 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } if( $i < $nRules ) { $mover .= ""; } - # if( $i > 2 ) { - # $mover .= ""; - # } else { - # $mover .= ""; - # } $mover .= "
V     v @@ -199,11 +186,6 @@ sub showRule {    A  
"; push(@cols, $mover); print &ui_checked_columns_row(\@cols, \@tds, "d", $i); diff --git a/src/turtlefirewall/list_services.cgi b/src/turtlefirewall/list_services.cgi index 22556b1..27bb8b5 100644 --- a/src/turtlefirewall/list_services.cgi +++ b/src/turtlefirewall/list_services.cgi @@ -3,14 +3,14 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; -&ui_print_header( "$icons{SERVICE}{IMAGE}$text{'list_services_title'}", $text{'title'}, "" ); +&ui_print_header( "$icons{ICON}{IMAGE}$text{'index_icon_services'}", $text{'title'}, "" ); &LoadServices($fw); &showServices(); diff --git a/src/turtlefirewall/module.info b/src/turtlefirewall/module.info index 832b6e2..4f485d8 100644 --- a/src/turtlefirewall/module.info +++ b/src/turtlefirewall/module.info @@ -1,7 +1,7 @@ os_support=*-linux -version=2.4 +version=2.7 longdesc=Configure a Linux firewall in a simple and fast way. name=turtlefirewall desc=Turtle Firewall category=net -depends=2.201 +depends=2.600 diff --git a/src/turtlefirewall/save_addresslist.cgi b/src/turtlefirewall/save_addresslist.cgi index eae56c4..632aded 100644 --- a/src/turtlefirewall/save_addresslist.cgi +++ b/src/turtlefirewall/save_addresslist.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $addresslist = $in{'addresslist'}; diff --git a/src/turtlefirewall/save_connmark.cgi b/src/turtlefirewall/save_connmark.cgi index b72c4f7..6481a86 100644 --- a/src/turtlefirewall/save_connmark.cgi +++ b/src/turtlefirewall/save_connmark.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; $src =~ s/\0/,/g; my $dst = $in{'dst'}; @@ -71,5 +72,6 @@ if( $in{'delete'} ) { $fw->AddConnmark( $in{'new'} ? 0 : $idx, $src, $dst, $service, $ndpi, $category, $hostnameset, $riskset, $port, $time, $mark, $active ); } +if( $idx ne $newIdx ) { $fw->MoveConnmark( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_manglerules.cgi'.($in{'delete'} ? "?idx=$idx" : '') ); +&redirect( 'list_manglerules.cgi'.($in{'delete'} ? '' : "?table=connmark&idx=$idx") ); diff --git a/src/turtlefirewall/save_connmarkpreroute.cgi b/src/turtlefirewall/save_connmarkpreroute.cgi index 041d649..d3d930e 100644 --- a/src/turtlefirewall/save_connmarkpreroute.cgi +++ b/src/turtlefirewall/save_connmarkpreroute.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; my $dst = $in{'dst'}; my ($service, $port) = &formServiceParse( $in{'servicetype'}, $in{'service2'}, $in{'service3'}, $in{'port'} ); @@ -69,5 +70,6 @@ if( $in{'delete'} ) { $fw->AddConnmarkPreroute( $in{'new'} ? 0 : $idx, $src, $dst, $service, $ndpi, $category, $hostnameset, $riskset, $port, $time, $mark, $active ); } +if( $idx ne $newIdx ) { $fw->MoveConnmarkPreroute( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_manglerules.cgi'.($in{'delete'} ? "?idx=$idx" : '') ); +&redirect( 'list_manglerules.cgi'.($in{'delete'} ? '' : "?table=connmarkpreroute&idx=$idx") ); diff --git a/src/turtlefirewall/save_conntrack.cgi b/src/turtlefirewall/save_conntrack.cgi index d0fad90..d078b99 100644 --- a/src/turtlefirewall/save_conntrack.cgi +++ b/src/turtlefirewall/save_conntrack.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; my $dst = $in{'dst'}; my $service = $in{'service'}; @@ -94,5 +95,6 @@ if( $in{'delete'} ) { $fw->AddConntrack( $in{'new'} ? 0 : $idx, $src, $dst, $service, $port, $helper, $active ); } +if( $idx ne $newIdx ) { $fw->MoveConntrack( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_rawrules.cgi'.($in{'delete'} ? "?idx=$idx" : '') ); +&redirect( 'list_rawrules.cgi'.($in{'delete'} ? '' : "?table=conntrack&idx=$idx") ); diff --git a/src/turtlefirewall/save_conntrackpreroute.cgi b/src/turtlefirewall/save_conntrackpreroute.cgi index 2183bda..bc26a7e 100644 --- a/src/turtlefirewall/save_conntrackpreroute.cgi +++ b/src/turtlefirewall/save_conntrackpreroute.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; my $dst = $in{'dst'}; my $service = $in{'service'}; @@ -94,5 +95,6 @@ if( $in{'delete'} ) { $fw->AddConntrackPreroute( $in{'new'} ? 0 : $idx, $src, $dst, $service, $port, $helper, $active ); } +if( $idx ne $newIdx ) { $fw->MoveConntrackPreroute( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_rawrules.cgi'.($in{'delete'} ? "?idx=$idx" : '') ); +&redirect( 'list_rawrules.cgi'.($in{'delete'} ? '' : "?table=conntrackpreroute&idx=$idx") ); diff --git a/src/turtlefirewall/save_geoip.cgi b/src/turtlefirewall/save_geoip.cgi index b4c338b..2b5f153 100644 --- a/src/turtlefirewall/save_geoip.cgi +++ b/src/turtlefirewall/save_geoip.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $geoip = $in{'geoip'}; diff --git a/src/turtlefirewall/save_group.cgi b/src/turtlefirewall/save_group.cgi index 1155167..bc04660 100644 --- a/src/turtlefirewall/save_group.cgi +++ b/src/turtlefirewall/save_group.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $group = $in{'group'}; diff --git a/src/turtlefirewall/save_host.cgi b/src/turtlefirewall/save_host.cgi index d54ee85..2802afb 100644 --- a/src/turtlefirewall/save_host.cgi +++ b/src/turtlefirewall/save_host.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $host = $in{'host'}; diff --git a/src/turtlefirewall/save_hostnameset.cgi b/src/turtlefirewall/save_hostnameset.cgi index 4cae000..ecb4905 100644 --- a/src/turtlefirewall/save_hostnameset.cgi +++ b/src/turtlefirewall/save_hostnameset.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $hostnameset = $in{'hostnameset'}; diff --git a/src/turtlefirewall/save_ipset.cgi b/src/turtlefirewall/save_ipset.cgi index 63071d1..015e34f 100644 --- a/src/turtlefirewall/save_ipset.cgi +++ b/src/turtlefirewall/save_ipset.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $ipset = $in{'ipset'}; diff --git a/src/turtlefirewall/save_masquerade.cgi b/src/turtlefirewall/save_masquerade.cgi index 60e77ef..281ed35 100644 --- a/src/turtlefirewall/save_masquerade.cgi +++ b/src/turtlefirewall/save_masquerade.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; my $dst = $in{'dst'}; my ($service, $port) = &formServiceParse( $in{'servicetype'}, $in{'service2'}, $in{'service3'}, $in{'port'} ); @@ -57,5 +58,6 @@ if( $in{'delete'} ) { $fw->AddMasquerade( $in{'new'} ? 0 : $idx, $src, $dst, $service, $port, $is_masquerade, $active ); } +if( $idx ne $newIdx ) { $fw->MoveMasquerade( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_nat.cgi' ); +&redirect( 'list_nat.cgi'.($in{'delete'} ? '' : "?table=masquerade&idx=$idx") ); diff --git a/src/turtlefirewall/save_nat.cgi b/src/turtlefirewall/save_nat.cgi index c49613f..e30d834 100644 --- a/src/turtlefirewall/save_nat.cgi +++ b/src/turtlefirewall/save_nat.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $virtual = $in{'virtual'}; my $real = $in{'real'}; my ($service, $port) = &formServiceParse( $in{'servicetype'}, $in{'service2'}, $in{'service3'}, $in{'port'} ); @@ -72,5 +73,6 @@ if( $in{'delete'} ) { } } +if( $idx ne $newIdx ) { $fw->MoveNat( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_nat.cgi' ); +&redirect( 'list_nat.cgi'.($in{'delete'} ? '' : "?table=nat&idx=$idx") ); diff --git a/src/turtlefirewall/save_net.cgi b/src/turtlefirewall/save_net.cgi index 3650b78..0e7aebd 100644 --- a/src/turtlefirewall/save_net.cgi +++ b/src/turtlefirewall/save_net.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $net = $in{'net'}; diff --git a/src/turtlefirewall/save_options.cgi b/src/turtlefirewall/save_options.cgi index 62bc445..27c3d69 100644 --- a/src/turtlefirewall/save_options.cgi +++ b/src/turtlefirewall/save_options.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); if( $in{save} ne '' ) { diff --git a/src/turtlefirewall/save_ratelimit.cgi b/src/turtlefirewall/save_ratelimit.cgi index bbd8b9b..14bd3d6 100644 --- a/src/turtlefirewall/save_ratelimit.cgi +++ b/src/turtlefirewall/save_ratelimit.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $ratelimit = $in{'ratelimit'}; diff --git a/src/turtlefirewall/save_redirect.cgi b/src/turtlefirewall/save_redirect.cgi index 86ef283..38550b0 100644 --- a/src/turtlefirewall/save_redirect.cgi +++ b/src/turtlefirewall/save_redirect.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; my $dst = $in{'dst'}; my ($service, $port) = &formServiceParse( $in{'servicetype'}, $in{'service2'}, $in{'service3'}, $in{'port'} ); @@ -66,5 +67,6 @@ if( $in{'delete'} ) { $fw->AddRedirect( $in{'new'} ? 0 : $idx, $src, $dst, $service, $port, $toport, $is_redirect, $active ); } +if( $idx ne $newIdx ) { $fw->MoveRedirect( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_nat.cgi' ); +&redirect( 'list_nat.cgi'.($in{'delete'} ? '' : "?table=redirect&idx=$idx") ); diff --git a/src/turtlefirewall/save_riskset.cgi b/src/turtlefirewall/save_riskset.cgi index 630c1f5..0136554 100644 --- a/src/turtlefirewall/save_riskset.cgi +++ b/src/turtlefirewall/save_riskset.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $riskset = $in{'riskset'}; diff --git a/src/turtlefirewall/save_rule.cgi b/src/turtlefirewall/save_rule.cgi index 29ea535..cca8d71 100644 --- a/src/turtlefirewall/save_rule.cgi +++ b/src/turtlefirewall/save_rule.cgi @@ -3,15 +3,16 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $idx = $in{'idx'}; +my $newIdx = $in{'newIdx'}; my $src = $in{'src'}; $src =~ s/\0/,/g; my $dst = $in{'dst'}; @@ -72,20 +73,17 @@ if( $in{'delete'} ) { &error( $text{save_rule_error4} ); } - if( $target eq 'ACCEPT' && ($ndpi eq 'all' || $hostnameset ne '' || $riskset ne '') ) { - &error( $text{save_rule_error5} ); - } - if( $target ne 'DROP' && $ratelimit ne '' ) { - &error( $text{save_rule_error6} ); + &error( $text{save_rule_error5} ); } if( $log ne '' && $ratelimit ne '' ) { - &error( $text{save_rule_error7} ); + &error( $text{save_rule_error6} ); } $fw->AddRule( $in{'new'} ? 0 : $idx, $src, $dst, $service, $ndpi, $category, $hostnameset, $riskset, $ratelimit, $port, $time, $target, $active, $log, $description ); } +if( $idx ne $newIdx ) { $fw->MoveRule( $idx, $newIdx ); $idx=$newIdx; } $fw->SaveFirewall(); -&redirect( 'list_rules.cgi'.($in{'delete'} ? "?idx=$idx" : '') ); +&redirect( 'list_rules.cgi'.($in{'delete'} ? '' : "?idx=$idx") ); diff --git a/src/turtlefirewall/save_time.cgi b/src/turtlefirewall/save_time.cgi index 9f64970..02309d3 100644 --- a/src/turtlefirewall/save_time.cgi +++ b/src/turtlefirewall/save_time.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $time = $in{'time'}; diff --git a/src/turtlefirewall/save_timegroup.cgi b/src/turtlefirewall/save_timegroup.cgi index fd271a4..00ce192 100644 --- a/src/turtlefirewall/save_timegroup.cgi +++ b/src/turtlefirewall/save_timegroup.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); my $timegroup = $in{'timegroup'}; diff --git a/src/turtlefirewall/save_zone.cgi b/src/turtlefirewall/save_zone.cgi index 3bd0253..4b43655 100644 --- a/src/turtlefirewall/save_zone.cgi +++ b/src/turtlefirewall/save_zone.cgi @@ -3,12 +3,12 @@ #====================================================================== # Turtle Firewall webmin module # -# Copyright (c) Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== -do 'turtlefirewall-lib.pl'; +require './turtlefirewall-lib.pl'; &ReadParse(); $newzone = $in{'newzone'}; diff --git a/src/turtlefirewall/setup/TurtleFirewall.pm b/src/turtlefirewall/setup/TurtleFirewall.pm index 08e2e27..4924685 100644 --- a/src/turtlefirewall/setup/TurtleFirewall.pm +++ b/src/turtlefirewall/setup/TurtleFirewall.pm @@ -1,27 +1,28 @@ -# TurtleFirewall: Turtle Firewall Library +# Turtle Firewall : Library # -# Software for configuring a Linux firewall (netfilter) +# Software for configuring a linux firewall (netfilter) # # 2001/11/23 13:25:00 # #====================================================================== -# Copyright (c) 2001-2024 Andrea Frigido +# Copyright (c) 2001-2026 Andrea Frigido # You may distribute under the terms of either the GNU General Public # License #====================================================================== package TurtleFirewall; +use strict; +use warnings; use XML::Parser; # Turtle Firewall Version sub Version { - return '2.4'; + return '2.7'; } sub new { - my $this ={}; - #$this->{NOME} = undef; + my $this = {}; $this->{fw} = (); $this->{fwItems} = (); $this->{fwKeys} = (); @@ -40,127 +41,127 @@ sub new { # Public method for get firewall info (after LoadFirewall) sub GetZoneList { my $this = shift; - return sort( keys %{ $this->{fw}{ZONE} } ); + return exists($this->{fw}{ZONE}) ? sort( keys %{ $this->{fw}{ZONE} } ) : (); } sub GetGeoipList { my $this = shift; - return sort( keys %{ $this->{fw}{GEOIP} } ); + return exists($this->{fw}{GEOIP}) ? sort( keys %{ $this->{fw}{GEOIP} } ) : (); } sub GetNetList { my $this = shift; - return sort( keys %{ $this->{fw}{NET} } ); + return exists($this->{fw}{NET}) ? sort( keys %{ $this->{fw}{NET} } ) : (); } sub GetHostList { my $this = shift; - return sort( keys %{ $this->{fw}{HOST} } ); + return exists($this->{fw}{HOST}) ? sort( keys %{ $this->{fw}{HOST} } ) : (); } sub GetTimeList { my $this = shift; - return sort( keys %{ $this->{fw}{TIME} } ); + return exists($this->{fw}{TIME}) ? sort( keys %{ $this->{fw}{TIME} } ) : (); } sub GetGroupList { my $this = shift; - return @{$this->{fwKeys}{GROUP}}; + return exists($this->{fwKeys}{GROUP}) ? sort @{ $this->{fwKeys}{GROUP} } : (); } sub GetTimeGroupList { my $this = shift; - return @{$this->{fwKeys}{TIMEGROUP}}; + return exists($this->{fwKeys}{TIMEGROUP}) ? sort @{$this->{fwKeys}{TIMEGROUP}} : (); } sub GetHostNameSetList { my $this = shift; - return sort( keys %{ $this->{fw}{HOSTNAMESET} } ); + return exists($this->{fw}{HOSTNAMESET}) ? sort( keys %{ $this->{fw}{HOSTNAMESET} } ) : (); } sub GetRiskSetList { my $this = shift; - return sort( keys %{ $this->{fw}{RISKSET} } ); + return exists($this->{fw}{RISKSET}) ? sort( keys %{ $this->{fw}{RISKSET} } ) : (); } sub GetRateLimitList { my $this = shift; - return sort( keys %{ $this->{fw}{RATELIMIT} } ); + return exists($this->{fw}{RATELIMIT}) ? sort( keys %{ $this->{fw}{RATELIMIT} } ) : (); } sub GetAddressListList { my $this = shift; - return sort( keys %{ $this->{fw}{ADDRESSLIST} } ); + return exists($this->{fw}{ADDRESSLIST}) ? sort( keys %{ $this->{fw}{ADDRESSLIST} } ) : (); } sub GetIPSetList { my $this = shift; - return sort( keys %{ $this->{fw}{IPSET} } ); + return exists($this->{fw}{IPSET}) ? sort( keys %{ $this->{fw}{IPSET} } ) : (); } sub GetZone { my ($this,$name) = @_; - return %{ $this->{fw}{ZONE}{$name} }; + return exists($this->{fw}{ZONE}{$name}) ? %{ $this->{fw}{ZONE}{$name} } : (); } sub GetGeoip { my ($this,$name) = @_; - return %{ $this->{fw}{GEOIP}{$name} }; + return exists($this->{fw}{GEOIP}{$name}) ? %{ $this->{fw}{GEOIP}{$name} } : (); } sub GetNet { my ($this,$name) = @_; - return %{ $this->{fw}{NET}{$name} }; + return exists($this->{fw}{NET}{$name}) ? %{ $this->{fw}{NET}{$name} } : (); } sub GetHost { my ($this,$name) = @_; - return %{ $this->{fw}{HOST}{$name} }; + return exists($this->{fw}{HOST}{$name}) ? %{ $this->{fw}{HOST}{$name} } : (); } sub GetTime { my ($this,$name) = @_; - return %{ $this->{fw}{TIME}{$name} }; + return exists($this->{fw}{TIME}{$name}) ? %{ $this->{fw}{TIME}{$name} } : (); } sub GetGroup { my ($this,$name) = @_; - return %{ $this->{fw}{GROUP}{$name} }; + return exists($this->{fw}{GROUP}{$name}) ? %{ $this->{fw}{GROUP}{$name} } : (); } sub GetTimeGroup { my ($this,$name) = @_; - return %{ $this->{fw}{TIMEGROUP}{$name} }; + return exists($this->{fw}{TIMEGROUP}{$name}) ? %{ $this->{fw}{TIMEGROUP}{$name} } : (); } sub GetHostNameSet { my ($this,$name) = @_; - return %{ $this->{fw}{HOSTNAMESET}{$name} }; + return exists($this->{fw}{HOSTNAMESET}{$name}) ? %{ $this->{fw}{HOSTNAMESET}{$name} } : (); } sub GetRiskSet { my ($this,$name) = @_; - return %{ $this->{fw}{RISKSET}{$name} }; + return exists($this->{fw}{RISKSET}{$name}) ? %{ $this->{fw}{RISKSET}{$name} } : (); } sub GetRateLimit { my ($this,$name) = @_; - return %{ $this->{fw}{RATELIMIT}{$name} }; + return exists($this->{fw}{RATELIMIT}{$name}) ? %{ $this->{fw}{RATELIMIT}{$name} } : (); } sub GetAddressList { my ($this,$name) = @_; - return %{ $this->{fw}{ADDRESSLIST}{$name} }; + return exists($this->{fw}{ADDRESSLIST}{$name}) ? %{ $this->{fw}{ADDRESSLIST}{$name} } : (); } sub GetIPSet { my ($this,$name) = @_; - return %{ $this->{fw}{IPSET}{$name} }; + return exists($this->{fw}{IPSET}{$name}) ? %{ $this->{fw}{IPSET}{$name} } : (); } sub GetAllItemsList { my $this = shift; - return sort( keys %{ $this->{fwItems} } ); + return exists($this->{fwItems}) ? sort( keys %{ $this->{fwItems} } ) : (); } # GetItemsAllowToGroup( group ) @@ -170,26 +171,28 @@ sub GetItemsAllowToGroup { my $group = shift; my @items = (); push @items, 'FIREWALL'; - push @items, @{$this->{fwKeys}{ZONE}}; - push @items, @{$this->{fwKeys}{NET}}; - push @items, @{$this->{fwKeys}{HOST}}; - push @items, @{$this->{fwKeys}{GEOIP}}; - push @items, @{$this->{fwKeys}{IPSET}}; - foreach my $g ( @{$this->{fwKeys}{GROUP}} ) { - if( $g eq $group ) { - last; + push @items, exists($this->{fwKeys}{ZONE}) ? @{$this->{fwKeys}{ZONE}} : (); + push @items, exists($this->{fwKeys}{NET}) ? @{$this->{fwKeys}{NET}} : (); + push @items, exists($this->{fwKeys}{HOST}) ? @{$this->{fwKeys}{HOST}} : (); + push @items, exists($this->{fwKeys}{GEOIP}) ? @{$this->{fwKeys}{GEOIP}} : (); + push @items, exists($this->{fwKeys}{IPSET}) ? @{$this->{fwKeys}{IPSET}} : (); + if( exists($this->{fwKeys}{GROUP}) ) { + foreach my $g ( @{$this->{fwKeys}{GROUP}} ) { + if( $g eq $group ) { + last; + } + push @items, $g; } - push @items, $g; } - return @items; + return sort @items; } sub GetItemsAllowToTimeGroup { my $this = shift; my $timegroup = shift; my @items = (); - push @items, @{$this->{fwKeys}{TIME}}; - return @items; + push @items, exists($this->{fwKeys}{TIME}) ? @{$this->{fwKeys}{TIME}} : (); + return sort @items; } sub GetServicesList { @@ -242,7 +245,6 @@ sub GetMasqueradesCount { } sub GetMasquerade { - # param n = id of masquerade rule (1 .. MasqueradeCount) my ($this,$n) = @_; return %{ $this->{fw}{MASQUERADE}[$n-1] }; } @@ -435,7 +437,7 @@ sub AddZone { # AddMasquerade( $idx, $zone, $active ) if $idx==0 then add new Masquerade sub AddMasquerade { my ($this, $idx, $src, $dst, $service, $port, $masquerade, $active ) = @_; - + my %attr = ( 'SRC'=>$src, 'DST'=>$dst, 'SERVICE'=>$service); if( $port ne '' ) { $attr{PORT} = $port; } if( ! $masquerade ) { $attr{MASQUERADE} = 'NO'; } @@ -454,6 +456,13 @@ sub AddMasqueradeAttr { } } +sub MoveMasquerade { + my ($this, $idxSrc, $idxDst) = @_; + my %attr = %{$this->{fw}{MASQUERADE}[$idxSrc-1]}; + splice @{$this->{fw}{MASQUERADE}}, $idxSrc-1, 1; + splice @{$this->{fw}{MASQUERADE}}, $idxDst-1, 0, \%attr; +} + # AddNat( $idx, $virtual, $real, $service, $port, $toport, $active ) if $idx==0 then add new Masquerade sub AddNat { my ($this, $idx, $virtual, $real, $service, $port, $toport, $active) = @_; @@ -476,6 +485,13 @@ sub AddNatAttr { } } +sub MoveNat { + my ($this, $idxSrc, $idxDst) = @_; + my %attr = %{$this->{fw}{NAT}[$idxSrc-1]}; + splice @{$this->{fw}{NAT}}, $idxSrc-1, 1; + splice @{$this->{fw}{NAT}}, $idxDst-1, 0, \%attr; +} + # AddRedirect( $idx, $src, $dst, $service, $port, $toport, $active ); sub AddRedirect { my ($this, $idx, $src, $dst, $service, $port, $toport, $redirect, $active ) = @_; @@ -498,6 +514,13 @@ sub AddRedirectAttr { } } +sub MoveRedirect { + my ($this, $idxSrc, $idxDst) = @_; + my %attr = %{$this->{fw}{REDIRECT}[$idxSrc-1]}; + splice @{$this->{fw}{REDIRECT}}, $idxSrc-1, 1; + splice @{$this->{fw}{REDIRECT}}, $idxDst-1, 0, \%attr; +} + # AddRule( $idx, $src, $dst, $service, $ndpi, $category, $hostnameset, $riskset, $ratelimit, $port, $time, $target, $active, $log, $description ); sub AddRule { my ($this, $idx, $src, $dst, $service, $ndpi, $category, $hostnameset, $riskset, $ratelimit, $port, $time, $target, $active, $log, $description ) = @_; @@ -812,7 +835,7 @@ sub DeleteItem { last; } } - + if( !$found ) { delete $this->{fw}{$type}{$name}; delete $this->{fwItems}{$name}; @@ -837,7 +860,7 @@ sub RenameItem { # An Item with this name exists return 0; } else { - $type = $this->{fwItems}{$oldname}; + my $type = $this->{fwItems}{$oldname}; %{$this->{fw}{$type}{$newname}} = %{$this->{fw}{$type}{$oldname}}; $this->{fw}{$type}{$newname}{NAME} = $newname; $this->{fwItems}{$newname} = $type; @@ -851,22 +874,22 @@ sub RenameItem { # If it's a zone, I need to change all items that use this zone. if( $type eq 'ZONE' ) { - foreach $k (@{$this->{fwKeys}{HOST}}) { + foreach my $k (@{$this->{fwKeys}{HOST}}) { if( $this->{fw}{HOST}{$k}{ZONE} eq $oldname ) { $this->{fw}{HOST}{$k}{ZONE} = $newname; } } - foreach $k (@{$this->{fwKeys}{NET}}) { + foreach my $k (@{$this->{fwKeys}{NET}}) { if( $this->{fw}{NET}{$k}{ZONE} eq $oldname ) { $this->{fw}{NET}{$k}{ZONE} = $newname; } } - foreach $k (@{$this->{fwKeys}{GEOIP}}) { + foreach my $k (@{$this->{fwKeys}{GEOIP}}) { if( $this->{fw}{GEOIP}{$k}{ZONE} eq $oldname ) { $this->{fw}{GEOIP}{$k}{ZONE} = $newname; } } - foreach $k (@{$this->{fwKeys}{IPSET}}) { + foreach my $k (@{$this->{fwKeys}{IPSET}}) { if( $this->{fw}{IPSET}{$k}{ZONE} eq $oldname ) { $this->{fw}{IPSET}{$k}{ZONE} = $newname; } @@ -875,7 +898,7 @@ sub RenameItem { # If it's an addresslist, I need to change all ipsets that use this addresslist. if( $type eq 'ADDRESSLIST' ) { - foreach $k (@{$this->{fwKeys}{IPSET}}) { + foreach my $k (@{$this->{fwKeys}{IPSET}}) { if( $this->{fw}{IPSET}{$k}{IP} eq $oldname ) { $this->{fw}{IPSET}{$k}{IP} = $newname; } @@ -903,7 +926,7 @@ sub RenameItem { # Change item name in all rules foreach my $ruletype ('RULE','CONNMARKPREROUTE','CONNMARK','CONNTRACKPREROUTE','CONNTRACK','NAT','MASQUERADE','REDIRECT') { for( my $i=0; $i<=$#{$this->{fw}{$ruletype}}; $i++ ) { - foreach $item ('SRC','DST','ZONE','VIRTUAL','REAL','TIME','HOSTNAMESET','RISKSET','RATELIMIT') { + foreach my $item ('SRC','DST','ZONE','VIRTUAL','REAL','TIME','HOSTNAMESET','RISKSET','RATELIMIT') { my @item_list = split( /,/, $this->{fw}{$ruletype}[$i]{$item} ); if( grep( /^$oldname$/, @item_list ) ) { s/^$oldname$/$newname/ for @item_list; @@ -926,25 +949,25 @@ sub GetItemReferences { my %references = (); if( $type eq 'ZONE' ) { - foreach $k (@{$this->{fwKeys}{HOST}}) { + foreach my $k (@{$this->{fwKeys}{HOST}}) { if( $this->{fw}{HOST}{$k}{ZONE} eq $item ) { $references{$k} = 'HOST'; } } - foreach $k (@{$this->{fwKeys}{NET}}) { + foreach my $k (@{$this->{fwKeys}{NET}}) { if( $this->{fw}{NET}{$k}{ZONE} eq $item ) { $references{$k} = 'NET'; } } - foreach $k (@{$this->{fwKeys}{GEOIP}}) { + foreach my $k (@{$this->{fwKeys}{GEOIP}}) { if( $this->{fw}{GEOIP}{$k}{ZONE} eq $item ) { $references{$k} = 'GEOIP'; } } - foreach $k (@{$this->{fwKeys}{IPSET}}) { + foreach my $k (@{$this->{fwKeys}{IPSET}}) { if( $this->{fw}{IPSET}{$k}{ZONE} eq $item ) { $references{$k} = 'IPSET'; } @@ -952,7 +975,7 @@ sub GetItemReferences { } if( $type eq 'ADDRESSLIST' ) { - foreach $k (@{$this->{fwKeys}{IPSET}}) { + foreach my $k (@{$this->{fwKeys}{IPSET}}) { if( $this->{fw}{IPSET}{$k}{IP} eq $item ) { $references{$k} = 'IPSET'; } @@ -977,10 +1000,10 @@ sub GetItemReferences { foreach my $ruletype ('RULE','CONNMARKPREROUTE','CONNMARK','CONNTRACKPREROUTE','CONNTRACK','NAT','MASQUERADE','REDIRECT') { for( my $i=0; $i<=$#{$this->{fw}{$ruletype}}; $i++ ) { - foreach $ruleitem ('SRC','DST','ZONE','VIRTUAL','REAL','TIME','HOSTNAMESET','RISKSET','RATELIMIT') { + foreach my $ruleitem ('SRC','DST','ZONE','VIRTUAL','REAL','TIME','HOSTNAMESET','RISKSET','RATELIMIT') { my @ruleitem_list = split( /,/, $this->{fw}{$ruletype}[$i]{$ruleitem} ); if( grep( /^$item$/, @ruleitem_list ) ) { - $references{"${ruleitem} ${i}"} = $ruletype; + $references{"$ruleitem $i $ruletype"} = $ruletype; } } } @@ -1134,9 +1157,9 @@ sub LoadFirewall { my $name = uc($tree[$i]); if ($name eq 'FIREWALL') { my @list = @{$tree[$i+1]}; - my %attr = shift @list; + my %attr = %{shift @list}; - # Loop over second-level tags (hosts, groups, rules ecc.) + # Loop over second-level tags (hosts, groups, rules etc.) for( my $j=0; $j<=$#list; $j+=2 ) { my $name2 = uc($list[$j]); if( $name2 eq 'ZONE' ) { $this->_LoadFirewallItem( 'ZONE', @{$list[$j+1]} ); } @@ -1174,9 +1197,10 @@ sub _LoadFirewallItem { my %attrs = upperKeys( %{shift @list} ); my $name = $attrs{'NAME'}; - if( $this->{fwItems}{$name} ne '' ) { - print STDERR qq~Error: "$name" item is already present.\n~; + if( defined($this->{fwItems}{$name}) && $this->{fwItems}{$name} ne '' ) { + print STDERR "Error: $name item is already present.\n"; } + $this->{fwItems}{$name} = $type; push @{$this->{fwKeys}{$type}}, $name; %{$this->{fw}{$type}{$name}} = %attrs; @@ -1215,9 +1239,8 @@ sub _LoadFirewallNat { my $this = shift; my $type = shift; my @list = @_; - #my $name = $list[$i]; my %attrs = upperKeys( %{shift @list} ); - + ### # Backward compatibility with TurtleFirewall < 1.29 configuration file if( $type eq 'MASQUERADE' ) { @@ -1229,7 +1252,7 @@ sub _LoadFirewallNat { $attrs{SERVICE} = 'all'; } } - + %{$this->{fw}{$type}[$#{$this->{fw}{$type}}+1]} = %attrs; } @@ -1241,14 +1264,14 @@ sub _LoadFirewallRule { my @srcs = split(/,/,$attrs{'SRC'}); foreach my $src (@srcs) { - if( $this->{fwItems}{$src} eq '' && $src ne '*' ) { + if( defined($this->{fwItems}{$src}) && $this->{fwItems}{$src} eq '' && $src ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{RULE}}+2)." has an invalid source item ($src).\n"; } } my @dsts = split(/,/,$attrs{'DST'}); foreach my $dst (@dsts) { - if( $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { + if( defined($this->{fwItems}{$dst}) && $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{RULE}}+2)." has an invalid destination item ($dst).\n"; } } @@ -1263,12 +1286,12 @@ sub _LoadFirewallConnmarkPreroute { my %attrs = upperKeys( %{shift @list} ); my $src = $attrs{'SRC'}; - if( $this->{fwItems}{$src} eq '' && $src ne '*' ) { + if( defined($this->{fwItems}{$src}) && $this->{fwItems}{$src} eq '' && $src ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNMARKPREROUTE}}+2)." has an invalid source item ($src).\n"; } my $dst = $attrs{'DST'}; - if( $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { + if( defined($this->{fwItems}{$dst}) && $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNMARKPREROUTE}}+2)." has an invalid destination item ($dst).\n"; } @@ -1283,14 +1306,14 @@ sub _LoadFirewallConnmark { my @srcs = split(/,/,$attrs{'SRC'}); foreach my $src (@srcs) { - if( $this->{fwItems}{$src} eq '' && $src ne '*' ) { + if( defined($this->{fwItems}{$src}) && $this->{fwItems}{$src} eq '' && $src ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNMARK}}+2)." has an invalid source item ($src).\n"; } } my @dsts = split(/,/,$attrs{'DST'}); foreach my $dst (@dsts) { - if( $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { + if( defined($this->{fwItems}{$dst}) && $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNMARK}}+2)." has an invalid destination item ($dst).\n"; } } @@ -1305,12 +1328,12 @@ sub _LoadFirewallConntrackPreroute { my %attrs = upperKeys( %{shift @list} ); my $src = $attrs{'SRC'}; - if( $this->{fwItems}{$src} eq '' && $src ne '*' ) { + if( defined($this->{fwItems}{$src}) && $this->{fwItems}{$src} eq '' && $src ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNTRACKPREROUTE}}+2)." has an invalid source item ($src).\n"; } my $dst = $attrs{'DST'}; - if( $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { + if( defined($this->{fwItems}{$dst}) && $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNTRACKPREROUTE}}+2)." has an invalid destination item ($dst).\n"; } @@ -1324,12 +1347,12 @@ sub _LoadFirewallConntrack { my %attrs = upperKeys( %{shift @list} ); my $src = $attrs{'SRC'}; - if( $this->{fwItems}{$src} eq '' && $src ne '*' ) { + if( defined($this->{fwItems}{$src}) && $this->{fwItems}{$src} eq '' && $src ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNTRACK}}+2)." has an invalid source item ($src).\n"; } my $dst = $attrs{'DST'}; - if( $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { + if( defined($this->{fwItems}{$dst}) && $this->{fwItems}{$dst} eq '' && $dst ne '*' ) { print STDERR "Error: rule number ".($#{$this->{fw}{CONNTRACK}}+2)." has an invalid destination item ($dst).\n"; } @@ -1337,12 +1360,6 @@ sub _LoadFirewallConntrack { } # Internal method for add OPTIONS to firewall object -# -# XML: -# -# \n"; $xml .= "\n"; - foreach my $k (keys %{$fw{'ZONE'}}) { - if( $k ne 'FIREWALL' ) { - $xml .= $this->attr2xml( 'zone', %{$fw{'ZONE'}{$k}} ); + if( exists($fw{'ZONE'}) ) { + foreach my $k (keys %{$fw{'ZONE'}}) { + if( $k ne 'FIREWALL' ) { + $xml .= $this->attr2xml( 'zone', %{$fw{'ZONE'}{$k}} ); + } } + $xml .= "\n"; } - $xml .= "\n"; - foreach my $k (keys %{$fw{'NET'}}) { - $xml .= $this->attr2xml( 'net', %{$fw{'NET'}{$k}} ); + if( exists($fw{'NET'}) ) { + foreach my $k (keys %{$fw{'NET'}}) { + $xml .= $this->attr2xml( 'net', %{$fw{'NET'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'NET'}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'HOST'}}) { - $xml .= $this->attr2xml( 'host', %{$fw{'HOST'}{$k}} ); + if( exists($fw{'HOST'}) ) { + foreach my $k (keys %{$fw{'HOST'}}) { + $xml .= $this->attr2xml( 'host', %{$fw{'HOST'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'HOST'}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'GEOIP'}}) { - $xml .= $this->attr2xml( 'geoip', %{$fw{'GEOIP'}{$k}} ); + if( exists($fw{'GEOIP'}) ) { + foreach my $k (keys %{$fw{'GEOIP'}}) { + $xml .= $this->attr2xml( 'geoip', %{$fw{'GEOIP'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'GEOIP'}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'ADDRESSLIST'}}) { - $xml .= $this->attr2xml( 'addresslist', %{$fw{'ADDRESSLIST'}{$k}} ); + if( exists($fw{'ADDRESSLIST'}) ) { + foreach my $k (keys %{$fw{'ADDRESSLIST'}}) { + $xml .= $this->attr2xml( 'addresslist', %{$fw{'ADDRESSLIST'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'ADDRESSLIST'}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'IPSET'}}) { - $xml .= $this->attr2xml( 'ipset', %{$fw{'IPSET'}{$k}} ); + if( exists($fw{'IPSET'}) ) { + foreach my $k (keys %{$fw{'IPSET'}}) { + $xml .= $this->attr2xml( 'ipset', %{$fw{'IPSET'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'IPSET'}} ) { $xml .= "\n"; } - foreach my $k (@{$this->{fwKeys}{GROUP}}) { - $xml .= "_clean($fw{'GROUP'}{$k}{DESCRIPTION})."\">\n"; - foreach my $item (@{$fw{'GROUP'}{$k}{ITEMS}}) { - $xml .= "\t_clean($item)."\"/>\n"; + if( exists($this->{fwKeys}{GROUP}) ) { + foreach my $k (@{$this->{fwKeys}{GROUP}}) { + $xml .= "_clean($fw{'GROUP'}{$k}{DESCRIPTION})."\">\n"; + foreach my $item (@{$fw{'GROUP'}{$k}{ITEMS}}) { + $xml .= "\t_clean($item)."\"/>\n"; + } + $xml .= "\n"; } - $xml .= "\n"; + $xml .= "\n"; } - if( @{$this->{fwKeys}{GROUP}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'TIME'}}) { - $xml .= $this->attr2xml( 'time', %{$fw{'TIME'}{$k}} ); + if( exists($fw{'TIME'}) ) { + foreach my $k (keys %{$fw{'TIME'}}) { + $xml .= $this->attr2xml( 'time', %{$fw{'TIME'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'TIME'}} ) { $xml .= "\n"; } - foreach my $k (@{$this->{fwKeys}{TIMEGROUP}}) { - $xml .= "_clean($fw{'TIMEGROUP'}{$k}{DESCRIPTION})."\">\n"; - foreach my $item (@{$fw{'TIMEGROUP'}{$k}{ITEMS}}) { - $xml .= "\t_clean($item)."\"/>\n"; + if( exists($this->{fwKeys}{TIMEGROUP}) ) { + foreach my $k (@{$this->{fwKeys}{TIMEGROUP}}) { + $xml .= "_clean($fw{'TIMEGROUP'}{$k}{DESCRIPTION})."\">\n"; + foreach my $item (@{$fw{'TIMEGROUP'}{$k}{ITEMS}}) { + $xml .= "\t_clean($item)."\"/>\n"; + } + $xml .= "\n"; } - $xml .= "\n"; + $xml .= "\n"; } - if( @{$this->{fwKeys}{TIMEGROUP}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'HOSTNAMESET'}}) { - $xml .= $this->attr2xml( 'hostnameset', %{$fw{'HOSTNAMESET'}{$k}} ); + if( exists($fw{'HOSTNAMESET'}) ) { + foreach my $k (keys %{$fw{'HOSTNAMESET'}}) { + $xml .= $this->attr2xml( 'hostnameset', %{$fw{'HOSTNAMESET'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'HOSTNAMESET'}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'RISKSET'}}) { - $xml .= $this->attr2xml( 'riskset', %{$fw{'RISKSET'}{$k}} ); + if( exists($fw{'RISKSET'}) ) { + foreach my $k (keys %{$fw{'RISKSET'}}) { + $xml .= $this->attr2xml( 'riskset', %{$fw{'RISKSET'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'RISKSET'}} ) { $xml .= "\n"; } - foreach my $k (keys %{$fw{'RATELIMIT'}}) { - $xml .= $this->attr2xml( 'ratelimit', %{$fw{'RATELIMIT'}{$k}} ); + if( exists($fw{'RATELIMIT'}) ) { + foreach my $k (keys %{$fw{'RATELIMIT'}}) { + $xml .= $this->attr2xml( 'ratelimit', %{$fw{'RATELIMIT'}{$k}} ); + } + $xml .= "\n"; } - if( %{$fw{'RATELIMIT'}} ) { $xml .= "\n"; } - my @nats = @{$fw{'NAT'}}; - for my $i (0..$#nats) { - $xml .= $this->attr2xml( 'nat', %{$nats[$i]} ); + if( exists($fw{'NAT'}) ) { + my @nats = @{$fw{'NAT'}}; + for my $i (0..$#nats) { + $xml .= $this->attr2xml( 'nat', %{$nats[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'NAT'}} ) { $xml .= "\n"; } - my @masq = @{$fw{'MASQUERADE'}}; - for my $i (0..$#masq) { - $xml .= $this->attr2xml( 'masquerade', %{$masq[$i]} ); + if( exists($fw{'MASQUERADE'}) ) { + my @masq = @{$fw{'MASQUERADE'}}; + for my $i (0..$#masq) { + $xml .= $this->attr2xml( 'masquerade', %{$masq[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'MASQUERADE'}} ) { $xml .= "\n"; } - my @redirectlist = @{$fw{'REDIRECT'}}; - for my $i (0..$#redirectlist) { - $xml .= $this->attr2xml( 'redirect', %{$redirectlist[$i]} ); + if( exists($fw{'REDIRECT'}) ) { + my @redirectlist = @{$fw{'REDIRECT'}}; + for my $i (0..$#redirectlist) { + $xml .= $this->attr2xml( 'redirect', %{$redirectlist[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'REDIRECT'}} ) { $xml .= "\n"; } - my @conntrackpreroutes = @{$fw{'CONNTRACKPREROUTE'}}; - for my $i (0..$#conntrackpreroutes) { - $xml .= $this->attr2xml( 'conntrackpreroute', %{$conntrackpreroutes[$i]} ); + if( exists($fw{'CONNTRACKPREROUTE'}) ) { + my @conntrackpreroutes = @{$fw{'CONNTRACKPREROUTE'}}; + for my $i (0..$#conntrackpreroutes) { + $xml .= $this->attr2xml( 'conntrackpreroute', %{$conntrackpreroutes[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'CONNTRACKPREROUTE'}} ) { $xml .= "\n"; } - my @conntracks = @{$fw{'CONNTRACK'}}; - for my $i (0..$#conntracks) { - $xml .= $this->attr2xml( 'conntrack', %{$conntracks[$i]} ); + if( exists($fw{'CONNTRACK'}) ) { + my @conntracks = @{$fw{'CONNTRACK'}}; + for my $i (0..$#conntracks) { + $xml .= $this->attr2xml( 'conntrack', %{$conntracks[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'CONNTRACK'}} ) { $xml .= "\n"; } - my @connmarkpreroutes = @{$fw{'CONNMARKPREROUTE'}}; - for my $i (0..$#connmarkpreroutes) { - $xml .= $this->attr2xml( 'connmarkpreroute', %{$connmarkpreroutes[$i]} ); + if( exists($fw{'CONNMARKPREROUTE'}) ) { + my @connmarkpreroutes = @{$fw{'CONNMARKPREROUTE'}}; + for my $i (0..$#connmarkpreroutes) { + $xml .= $this->attr2xml( 'connmarkpreroute', %{$connmarkpreroutes[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'CONNMARKPREROUTE'}} ) { $xml .= "\n"; } - my @connmarks = @{$fw{'CONNMARK'}}; - for my $i (0..$#connmarks) { - $xml .= $this->attr2xml( 'connmark', %{$connmarks[$i]} ); + if( exists($fw{'CONNMARK'}) ) { + my @connmarks = @{$fw{'CONNMARK'}}; + for my $i (0..$#connmarks) { + $xml .= $this->attr2xml( 'connmark', %{$connmarks[$i]} ); + } + $xml .= "\n"; } - if( @{$fw{'CONNMARK'}} ) { $xml .= "\n"; } - my @rules = @{$fw{'RULE'}}; - for my $i (0..$#rules) { - $xml .= $this->attr2xml( 'rule', %{$rules[$i]} ); + if( exists($fw{'RULE'}) ) { + my @rules = @{$fw{'RULE'}}; + for my $i (0..$#rules) { + $xml .= $this->attr2xml( 'rule', %{$rules[$i]} ); + } + $xml .= "\n"; } - $xml .= "\n"; $xml .= "\n"; @@ -1692,14 +1749,14 @@ sub attr2xml { return $appo; } -# Translate """ to "'", "<" to "<" and ">" to ">" and "&" to "&" +# Translate """ to "'", "&" to "&", "<" to "<" and ">" to ">" sub _clean { my $this = shift; my $s = shift; $s =~ s/\"/\'/g; + $s =~ s/\&/&/g; $s =~ s/\/>/g; - $s =~ s/\&/&/g; return $s; } @@ -1714,13 +1771,11 @@ sub checkName { sub GetStatus { my $iptables = qx{iptables -L -n}; return $iptables =~ /Chain BACK/g; - #my $nftables = qx{nft list table ip filter 2>&1}; - #return $nftables =~ /chain BACK/g } sub startFirewall { my $this = shift; - + # PreLoad modules print "nftables_module: on\n"; $this->command('modprobe nf_tables', '/dev/null'); @@ -1775,16 +1830,16 @@ sub startFirewall { # PreLoad module for nDPI print "ndpi_module: on\n"; - $this->command('modprobe xt_ndpi ndpi_enable_flow=1 ndpi_flow_opt=cCFVR', '/dev/null'); - + $this->command('modprobe xt_ndpi ndpi_enable_flow=1 ndpi_flow_opt=cFR', '/dev/null'); + # Enable IP forwarding $this->command('echo "1"', '/proc/sys/net/ipv4/ip_forward'); - - if( $this->{fw}{OPTION}{rp_filter} eq 'unchange' ) { + + if( !defined($this->{fw}{OPTION}{rp_filter}) || $this->{fw}{OPTION}{rp_filter} eq 'unchange' ) { print "rp_filter: unchange\n"; } else { my $flag; - if( $this->{fw}{OPTION}{rp_filter} eq 'off' ) { + if( defined($this->{fw}{OPTION}{rp_filter}) && $this->{fw}{OPTION}{rp_filter} eq 'off' ) { print "rp_filter: off\n"; $flag = 0; } else { @@ -1794,11 +1849,11 @@ sub startFirewall { $this->command( "for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo $flag > \$f; done" ); } - if( $this->{fw}{OPTION}{log_martians} eq 'unchange' ) { + if( !defined($this->{fw}{OPTION}{log_martians}) || $this->{fw}{OPTION}{log_martians} eq 'unchange' ) { print "log_martians: unchange\n"; } else { my $flag; - if( $this->{fw}{OPTION}{log_martians} eq 'off' ) { + if( defined($this->{fw}{OPTION}{log_martians}) && $this->{fw}{OPTION}{log_martians} eq 'off' ) { print "log_martians: off\n"; $flag = 0; } else { @@ -1807,12 +1862,12 @@ sub startFirewall { } $this->command( "for f in /proc/sys/net/ipv4/conf/*/log_martians; do echo $flag > \$f; done" ); } - + # I want all icmp_echo_ignore_all set to off. Turtle Firewall uses iptables # rules for drop or allow icmp echo packets. Andrea Frigido 2004-07-17 $this->command( 'echo "1"', '/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts' ); $this->command( 'echo "0"', '/proc/sys/net/ipv4/icmp_echo_ignore_all' ); - + # Disable tcp_ecn flag. $this->command( 'echo 0', '/proc/sys/net/ipv4/tcp_ecn' ); @@ -1828,9 +1883,9 @@ sub startFirewall { # Enable bad error message protection. $this->command( 'echo 1', '/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses' ); - + # Other options - if( $this->{fw}{OPTION}{nf_conntrack_max} > 0 ) { + if( defined($this->{fw}{OPTION}{nf_conntrack_max}) && $this->{fw}{OPTION}{nf_conntrack_max} > 0 ) { open( FILE, ">/proc/sys/net/netfilter/nf_conntrack_max" ); print FILE $this->{fw}{OPTION}{nf_conntrack_max}; close FILE; @@ -1838,22 +1893,17 @@ sub startFirewall { } # Ensure ipset item present for IP Blacklist - if( $this->{fw}{OPTION}{drop_ip_blacklist} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_ip_blacklist}) || $this->{fw}{OPTION}{drop_ip_blacklist} ne 'off' ) { $this->command('/usr/lib/turtlefirewall/ip_blacklist -I', '/dev/null'); } # Ensure dpi item present for Domain Blacklist - if( $this->{fw}{OPTION}{drop_domain_blacklist} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_domain_blacklist}) || $this->{fw}{OPTION}{drop_domain_blacklist} ne 'off' ) { $this->command('/usr/lib/turtlefirewall/domain_blacklist -I', '/dev/null'); } - # Ensure dpi item present for JA3 Blacklist - if( $this->{fw}{OPTION}{drop_ja3_blacklist} ne 'off' ) { - $this->command('/usr/lib/turtlefirewall/ja3_blacklist -I', '/dev/null'); - } - # Ensure dpi item present for SHA1 Blacklist - if( $this->{fw}{OPTION}{drop_sha1_blacklist} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_sha1_blacklist}) || $this->{fw}{OPTION}{drop_sha1_blacklist} ne 'off' ) { $this->command('/usr/lib/turtlefirewall/sha1_blacklist -I', '/dev/null'); } @@ -1864,7 +1914,7 @@ sub startFirewall { my @item_list = (); push(@item_list, split( /,/, $this->{fw}{RULE}[$i]{SRC} ) ); push(@item_list, split( /,/, $this->{fw}{RULE}[$i]{DST} ) ); - if( grep( /^$s$/, @item_list ) && $this->{fw}{RULE}[$i]{ACTIVE} ne 'NO') { + if( grep( /^$s$/, @item_list ) && !$this->{fw}{RULE}[$i]{ACTIVE} ) { my $addresslist_file = $this->{fw}{ADDRESSLIST}{$ipset{'IP'}}{FILE}; my $addresslist_type = $this->{fw}{ADDRESSLIST}{$ipset{'IP'}}{TYPE}; if( ! -e $addresslist_file ) { @@ -1878,35 +1928,30 @@ sub startFirewall { } } + # Restore IPtables Rules my $rules = $this->getIptablesRules(); - - my $use_iptables_restore = 1; - - if( $use_iptables_restore ) { - umask 0077; - open FILE, ">/etc/turtlefirewall/iptables.dat"; - print FILE $rules; - close FILE; - if( -x '/usr/sbin/iptables-nft-restore' ) { - print "run iptables-nft-restore\n"; - $this->command('cat /etc/turtlefirewall/iptables.dat | /usr/sbin/iptables-nft-restore'); - } elsif( -x '/usr/sbin/iptables-restore' ) { - print "run iptables-restore\n"; - $this->command('cat /etc/turtlefirewall/iptables.dat | /usr/sbin/iptables-restore'); - } else { - print STDERR "Error: iptables-restore needed\n"; - } - # doesn't unlink, for debugging - #unlink "/etc/turtlefirewall/iptables.dat"; - } else { - $this->iptables_restore_emu( $rules ); + + umask 0077; + open FILE, ">/etc/turtlefirewall/iptables.dat"; + print FILE $rules; + close FILE; + if( -x '/usr/sbin/iptables-nft-restore' ) { + print "run iptables-nft-restore\n"; + $this->command('cat /etc/turtlefirewall/iptables.dat | /usr/sbin/iptables-nft-restore'); + } elsif( -x '/usr/sbin/iptables-restore' ) { + print "run iptables-restore\n"; + $this->command('cat /etc/turtlefirewall/iptables.dat | /usr/sbin/iptables-restore'); + } else { + print STDERR "Error: iptables-restore needed\n"; } + # Don't unlink, for debugging + unlink "/etc/turtlefirewall/iptables.dat"; # Apply Rate Limits for my $r ($this->GetRateLimitList()) { my %ratelimit = $this->GetRateLimit($r); for( my $i=0; $i<=$#{$this->{fw}{RULE}}; $i++ ) { - if( $this->{fw}{RULE}[$i]{RATELIMIT} eq $r && $this->{fw}{RULE}[$i]{ACTIVE} ne 'NO') { + if( defined($this->{fw}{RULE}[$i]{RATELIMIT}) && $this->{fw}{RULE}[$i]{RATELIMIT} eq $r && !$this->{fw}{RULE}[$i]{ACTIVE} ) { # Convert to bps my $rate = $ratelimit{'RATE'} * 1024000; print "run ratelimit-restore $r($ratelimit{'RATE'} Mbps)\n"; @@ -1924,22 +1969,22 @@ sub startFirewall { my @item_list = (); push(@item_list, split( /,/, $this->{fw}{RULE}[$i]{SRC} ) ); push(@item_list, split( /,/, $this->{fw}{RULE}[$i]{DST} ) ); - if( grep( /^$s$/, @item_list ) && $this->{fw}{RULE}[$i]{ACTIVE} ne 'NO') { + if( grep( /^$s$/, @item_list ) && !$this->{fw}{RULE}[$i]{ACTIVE} ) { print "run ipset-restore $s($ipset{'IP'})\n"; my $addresslist_file = $this->{fw}{ADDRESSLIST}{$ipset{'IP'}}{FILE}; my $addresslist_type = $this->{fw}{ADDRESSLIST}{$ipset{'IP'}}{TYPE}; $this->command( "ipset flush $ipset{'IP'}", "/dev/null 2>&1" ); my @items = (); open( FILE, "<", "$addresslist_file" ); - while( ) { + while(my $l = ) { if( $addresslist_type eq "hash:ip" ) { - if( $_ =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ ) { push(@items, $1); } + if( $l =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ ) { push(@items, $1); } } if( $addresslist_type eq "hash:net" ) { - if( $_ =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\b([0-9]|[12][0-9]|3[0-2])\b)/ ) { push(@items, $1); } + if( $l =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\b([0-9]|[12][0-9]|3[0-2])\b)/ ) { push(@items, $1); } } if( $addresslist_type eq "hash:mac" ) { - if( $_ =~ /([0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2})/ ) { push(@items, $1); } + if( $l =~ /([0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2})/ ) { push(@items, $1); } } } close( FILE ); @@ -1966,26 +2011,27 @@ sub stopFirewall { "iptables -P INPUT ACCEPT; ". "iptables -P OUTPUT ACCEPT; ". "iptables -P FORWARD ACCEPT" ); - #$this->command( 'nft flush ruleset' ); - - # enable ping + + # Enable ping $this->command( 'echo "0"', '/proc/sys/net/ipv4/icmp_echo_ignore_all' ); - # flush conntrack table + # Flush conntrack table $this->command( 'conntrack -F', '/dev/null 2>&1' ); } sub getIptablesRules { my $this = shift; - + my $chains = ''; my $rules = ''; my $chains_nat = ''; my $rules_nat = ''; - + my $chains_mangle = ''; my $rules_mangle = ''; + my $rules_mangle_option = ''; + my $chains_mangle_connmarkpreroute = ''; my $rules_mangle_connmarkpreroute = ''; @@ -2002,18 +2048,19 @@ sub getIptablesRules { my $rules_raw_conntrack = ''; my $log_limit=60; - my $log_limit_burst=5; - if( $this->{fw}{OPTION}{log_limit} > 0 ) { + if( defined($this->{fw}{OPTION}{log_limit}) && $this->{fw}{OPTION}{log_limit} > 0 ) { $log_limit = $this->{fw}{OPTION}{log_limit}; - print "log_limit: $log_limit\n"; } - if( $this->{fw}{OPTION}{log_limit_burst} > 0 ) { + $this->{log_limit} = $log_limit; + print "log_limit: $log_limit\n"; + + my $log_limit_burst=5; + if( defined($this->{fw}{OPTION}{log_limit_burst}) && $this->{fw}{OPTION}{log_limit_burst} > 0 ) { $log_limit_burst = $this->{fw}{OPTION}{log_limit_burst}; - print "log_limit_burst: $log_limit_burst\n"; } - $this->{log_limit} = $log_limit; $this->{log_limit_burst} = $log_limit_burst; - + print "log_limit_burst: $log_limit_burst\n"; + # Chains for filter table $chains .= "*filter\n". ":FORWARD DROP [0:0]\n". @@ -2039,10 +2086,6 @@ sub getIptablesRules { ":PREROUTING ACCEPT [0:0]\n". ":OUTPUT ACCEPT [0:0]\n"; - # Copy packet mark to connection mark and vice versa - $rules_mangle .= "-A PREROUTING -j CONNMARK --restore-mark\n"; - $rules_mangle .= "-A POSTROUTING -j CONNMARK --save-mark\n"; - # Enable access from/to the loopback interface. $rules .= "-A INPUT -i lo -j ACCEPT\n"; $rules .= "-A OUTPUT -o lo -j ACCEPT\n"; @@ -2051,9 +2094,9 @@ sub getIptablesRules { # START of INVALID Packets filter by Mark Francis $chains .= ":INVALID - [0:0]\n"; $chains .= ":CHECK_INVALID - [0:0]\n"; - + print "drop_invalid_state: "; - if( $this->{fw}{OPTION}{drop_invalid_state} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_invalid_state}) || $this->{fw}{OPTION}{drop_invalid_state} ne 'off' ) { $rules .= "-A CHECK_INVALID -m conntrack --ctstate INVALID -j INVALID\n"; $rules .= "-A INVALID -m conntrack --ctstate INVALID ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-STATE(DRO) \"\n"; @@ -2061,9 +2104,9 @@ sub getIptablesRules { } else { print "off\n"; } - + print "drop_invalid_all: "; - if( $this->{fw}{OPTION}{drop_invalid_all} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_invalid_all}) || $this->{fw}{OPTION}{drop_invalid_all} ne 'off' ) { $rules .= "-A CHECK_INVALID -p tcp --tcp-flags ALL ALL -j INVALID\n"; $rules .= "-A INVALID -p tcp --tcp-flags ALL ALL ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-ALL(DRO) \"\n"; @@ -2071,9 +2114,9 @@ sub getIptablesRules { } else { print "off\n"; } - + print "drop_invalid_none: "; - if( $this->{fw}{OPTION}{drop_invalid_none} ne 'off' ) { + if( !defined( $this->{fw}{OPTION}{drop_invalid_none}) || $this->{fw}{OPTION}{drop_invalid_none} ne 'off' ) { $rules .= "-A CHECK_INVALID -p tcp --tcp-flags ALL NONE -j INVALID\n"; $rules .= "-A INVALID -p tcp --tcp-flags ALL NONE ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-NONE(DRO) \"\n"; @@ -2081,9 +2124,9 @@ sub getIptablesRules { } else { print "off\n"; } - + print "drop_invalid_fin_notack: "; - if( $this->{fw}{OPTION}{drop_invalid_fin_notack} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_invalid_fin_notack}) || $this->{fw}{OPTION}{drop_invalid_fin_notack} ne 'off' ) { $rules .= "-A CHECK_INVALID -p tcp --tcp-flags FIN,ACK FIN -j INVALID\n"; $rules .= "-A INVALID -p tcp --tcp-flags FIN,ACK FIN ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-FIN,!ACK(DRO) \"\n"; @@ -2091,9 +2134,9 @@ sub getIptablesRules { } else { print "off\n"; } - + print "drop_invalid_sys_fin: "; - if( $this->{fw}{OPTION}{drop_invalid_syn_fin} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_invalid_syn_fin}) || $this->{fw}{OPTION}{drop_invalid_syn_fin} ne 'off' ) { $rules .= "-A CHECK_INVALID -p tcp --tcp-flags SYN,FIN SYN,FIN -j INVALID\n"; $rules .= "-A INVALID -p tcp --tcp-flags SYN,FIN SYN,FIN ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-SYN,FIN(DRO) \"\n"; @@ -2103,7 +2146,7 @@ sub getIptablesRules { } print "drop_invalid_syn_rst: "; - if( $this->{fw}{OPTION}{drop_invalid_syn_rst} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_invalid_syn_rst}) || $this->{fw}{OPTION}{drop_invalid_syn_rst} ne 'off' ) { $rules .= "-A CHECK_INVALID -p tcp --tcp-flags SYN,RST SYN,RST -j INVALID\n"; $rules .= "-A INVALID -p tcp --tcp-flags SYN,RST SYN,RST ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-SYN,RST(DRO) \"\n"; @@ -2111,9 +2154,9 @@ sub getIptablesRules { } else { print "off\n"; } - + print "drop_invalid_fragment: "; - if( $this->{fw}{OPTION}{drop_invalid_fragment} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_invalid_fragment}) || $this->{fw}{OPTION}{drop_invalid_fragment} ne 'off' ) { $rules .= "-A CHECK_INVALID -f -j INVALID\n"; $rules .= "-A INVALID -f ". " -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=INVALID-FRAGMENT(DRO) \"\n"; @@ -2132,9 +2175,9 @@ sub getIptablesRules { $rules .= "-A FORWARD -j CHECK_INVALID\n"; # END of INVALID Packets filter by Mark Francis ############################################### - + print "drop_ip_blacklist: "; - if( $this->{fw}{OPTION}{drop_ip_blacklist} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_ip_blacklist}) || $this->{fw}{OPTION}{drop_ip_blacklist} ne 'off' ) { $chains .= ":IP_BLACKLIST - [0:0]\n"; $rules .= "-A IP_BLACKLIST -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=IP-BLACKLIST(DRO) \"\n"; $rules .= "-A IP_BLACKLIST -j DROP\n"; @@ -2148,7 +2191,7 @@ sub getIptablesRules { } print "drop_domain_blacklist: "; - if( $this->{fw}{OPTION}{drop_domain_blacklist} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_domain_blacklist}) || $this->{fw}{OPTION}{drop_domain_blacklist} ne 'off' ) { $chains .= ":DOMAIN_BLACKLIST - [0:0]\n"; $rules .= "-A DOMAIN_BLACKLIST -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=DOMAIN-BLACKLIST(DRO) \"\n"; $rules .= "-A DOMAIN_BLACKLIST -j DROP\n"; @@ -2165,22 +2208,8 @@ sub getIptablesRules { print "off\n"; } - print "drop_ja3_blacklist: "; - if( $this->{fw}{OPTION}{drop_ja3_blacklist} ne 'off' ) { - $chains .= ":JA3_BLACKLIST - [0:0]\n"; - $rules .= "-A JA3_BLACKLIST -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=JA3-BLACKLIST(DRO) \"\n"; - $rules .= "-A JA3_BLACKLIST -j DROP\n"; - - $rules .= "-A INPUT -m ndpi --all --risk 28 -j JA3_BLACKLIST\n"; - $rules .= "-A OUTPUT -m ndpi --all --risk 28 -j JA3_BLACKLIST\n"; - $rules .= "-A FORWARD -m ndpi --all --risk 28 -j JA3_BLACKLIST\n"; - print "on\n"; - } else { - print "off\n"; - } - print "drop_sha1_blacklist: "; - if( $this->{fw}{OPTION}{drop_sha1_blacklist} ne 'off' ) { + if( !defined($this->{fw}{OPTION}{drop_sha1_blacklist}) || $this->{fw}{OPTION}{drop_sha1_blacklist} ne 'off' ) { $chains .= ":SHA1_BLACKLIST - [0:0]\n"; $rules .= "-A SHA1_BLACKLIST -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"TFW=SHA1-BLACKLIST(DRO) \"\n"; $rules .= "-A SHA1_BLACKLIST -j DROP\n"; @@ -2192,7 +2221,16 @@ sub getIptablesRules { } else { print "off\n"; } - + + print "clamp_mss_to_pmtu: "; + if( !defined($this->{fw}{OPTION}{clamp_mss_to_pmtu}) || $this->{fw}{OPTION}{clamp_mss_to_pmtu} ne 'off' ) { + $rules_mangle_option .= "-A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o ppp+ -j TCPMSS --clamp-mss-to-pmtu\n"; + $rules_mangle .= $rules_mangle_option; + print "on\n"; + } else { + print "off\n"; + } + # Definition for the return chain # Return packet chain (NO new connections) $chains .= ":BACK - [0:0]\n"; @@ -2207,7 +2245,7 @@ sub getIptablesRules { $rules .= "-A ICMP-ACC -p icmp --icmp-type time-exceeded -j ACCEPT\n"; $rules .= "-A ICMP-ACC -p icmp --icmp-type parameter-problem -j ACCEPT\n"; $rules .= "-A ICMP-ACC -j RETURN\n"; - + # Application of CONNMARKPREROUTEs my $connmarkpreroutesCount = $this->GetConnmarkPreroutesCount(); if( $connmarkpreroutesCount > 0 ) { @@ -2231,10 +2269,10 @@ sub getIptablesRules { my $connmarksCount = $this->GetConnmarksCount(); if( $connmarksCount > 0 ) { my @zone = $this->GetZoneList(); - for(my $i=0; $i<=$#zone; $i++ ) { + for( my $i=0; $i<=$#zone; $i++ ) { my $z1 = $zone[$i]; my %zone1 = $this->GetZone($z1); - for($j=0; $j<=$#zone; $j++ ) { + for( my $j=0; $j<=$#zone; $j++ ) { my $z2 = $zone[$j]; my %zone2 = $this->GetZone($z2); if( $z1 eq 'FIREWALL' || $z2 eq 'FIREWALL' ) { @@ -2261,6 +2299,12 @@ sub getIptablesRules { $rules_mangle .= $rules_mangle_connmark; } + # Copy packet mark to connection mark and vice versa + if( $rules_mangle_connmarkpreroute || $rules_mangle_connmark ) { + $rules_mangle .= "-I PREROUTING -j CONNMARK --restore-mark\n"; + $rules_mangle .= "-A POSTROUTING -j CONNMARK --save-mark\n"; + } + # Application of CONNTRACKPREROUTEs my $conntrackpreroutesCount = $this->GetConntrackPreroutesCount(); if( $conntrackpreroutesCount > 0 ) { @@ -2300,7 +2344,6 @@ sub getIptablesRules { } # Application of NATs - my $rules_nat = ''; for( my $i=1; $i <= $this->GetNatsCount(); $i++ ) { $rules_nat .= $this->applyNat( $this->GetNat($i) ); } @@ -2317,7 +2360,7 @@ sub getIptablesRules { # Close the MASQ chain with a RETURN to the POSTROUTING parent chain $rules_nat .= "-A MASQ -j RETURN\n"; } - + # REDIRECT my $redirectCount = $this->GetRedirectCount(); if( $redirectCount > 0 ) { @@ -2333,10 +2376,10 @@ sub getIptablesRules { # Create the chains for the ZONES my @zone = $this->GetZoneList(); - for(my $i=0; $i<=$#zone; $i++ ) { + for( my $i=0; $i<=$#zone; $i++ ) { my $z1 = $zone[$i]; my %zone1 = $this->GetZone($z1); - for($j=0; $j<=$#zone; $j++ ) { + for( my $j=0; $j<=$#zone; $j++ ) { my $z2 = $zone[$j]; my %zone2 = $this->GetZone($z2); if( $z1 eq 'FIREWALL' || $z2 eq 'FIREWALL' ) { @@ -2362,12 +2405,12 @@ sub getIptablesRules { for( my $i=1; $i <= $rulesCount; $i++ ) { $rules .= $this->applyRule( 1, 0, 0, 0, $this->GetRule($i) ); } - + # Close the zone chains - for(my $i=0; $i<=$#zone; $i++ ) { - $z1 = $zone[$i]; - for($j=0; $j<=$#zone; $j++ ) { - $z2 = $zone[$j]; + for( my $i=0; $i<=$#zone; $i++ ) { + my $z1 = $zone[$i]; + for( my $j=0; $j<=$#zone; $j++ ) { + my $z2 = $zone[$j]; if( $z1 ne 'FIREWALL' || $z2 ne 'FIREWALL' ) { my $logprefix = "TFW=$z1-$z2"; # iptables --log-prefix max = 29 @@ -2384,9 +2427,9 @@ sub getIptablesRules { $rules .= "-A $chain -m limit --limit $log_limit/hour --limit-burst $log_limit_burst -j LOG --log-prefix \"$logprefix \"\n"; } print "DROP any other connections and LOG Action\n"; - + return ($rules_raw_conntrackpreroute || $rules_raw_conntrack ? $chains_raw.$rules_raw."COMMIT\n" : "*raw\nCOMMIT\n"). - ($rules_mangle_connmarkpreroute || $rules_mangle_connmark ? $chains_mangle.$rules_mangle."COMMIT\n" : "*mangle\nCOMMIT\n"). + ($rules_mangle_connmarkpreroute || $rules_mangle_connmark || $rules_mangle_option ? $chains_mangle.$rules_mangle."COMMIT\n" : "*mangle\nCOMMIT\n"). $chains.$rules."COMMIT\n".$chains_nat.$rules_nat."COMMIT\n"; } @@ -2399,19 +2442,19 @@ sub applyNat { my %services = %{$this->{services}}; my $rules = ''; - - if( $nat{ACTIVE} eq 'NO' ) { + + if( $nat{ACTIVE} ) { return ''; } - my $virtual = $nat{VIRTUAL}; - my $real = $nat{REAL}; - my $nmService = $nat{SERVICE}; - my $port = $nat{PORT}; # Optional port identifier - my $toport = $nat{TOPORT}; # Optional port identifier - my $virtual_ip=''; - my $virtual_if=''; - my $real_ip=''; + my $virtual = defined($nat{VIRTUAL}) ? $nat{VIRTUAL} : ''; + my $real = defined($nat{REAL}) ? $nat{REAL} : ''; + my $nmService = defined($nat{SERVICE}) ? $nat{SERVICE} : ''; + my $port = defined($nat{PORT}) ? $nat{PORT} : ''; # Optional port identifier + my $toport = defined($nat{TOPORT}) ? $nat{TOPORT} : ''; # Optional to port identifier + my $virtual_ip = ''; + my $virtual_if = ''; + my $real_ip = ''; # Service is a list of services? if( $nmService =~ /,/ ) { @@ -2425,16 +2468,15 @@ sub applyNat { } if( $virtual eq '' ) { - print STDERR "Error: VIRTUAL attribute missing in NAT rule definition.\n"; + print "Error: VIRTUAL attribute missing in NAT rule definition.\n"; return $rules; } if( $real eq '' ) { - print STDERR "Error: REAL attribute missing in NAT rule definition.\n"; + print "Error: REAL attribute missing in NAT rule definition.\n"; return $rules; } - if( $fwItems{$virtual} ne 'HOST' && $fwItems{$virtual} ne 'ZONE' ) { - print STDERR "Error: in a NAT rule definition, VIRTUAL attribute [$virtual] is not a valid host or zone name.\n"; + print "Error: in a NAT rule definition, VIRTUAL attribute [$virtual] is not a valid host or zone name.\n"; return $rules; } if( $fwItems{$virtual} eq 'HOST' ) { @@ -2443,12 +2485,16 @@ sub applyNat { if( $fwItems{$virtual} eq 'ZONE' ) { $virtual_if = $fw{ZONE}{$virtual}{IF}; } - if( $fwItems{$real} ne 'HOST' ) { - print STDERR "Error: in a NAT rule definition, REAL attribute is not a valid host name.\n"; + print "Error: in a NAT rule definition, REAL attribute is not a valid host name.\n"; + return $rules; + } + if( $fw{HOST}{$real}{IP} ne '' ) { + $real_ip = $fw{HOST}{$real}{IP}; + } else { + print "Error: in a NAT rule definition, IP attribute missing for $fw{HOST}{$real}{NAME}.\n"; return $rules; } - $real_ip = $fw{HOST}{$real}{IP}; if( $nmService eq '' || $nmService eq 'all' ) { # Interface-wide nat. This was the only way natting was used to be. @@ -2474,9 +2520,9 @@ sub applyNat { # Service-wide nat. This was introduced with v0.98. # On the 'go' way of the specified service we do a DNAT from $virtual_ip:$dport # to $real_ip:$dport, while on the 'back' way we do a SNAT from $real_ip:$sport - # to $virtual_ip:$sport. $state conditions and $jump tags are added to the iptable + # to $virtual_ip:$sport. $state conditions and $jump tags are added to the iptables # entries as well. - + print "NAT virtual($virtual),port($nmService". ($port ne '' ? "/$port" : ''). ") --> real($real)". @@ -2484,14 +2530,20 @@ sub applyNat { " \n"; #$rules .= "#NAT virtual( $virtual ) -to-> real( $real ) on service( $nmService($port) )\n"; - # Outputs a nat roule for each defined service channel + if( !grep /^$nmService$/, keys %services ) { + print "Error: NAT service $nmService invalid.\n"; + return $rules; + } + + # Outputs a nat rule for each defined service channel foreach my $filter (@{$services{$nmService}{FILTERS}}) { - my $direction = $filter->{DIRECTION}; - my $proto = $filter->{P}; - my $icmptype = $filter->{ICMPTYPE}; - my $sport = $filter->{SPORT}; - my $dport = $filter->{DPORT}; - my $state = $filter->{STATE}; + + my $direction = defined($filter->{DIRECTION}) ? $filter->{DIRECTION} : ''; + my $proto = defined($filter->{P}) ? $filter->{P} : ''; + my $icmptype = defined($filter->{ICMPTYPE}) ? $filter->{ICMPTYPE} : ''; + my $sport = defined($filter->{SPORT}) ? $filter->{SPORT} : ''; + my $dport = defined($filter->{DPORT}) ? $filter->{DPORT} : ''; + my $state = defined($filter->{STATE}) ? $filter->{STATE} : ''; # Fetches if( $sport eq 'PORT' ) { $sport = $port; } @@ -2517,8 +2569,8 @@ sub applyNat { if( $dport ne '' ) { $cmd .= "--dport $dport "; } if( $sport ne '' ) { $cmd .= "--sport $sport "; } } elsif( $proto ne 'icmp' ) { - # Well, I'm coding this... But what purpouse is supposed - # to have an icmp nat? Mmmmm... + # Well, I'm coding this... But what is the purpose + # of an icmp nat? Mmmmm... $cmd .= "-p $proto "; if( $icmptype ne '' ) { @@ -2553,7 +2605,7 @@ sub applyNat { # Finally, executes the command $rules .= "$cmd\n"; - # If is possible, now I apply the same rule to firewall itself + # If it is possible, now I apply the same rule to firewall itself if( $cmd =~ /PREROUTING/ && $cmd !~ / -i / ) { $cmd =~ s/PREROUTING/OUTPUT/; $rules .= "$cmd\n"; @@ -2566,23 +2618,23 @@ sub applyNat { sub applyMasquerade { my $this = shift; my %masq = @_; - + my %fw = %{$this->{fw}}; my %fwItems = %{$this->{fwItems}}; my %services = %{$this->{services}}; my $rules = ''; - if( $masq{ACTIVE} eq 'NO' ) { + if( $masq{ACTIVE} ) { return ''; } - + # Masquerade or don't masquerade? - my $is_masquerade = $masq{MASQUERADE} ne 'NO'; + my $is_masquerade = !$masq{MASQUERADE}; + + my $src = defined($masq{SRC}) ? $masq{SRC} : ''; + my $dst = defined($masq{DST}) ? $masq{DST} : ''; - my $src = $masq{SRC}; - my $dst = $masq{DST}; - ### # Backward compatibility with TurtleFirewall < 1.29 if( !$dst && $masq{ZONE} ) { @@ -2590,25 +2642,28 @@ sub applyMasquerade { } if( $dst eq '' ) { - print STDERR "Error: DST or ZONE attribute missing in MASQUERADE rule.\n"; + print "Error: DST or ZONE attribute missing in MASQUERADE rule.\n"; return $rules; } #if( $fwItems{$zone} ne 'ZONE' ) { - # print STDERR "Error: invalid ZONE attribute missing in MASQUERADE rule.\n"; + # print "Error: ZONE attribute missing in MASQUERADE rule.\n"; # return #} - # See if I have a group as source - if( $fwItems{$src} eq 'GROUP' ) { - my %newmasq = %masq; - foreach my $item ( @{$fw{GROUP}{$src}{ITEMS}} ) { - if( $item ne 'FIREWALL' ) { - $newmasq{SRC} = $item; - $rules .= $this->applyMasquerade( %newmasq ); + # Don't check group membership for * zone + if( $src ne '*' ) { + # See if I have a group as source + if( $fwItems{$src} eq 'GROUP' ) { + my %newmasq = %masq; + foreach my $item ( @{$fw{GROUP}{$src}{ITEMS}} ) { + if( $item ne 'FIREWALL' ) { + $newmasq{SRC} = $item; + $rules .= $this->applyMasquerade( %newmasq ); + } } + return $rules; } - return $rules; } # See if I have a group as destination @@ -2622,10 +2677,10 @@ sub applyMasquerade { } return $rules; } - + # Define the SERVICE - my $service = $masq{SERVICE}; - my $port = $masq{PORT}; + my $service = defined($masq{SERVICE}) ? $masq{SERVICE} : ''; + my $port = defined($masq{PORT}) ? $masq{PORT} : '';; # Service is a list of services? if( $service =~ /,/ ) { @@ -2643,18 +2698,27 @@ sub applyMasquerade { } my ($src_zone, $src_peer, $src_type, $src_mac) = $this->expand_item( $src ); - my %src_zone_attr = $this->GetZone( $src_zone ); - $src_if = $src_zone_attr{IF}; - my ($dst_zone, $dst_peer, $dst_type, undef) = $this->expand_item( $dst ); + my $src_if = ''; + if( $src ne '*' ) { + my %src_zone_attr = $this->GetZone( $src_zone ); + $src_if = $src_zone_attr{IF}; + } + my ($dst_zone, $dst_peer, $dst_type, $dst_mac) = $this->expand_item( $dst ); my %dst_zone_attr = $this->GetZone( $dst_zone ); - $dst_if = $dst_zone_attr{IF}; - + my $dst_if = $dst_zone_attr{IF}; + + # Invalid Masquerade, Ignore + if( $dst_mac ne '' && $dst_peer eq '' ) { + print "Error: MASQUERADE $dst (mac:$dst_mac) invalid.\n"; + return $rules; + } + print $is_masquerade ? '' : 'NOT ',"MASQUERADE port($service"; if( $service eq 'tcp' || $service eq 'udp' ) { print "/$port"; } print $src ? ") $src" : ' *'; if( $src_mac ne '' ) { print "(mac:$src_mac)"; } print " --> $dst IF $dst_if\n"; - + $rules .= $this->applyServiceMasquerade( \%services, $service, $src_if, $src_peer, $src_type, $src_mac, $dst_if, $dst_peer, $dst_type, $port, $is_masquerade); return $rules; } @@ -2668,36 +2732,38 @@ sub applyServiceMasquerade { sub _applyServiceMasquerade { my $this = shift; my ($ref_calledServices, $ref_services, $serviceName, $src_if, $src_peer, $src_type, $src_mac, $dst_if, $dst_peer, $dst_type, $port, $is_masquerade) = @_; - - my %service = %{$ref_services->{$serviceName}}; - # Service comment - #comment( "# $serviceName: ".$service{DESCRIPTION} ); + my $rules = ''; + + my %service = (); + if( !grep /^$serviceName$/, keys %{$ref_services} ) { + print "Error: MASQUERADE service $serviceName invalid.\n"; + return $rules; + } else { + %service = %{$ref_services->{$serviceName}}; + } $ref_calledServices->{$serviceName} = 1; - my $rules = ''; - # Loop on filering rules - my $i; - for( $i = 0; $i <= $#{$service{FILTERS}}; $i++ ) { + for( my $i=0; $i<=$#{$service{FILTERS}}; $i++ ) { my %filter = %{$service{FILTERS}[$i]}; - if( $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) { + if( defined($filter{SERVICE}) && $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) { # It is a subservice, recursion call to _applyServiceMasquerade $rules .= $this->_applyServiceMasquerade( $ref_calledServices, $ref_services, $filter{SERVICE}, $src_if, $src_peer, $src_type, $src_mac, $dst_if, $dst_peer, $dst_type, $port, $is_masquerade ); next; } - my $direction = $filter{DIRECTION}; - my $p = $filter{P}; - my $icmptype = $filter{ICMPTYPE}; - my $sport = $filter{SPORT}; - my $dport = $filter{DPORT}; - my $state = $filter{STATE}; - my $jump = $filter{JUMP}; + my $direction = defined($filter{DIRECTION}) ? $filter{DIRECTION} : ''; + my $p = defined($filter{P}) ? $filter{P} : ''; + my $icmptype = defined($filter{ICMPTYPE}) ? $filter{ICMPTYPE} : ''; + my $sport = defined($filter{SPORT}) ? $filter{SPORT} : ''; + my $dport = defined($filter{DPORT}) ? $filter{DPORT} : ''; + my $state = defined($filter{STATE}) ? $filter{STATE} : ''; + my $jump = defined($filter{JUMP}) ? $filter{JUMP} : ''; if( $direction ne 'go' ) { # Don't process Back filters, masquerade is apply only for go direction @@ -2734,15 +2800,17 @@ sub _applyServiceMasquerade { if( $sport ne '' ) { $cmd .= "--sport $sport "; } if( $dport ne '' ) { $cmd .= "--dport $dport "; } if( $state ne '' ) { $cmd .= "-m conntrack --ctstate $state "; } - + if( $is_masquerade ) { $cmd .= "-j MASQUERADE"; } else { # Don't masquerade and return to parent chain $cmd .= "-j RETURN"; } - + + # Print commands, for debugging #print "$cmd\n"; + $rules .= "$cmd\n"; } } @@ -2758,16 +2826,16 @@ sub applyRedirect { my %services = %{$this->{services}}; my $rules = ''; - - if( $redirect{ACTIVE} eq 'NO' ) { + + if( $redirect{ACTIVE} ) { return ''; } # Redirect or don't redirect? - my $is_redirect = $redirect{REDIRECT} ne 'NO'; + my $is_redirect = !$redirect{REDIRECT}; - my $src = $redirect{SRC}; - my $dst = $redirect{DST}; + my $src = defined($redirect{SRC}) ? $redirect{SRC} : ''; + my $dst = defined($redirect{DST}) ? $redirect{DST} : ''; # See if I have a group as source if( $fwItems{$src} eq 'GROUP' ) { @@ -2781,61 +2849,60 @@ sub applyRedirect { return $rules; } - # See if I have a group as destination - if( $fwItems{$dst} eq 'GROUP' ) { - my %newredirect = %redirect; - foreach my $item ( @{$fw{GROUP}{$dst}{ITEMS}} ) { - # Ignore ZONE items (PREROUTING don't accept -o option) - if( $item ne 'FIREWALL' && $fw{ZONE}{$item}{IF} eq '' ) { - $newredirect{DST} = $item; - $rules .= $this->applyRedirect( %newredirect ); - } else { - print "REDIRECT INVALID : IGNORING : $src --> $dst\n"; + # Don't check group membership for * zone + if( $dst ne '*' ) { + # See if I have a group as destination + if( $fwItems{$dst} eq 'GROUP' ) { + my %newredirect = %redirect; + foreach my $item ( @{$fw{GROUP}{$dst}{ITEMS}} ) { + # Ignore ZONE items (PREROUTING doesn't accept -o option) + if( $item ne 'FIREWALL' && $fw{ZONE}{$item}{IF} eq '' ) { + $newredirect{DST} = $item; + $rules .= $this->applyRedirect( %newredirect ); + } else { + print "Error: REDIRECT $src --> $dst invalid.\n"; + } } + return $rules; } - return $rules; } # I define the SERVICE - my $service = $redirect{SERVICE}; - my $port = $redirect{PORT}; - my $toport = $redirect{TOPORT}; + my $service = defined($redirect{SERVICE}) ? $redirect{SERVICE} : ''; + my $port = defined($redirect{PORT}) ? $redirect{PORT} : ''; + my $toport = defined($redirect{TOPORT}) ? $redirect{TOPORT} : ''; my ($src_zone, $src_peer, $src_type, $src_mac) = $this->expand_item( $src ); my %src_zone_attr = $this->GetZone( $src_zone ); my $src_if = $src_zone_attr{IF}; - - my $dst_zone; - my $dst_peer; - my $dst_if; - if( $dst eq '*' ) { - $dst_zone = '*'; - $dst_peer = '0.0.0.0/0'; - $dst_if = ''; - } else { - ($dst_zone, $dst_peer, $dst_type, undef) = $this->expand_item( $dst ); + my ($dst_zone, $dst_peer, $dst_type, $dst_mac) = $this->expand_item( $dst ); + my $dst_if = ''; + if( $dst ne '*' ) { my %dst_zone_attr = $this->GetZone( $dst_zone ); $dst_if = $dst_zone_attr{IF}; } - print $is_redirect ? '' : 'NOT ',"REDIRECT port($service"; - if( $service eq 'tcp' || $service eq 'udp' ) { print "/$port"; } # Invalid Redirect, Ignore - # print " $src"; - # if( $src_mac ne '' ) { print " (mac:$src_mac)"; } - if( $src_mac ne '' ) { print " : INVALID : IGNORING : $src (mac:$src_mac)"; - } else { - print ") $src"; + if( $src_mac ne '' && $src_peer eq '' ) { + print "Error: REDIRECT $src (mac:$src_mac) invalid.\n"; + return $rules; } - print " --> $dst"; + if( $dst_mac ne '' && $dst_peer eq '' ) { + print "Error: REDIRECT $dst (mac:$dst_mac) invalid.\n"; + return $rules; + } + + print $is_redirect ? '' : 'NOT ',"REDIRECT port($service"; + if( $service eq 'tcp' || $service eq 'udp' ) { print "/$port"; } + print ") $src --> $dst"; if( $is_redirect ) { print " TO LOCAL PORT $toport"; } print "\n"; # I create the 2 return chains - $rules .= $this->applyServiceRedirect( \%services, $service, $src_if, $src_peer, $src_type, $src_mac, $dst_if, $dst_peer, $dst_type, $port, $toport, $is_redirect); - + $rules .= $this->applyServiceRedirect( \%services, $service, $src_if, $src_peer, $src_type, $dst_if, $dst_peer, $dst_type, $port, $toport, $is_redirect); + return $rules; } @@ -2847,37 +2914,43 @@ sub applyServiceRedirect { sub _applyServiceRedirect { my $this = shift; - my ($ref_calledServices, $ref_services, $serviceName, $src_if, $src_peer, $src_type, $src_mac, $dst_if, $dst_peer, $dst_type, $port, $toport, $is_redirect) = @_; + my ($ref_calledServices, $ref_services, $serviceName, $src_if, $src_peer, $src_type, $dst_if, $dst_peer, $dst_type, $port, $toport, $is_redirect) = @_; my $rules = ''; - - my %service = %{$ref_services->{$serviceName}}; + + my %service = (); + if( !grep /^$serviceName$/, keys %{$ref_services} ) { + print "Error: REDIRECT service $serviceName invalid.\n"; + return $rules; + } else { + %service = %{$ref_services->{$serviceName}}; + } $ref_calledServices->{$serviceName} = 1; # loop on filering rules - for( my $i = 0; $i <= $#{$service{FILTERS}}; $i++ ) { + for( my $i=0; $i<=$#{$service{FILTERS}}; $i++ ) { my %filter = %{$service{FILTERS}[$i]}; - if( $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) { + if( defined($filter{SERVICE}) && $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) { # It is a subservice, recursion call to _applyService $rules .= $this->_applyServiceRedirect( $ref_calledServices, $ref_services, $filter{SERVICE}, - $src_if, $src_peer, $src_type, $src_mac, $dst_if, $dst_peer, $dst_type, $port, $toport, $is_redirect ); + $src_if, $src_peer, $src_type, $dst_if, $dst_peer, $dst_type, $port, $toport, $is_redirect ); next; } - my $direction = $filter{DIRECTION}; - my $p = $filter{P}; - my $icmptype = $filter{ICMPTYPE}; - my $sport = $filter{SPORT}; - my $dport = $filter{DPORT}; - my $state = $filter{STATE}; - my $jump = $filter{JUMP}; + my $direction = defined($filter{DIRECTION}) ? $filter{DIRECTION} : ''; + my $p = defined($filter{P}) ? $filter{P} : ''; + my $icmptype = defined($filter{ICMPTYPE}) ? $filter{ICMPTYPE} : ''; + my $sport = defined($filter{SPORT}) ? $filter{SPORT} : ''; + my $dport = defined($filter{DPORT}) ? $filter{DPORT} : ''; + my $state = defined($filter{STATE}) ? $filter{STATE} : ''; + my $jump = defined($filter{JUMP}) ? $filter{JUMP} : ''; # I only use the first tcp/udp filter rule if( $direction eq 'go' && ($p eq 'tcp' || $p eq 'udp' || $p eq '') && - ($filter{JUMP} eq '' || $filter{JUMP} eq 'ACCEPT') ) { + ($jump eq '' || $jump eq 'ACCEPT') ) { if( $dport eq 'PORT' ) { $dport = $port; @@ -2891,12 +2964,7 @@ sub _applyServiceRedirect { if( $src_type =~ /HOST|NET/ ) { $cmd .= "-s $src_peer "; } } - # Invalid Redirect, Ignore - #if( $src_mac =~ /^[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}\:[0-9a-fA-F]{2}$/ ) { - # $cmd .= "-m mac --mac-source $src_mac "; - #} - - # iptables prerouting chain don't accept -o option. + # iptables prerouting chain doesn't accept -o option. #if( $dst_if ne '' ) { $cmd .= "-o $dst_if "; } if( $dst_peer ne '' ) { if( $dst_type eq 'GEOIP' ) { $cmd .= "-m geoip --destination-country $dst_peer "; } @@ -2949,32 +3017,34 @@ sub applyRule { my $preroute = shift; my %rule = @_; - if( $rule{ACTIVE} eq 'NO' ) { + if( $rule{ACTIVE} ) { return ''; } - + my %fw = %{$this->{fw}}; my %fwItems = %{$this->{fwItems}}; my %services = %{$this->{services}}; my $rules = ''; - - my $src = $rule{SRC}; - my $dst = $rule{DST}; - my $time = $rule{TIME}; - my $target = $rule{TARGET}; - my $service = $rule{SERVICE}; - my $ndpi = $rule{NDPI}; - my $category = $rule{CATEGORY}; - my $hostnameset = $rule{HOSTNAMESET}; - my $hostname = $rule{HOSTNAME}; - my $riskset = $rule{RISKSET}; - my $risk = $rule{RISK}; - my $ratelimit = $rule{RATELIMIT}; - my $port = $rule{PORT}; - my $mark = $rule{MARK}; - my $helper = $rule{HELPER}; - my $log = $rule{LOG}; + + my $src = defined($rule{SRC}) ? $rule{SRC} : ''; + my $dst = defined($rule{DST}) ? $rule{DST} : ''; + my $time = defined($rule{TIME}) ? $rule{TIME} : ''; + my $target = defined($rule{TARGET}) ? $rule{TARGET} : ''; + my $service = defined($rule{SERVICE}) ? $rule{SERVICE} : ''; + my $ndpi = defined($rule{NDPI}) ? $rule{NDPI} : ''; + my $category = defined($rule{CATEGORY}) ? $rule{CATEGORY} : ''; + my $hostnameset = defined($rule{HOSTNAMESET}) ? $rule{HOSTNAMESET} : ''; + my $hostname = defined($rule{HOSTNAME}) ? $rule{HOSTNAME} : ''; + my $riskset = defined($rule{RISKSET}) ? $rule{RISKSET} : ''; + my $risk = defined($rule{RISK}) ? $rule{RISK} : ''; + my $ratelimit = defined($rule{RATELIMIT}) ? $rule{RATELIMIT} : ''; + my $port = defined($rule{PORT}) ? $rule{PORT} : ''; + my $mark = defined($rule{MARK}) ? $rule{MARK} : ''; + my $helper = defined($rule{HELPER}) ? $rule{HELPER} : ''; + my $log = defined($rule{LOG}) ? $rule{LOG} : ''; + + my $prev = ''; if( $display ) { if( $target ne '' ) { @@ -2997,7 +3067,6 @@ sub applyRule { if( $hostnameset ne '' ) { print " hostname($hostnameset)"; } if( $riskset ne '' ) { print " risk($riskset)"; } print " $src --> $dst"; - #if( $src_mac ne '' ) { print "(mac:$src_mac)"; } if( $ratelimit ne '' ) { print " WHEN rate($ratelimit)"; } if( $time ne '' ) { print " AT $time"; } if( $mark ne '' ) { print " WITH mark($mark)"; } @@ -3035,7 +3104,7 @@ sub applyRule { # sort @srcs = sort(@srcs); # unique values - my $prev = '***none***'; + $prev = '***none***'; @srcs = grep($_ ne $prev && (($prev) = $_), @srcs); if( $#srcs > 0 ) { # more then one element @@ -3052,11 +3121,13 @@ sub applyRule { my @dsts = (); my @dst_list = split( /,/, $dst ); foreach my $d (@dst_list) { - if( $d eq '*' && not $preroute ) { - # all zones - foreach my $item ( sort(keys(%{$fw{ZONE}})) ) { - if( $item ne 'FIREWALL' ) { - push @dsts, $item; + if( $d eq '*' ) { + if( ! $preroute ) { + # all zones + foreach my $item ( sort(keys(%{$fw{ZONE}})) ) { + if( $item ne 'FIREWALL' ) { + push @dsts, $item; + } } } } elsif( $fwItems{$d} eq 'GROUP' ) { @@ -3071,7 +3142,7 @@ sub applyRule { # sort @dsts = sort(@dsts); # unique values - my $prev = '***none***'; + $prev = '***none***'; @dsts = grep($_ ne $prev && (($prev) = $_), @dsts); if( $#dsts > 0 ) { # more then one element @@ -3109,16 +3180,27 @@ sub applyRule { $ndpi = join(",", @items); } + # ndpi service is a list of ndpi services? + if( $ndpi =~ /,/ ) { + my @ndpis = split( /,/, $ndpi ); + my %newrule = %rule; + foreach my $nserv (@ndpis) { + $newrule{NDPI} = $nserv; + $newrule{CATEGORY} = ''; + $rules .= $this->applyRule( 0, $mangle, $raw, $preroute, %newrule ); + } + return $rules; + } + # hostnameset items if( $hostnameset ne '' ) { my ($hostname_list) = $this->expand_hostnameset_item( $hostnameset ); - my @hostnames = (); my @hostnames = split( /,/, $hostname_list ); # sort @hostnames = sort(@hostnames); # unique values - my $prev = '***none***'; + $prev = '***none***'; @hostnames = grep($_ ne $prev && (($prev) = $_), @hostnames); if( $#hostnames > 0 ) { # more than one element @@ -3141,20 +3223,25 @@ sub applyRule { } my ($src_zone, $src_peer, $src_type, $src_mac) = $this->expand_item( $src ); - my ($dst_zone, $dst_peer, $dst_type, undef) = $this->expand_item( $dst ); + my ($dst_zone, $dst_peer, $dst_type, $dst_mac) = $this->expand_item( $dst ); if( $src_zone eq 'FIREWALL' && $dst_zone eq 'FIREWALL' ) { # ignore chain FIREWALL-FIREWALL if( !$mangle ) { - print "** FIREWALL-->FIREWALL ignored **\n"; + print "Error: FIREWALL-->FIREWALL invalid.\n"; } return $rules; } + if( $dst_mac ne '' && $dst_peer eq '' ) { + print "Error: destination (mac:$dst_mac) invalid.\n"; + return $rules; + } + # time items - $t_days = ''; - $t_start = ''; - $t_stop = ''; + my $weekdays = ''; + my $timestart = ''; + my $timestop = ''; if( $time ne '' ) { my @times = (); if( $fwItems{$time} eq 'TIMEGROUP' ) { @@ -3168,7 +3255,7 @@ sub applyRule { # sort @times = sort(@times); # unique values - my $prev = '***none***'; + $prev = '***none***'; @times = grep($_ ne $prev && (($prev) = $_), @times); if( $#times > 0 ) { # more then one element @@ -3181,43 +3268,43 @@ sub applyRule { } else { $time = shift @times; } - ($t_days, $t_start, $t_stop) = $this->expand_time_item( $time ); + ($weekdays, $timestart, $timestop) = $this->expand_time_item( $time ); } #command( "" ); #comment( "# service $service: $src --> $dst ($src_peer -> $dst_peer) [$src_zone -> $dst_zone]" ); - + # Create the Chains - my $andata = ''; - my $ritorno = ''; + my $goChain = ''; + my $backChain = ''; if( $preroute ) { - $andata = "$src_zone-IN"; + $goChain = "$src_zone-IN"; } else { - $andata = "$src_zone-$dst_zone"; + $goChain = "$src_zone-$dst_zone"; } if( $preroute || $raw ) { - $ritorno = ''; + $backChain = ''; } else { - $ritorno = "$dst_zone-$src_zone"; + $backChain = "$dst_zone-$src_zone"; } - + # Create the Rules if( $mangle ) { # Mangle Rule - $rules .= $this->applyService( \%services, $service, $andata, $ritorno, $src_peer, $src_type, $src_mac, $dst_peer, $dst_type, - $port, $ndpi, $category, $hostname, $risk, '', $t_days, $t_start, $t_stop, '', '', $mark, '' ); + $rules .= $this->applyService( \%services, $service, $goChain, $backChain, $src_peer, $src_type, $src_mac, $dst_peer, $dst_type, + $port, $ndpi, $hostname, $risk, '', $weekdays, $timestart, $timestop, '', '', $mark, '' ); } elsif( $raw ) { # Raw Rule - $rules .= $this->applyService( \%services, $service, $andata, $ritorno, $src_peer, $src_type, $src_mac, $dst_peer, $dst_type, - $port, $ndpi, $category, $hostname, $risk, '', $t_days, $t_start, $t_stop, '', '', '', $helper ); + $rules .= $this->applyService( \%services, $service, $goChain, $backChain, $src_peer, $src_type, $src_mac, $dst_peer, $dst_type, + $port, $ndpi, $hostname, $risk, '', $weekdays, $timestart, $timestop, '', '', '', $helper ); } else { # Filter Rule - $rules .= $this->applyService( \%services, $service, $andata, $ritorno, $src_peer, $src_type, $src_mac, $dst_peer, $dst_type, - $port, $ndpi, $category, $hostname, $risk, $ratelimit, $t_days, $t_start, $t_stop, $log, $target, '', '' ); + $rules .= $this->applyService( \%services, $service, $goChain, $backChain, $src_peer, $src_type, $src_mac, $dst_peer, $dst_type, + $port, $ndpi, $hostname, $risk, $ratelimit, $weekdays, $timestart, $timestop, $log, $target, '', '' ); } - + return $rules; } @@ -3231,39 +3318,40 @@ sub applyService { sub _applyService { my $this = shift; my( $ref_calledServices, $ref_services, $serviceName, $goChain, $backChain, $src, $src_type, $src_mac, $dst, $dst_type, - $port, $ndpi, $category, $hostname, $risk, $ratelimit, $t_days, $t_start, $t_stop, $log, $target, $mangle_mark, $helper ) = @_; - - my %service = %{$ref_services->{$serviceName}}; + $port, $ndpi, $hostname, $risk, $ratelimit, $weekdays, $timestart, $timestop, $log, $target, $mangle_mark, $helper ) = @_; my $rules = ''; - + + my %service = (); + if( !grep /^$serviceName$/, keys %{$ref_services} ) { + print "Error: service $serviceName invalid.\n"; + return $rules; + } else { + %service = %{$ref_services->{$serviceName}}; + } + $ref_calledServices->{$serviceName} = 1; - # service comment - #comment( "# $serviceName: ".$service{DESCRIPTION} ); - # - # loop on the filering rules - my $i; - for( $i = 0; $i <= $#{$service{FILTERS}}; $i++ ) { + for( my $i=0; $i<=$#{$service{FILTERS}}; $i++ ) { my %filter = %{$service{FILTERS}[$i]}; - - if( $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) { + + if( defined($filter{SERVICE}) && $filter{SERVICE} ne '' && !$ref_calledServices->{$filter{SERVICE}} ) { # It is a subservice, recursion call to _applyService $rules .= $this->_applyService( $ref_calledServices, $ref_services, $filter{SERVICE}, - $goChain, $backChain, $src, $src_type, $src_mac, $dst, $dst_type, $port, $ndpi, $category, $hostname, $risk, $ratelimit, - $t_days, $t_start, $t_stop, $log, $target, $mangle_mark, $helper ); + $goChain, $backChain, $src, $src_type, $src_mac, $dst, $dst_type, $port, $ndpi, $hostname, $risk, $ratelimit, + $weekdays, $timestart, $timestop, $log, $target, $mangle_mark, $helper ); next; } - my $direction = $filter{DIRECTION}; - my $p = $filter{P}; - my $icmptype = $filter{ICMPTYPE}; - my $sport = $filter{SPORT}; - my $dport = $filter{DPORT}; - my $state = $filter{STATE}; - my $jump = $filter{JUMP}; + my $direction = defined($filter{DIRECTION}) ? $filter{DIRECTION} : ''; + my $p = defined($filter{P}) ? $filter{P} : '';; + my $icmptype = defined($filter{ICMPTYPE}) ? $filter{ICMPTYPE} : '';; + my $sport = defined($filter{SPORT}) ? $filter{SPORT} : '';; + my $dport = defined($filter{DPORT}) ? $filter{DPORT} : '';; + my $state = defined($filter{STATE}) ? $filter{STATE} : '';; + my $jump = defined($filter{JUMP}) ? $filter{JUMP} : '';; if( $target =~ /DROP|REJECT/ && $direction ne 'go' && $ratelimit eq '' ) { # Don't process Back filters @@ -3321,44 +3409,37 @@ sub _applyService { if( $dport ne '' ) { $cmd .= "--dport $dport "; } if( $ndpi ne '' ) { - if( $target eq 'ACCEPT' ) { - if( $ndpi eq 'all' ) { - print "** all nDPI service ignored on target $target **\n"; - } else { + if( $ndpi eq 'all' ) { + # First Packet Classification only + $cmd .= "-m ndpi --all "; + } else { + if( $this->{ndpiprotocols}{$ndpi}{'DPI'} && $mangle_mark eq '' ) { my $cmddpi = $cmd; - $cmddpi .= "-m ndpi --inprogress $ndpi -j $target "; + # Allow beyond First Packet Classification + $cmddpi .= "-m ndpi --inprogress $ndpi -j ACCEPT "; $rules .= "$cmddpi\n"; - $cmd .= "-m ndpi --clevel dpi --proto $ndpi "; - } - if( $hostname ne '' ) { print "** nDPI hostname ignored on target $target **\n"; } - if( $risk ne '' ) { print "** nDPI risk ignored on target $target **\n"; } - } else { - if( $ndpi eq 'all' ) { - $cmd .= "-m ndpi --all "; - } else { - $cmd .= "-m ndpi --proto $ndpi "; - } - if( $hostname ne '' ) { $cmd .= "--host /$hostname/ "; } - if( $risk ne '' ) { $cmd .= "--risk $risk "; } + } + $cmd .= "-m ndpi --proto $ndpi "; } + if( $hostname ne '' ) { $cmd .= "--host /$hostname/ "; } + if( $risk ne '' ) { $cmd .= "--risk $risk "; } } if( $state ne '' ) { $cmd .= "-m conntrack --ctstate $state "; } - if( $t_days ne '' && $t_start ne '' && $t_stop ne '' ) { - $cmd .= "-m time --timestart $t_start --timestop $t_stop --weekdays $t_days "; + if( $weekdays ne '' && $timestart ne '' && $timestop ne '' ) { + $cmd .= "-m time --timestart $timestart --timestop $timestop --weekdays $weekdays "; } # LOG before target if( $log eq "YES" ) { my $cmdlog = $cmd; if( $target =~ /DROP|REJECT/ ) { + my $logprefix = ''; if( $risk ne '' ) { $logprefix = "TFW=RISK-$risk"; } elsif( $hostname ne '') { $logprefix = "TFW=$hostname"; - } elsif( $category ne '') { - $logprefix = "TFW=$category"; } elsif( $ndpi ne '' ) { $logprefix = "TFW=$ndpi"; } elsif( $src_type eq 'GEOIP' || $dst_type eq 'GEOIP' ) { @@ -3418,6 +3499,7 @@ sub _applyService { } } + # Print commands, for debugging #print "\n$cmd\n"; $rules .= "$cmd\n"; @@ -3425,41 +3507,52 @@ sub _applyService { return $rules; } -# Given the name of the item it returns the zone, ip & netmask +# Given the name of the item it returns the zone, ip & netmask, type and mac sub expand_item { my $this = shift; my $item = shift; - + my %fw = %{$this->{fw}}; my %fwItems = %{$this->{fwItems}}; - my $type = $fwItems{$item}; my $zone = ''; my $ip = ''; + my $type = ''; my $mac = ''; - if( $type eq 'ZONE' ) { - $zone = $item; - $ip = '0.0.0.0/0'; - } - if( $type eq 'GEOIP' ) { - $zone = $fw{GEOIP}{$item}{ZONE}; - $ip = $fw{GEOIP}{$item}{IP}; - } - if( $type eq 'IPSET' ) { - $zone = $fw{IPSET}{$item}{ZONE}; - $ip = $fw{IPSET}{$item}{IP}; - } - if( $type eq 'NET' ) { - $zone = $fw{NET}{$item}{ZONE}; - $ip = $fw{NET}{$item}{IP}.'/'.$fw{NET}{$item}{NETMASK}; - } - if( $type eq 'HOST' ) { - $zone = $fw{HOST}{$item}{ZONE}; - $ip = $fw{HOST}{$item}{IP}; - if( $ip ne '' ) {$ip = $ip.'/32';} - $mac = $fw{HOST}{$item}{MAC}; + if( defined($item) ) { + + if( $item eq '*' ) { + $type = 'ZONE'; + } else { + $type = $fwItems{$item}; + } + + if( $type eq 'ZONE' ) { + $zone = $item; + $ip = '0.0.0.0/0'; + } + if( $type eq 'GEOIP' ) { + $zone = $fw{GEOIP}{$item}{ZONE}; + $ip = $fw{GEOIP}{$item}{IP}; + } + if( $type eq 'IPSET' ) { + $zone = $fw{IPSET}{$item}{ZONE}; + $ip = $fw{IPSET}{$item}{IP}; + } + if( $type eq 'NET' ) { + $zone = $fw{NET}{$item}{ZONE}; + $ip = $fw{NET}{$item}{IP}.'/'.$fw{NET}{$item}{NETMASK}; + } + if( $type eq 'HOST' ) { + $zone = $fw{HOST}{$item}{ZONE}; + $ip = $fw{HOST}{$item}{IP}; + if( $ip ne '' ) {$ip = $ip.'/32';} + $mac = $fw{HOST}{$item}{MAC}; + } + } + return ($zone, $ip, $type, $mac ); } @@ -3476,7 +3569,7 @@ sub expand_time_item { $weekdays = $fw{TIME}{$item}{WEEKDAYS}; $timestart = $fw{TIME}{$item}{TIMESTART}; $timestop = $fw{TIME}{$item}{TIMESTOP}; - + return ( $weekdays, $timestart, $timestop ); } @@ -3488,7 +3581,7 @@ sub expand_hostnameset_item { my $hostnames = ''; $hostnames = $fw{HOSTNAMESET}{$item}{HOSTNAMES}; - + return ($hostnames); } @@ -3503,38 +3596,4 @@ sub command { } } -sub iptables_restore_emu { - my $this = shift; - my $rules = shift; - - my $table = ''; - my @lines = split(/\n/, $rules); - foreach my $line (@lines) { - $line =~ s/\#(.*)$//; - if( !$line || $line eq 'COMMIT' ) { - next; - } - if( $line =~ /^\*(.*?)$/ ) { - $table = $1 eq 'filter' ? '' : $1; - next; - } - my $cmd = ''; - my $chain = ''; - my $policy = ''; - if( $line =~ /^\:(.*?) (.*?) (.*?)$/ ) { - $chain = $1; - $policy = $2; - if( $chain =~ /^(INPUT|OUTPUT|FORWARD)$/ ) { - next; - } - $cmd = "-N $chain". ($policy ne '-' ? " -P $policy" : ''); - } else { - $cmd = $line; - } - if( $table ) { $cmd = "-t $table $cmd"; } - - $this->command("iptables $cmd"); - } -} - 1; diff --git a/src/turtlefirewall/setup/convertflowinfo.pl b/src/turtlefirewall/setup/convertflowinfo.pl new file mode 100644 index 0000000..72a876a --- /dev/null +++ b/src/turtlefirewall/setup/convertflowinfo.pl @@ -0,0 +1,109 @@ +#!/usr/bin/env perl + +# Turtle Firewall : Convert Flow Info +# +# Software for configuring a linux firewall (netfilter) +# +# 2001/11/23 13:25:00 +# +#====================================================================== +# Copyright (c) 2001-2026 Andrea Frigido +# You may distribute under the terms of either the GNU General Public +# License +#====================================================================== + +use Tie::File; + +my $log; + +foreach my $arg (@ARGV) { + if( $arg =~ /^(--log)\=(.*)/ ) { + $log = $2; + } else { + if( $arg ne '--help' ) { + print "Wrong parameters...\n"; + } + print "Use: convertflowinfo.pl [--log=file] [--help]\n"; + print "Example: convertflowinfo.pl --log=/tmp/flowinfo.log\n"; + exit(1); + } +} + +if( $log eq '' ) { print "Error: no log provided\n"; exit(1); } +if( ! -f $log ) { print "Error: $log not found\n"; exit(1); } + +my $logtype = qx{file --brief --mime-type $log}; +if( $logtype =~ /sqlite3/ ) { print "Error: $log already converted\n"; exit(1); } + +&convert2psv($log); + +my $qsql = "${log}.qsql"; +system("q -C readwrite -Hp 'select * from $log' > /dev/null 2>&1"); +if( ! -f $qsql ) { print "Error: $qsql not found\n"; exit(1); } + +system("mv -f $qsql $log > /dev/null 2>&1"); + +#============================================================================ + +sub convert2psv { + + my $log = shift; + + tie @log_lines, 'Tie::File', $log; + + foreach my $l (@log_lines) { + + my $stime = ''; + my $etime = ''; + my $l3proto = ''; + my $l4proto = ''; + my $source = ''; + my $sport = ''; + my $destination = ''; + my $dport = ''; + my $ubytes = ''; + my $dbytes = ''; + my $upackets = ''; + my $dpackets = ''; + my $ifindex = ''; + my $connmark = ''; + my $srcnat = ''; + my $dstnat = ''; + my $protocol = ''; + my $hostname = ''; + my $ja4c = ''; + my $tlsfp = ''; + my $risk = ''; + + if( $l =~ /^(.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?) / ) { + $stime = $1; + $etime = $2; + $l3proto = $3; + $l4proto = $4; + $source = $5; + $sport = $6; + $destination = $7; + $dport = $8; + $ubytes = $9; + $dbytes = $10; + $upackets = $11; + $dpackets = $12; + $ifindex = $13; + } + + if( $l =~ /CM=(.*?)( |$)/ ) { $connmark = $1; } + if( $l =~ /SN=(.*?)( |$)/ ) { $srcnat = $1; } + if( $l =~ /DN=(.*?)( |$)/ ) { $dstnat = $1; } + if( $l =~ /P=(.*?)( |$)/ ) { $protocol = $1; } + if( $l =~ /H=(.*?)( |$)/ && $l !~ /H=\"(.*?)\"( |$)/ ) { $hostname = $1; } + if( $l =~ /c=(.*?)( |$)/ ) { $ja4c = $1; } + if( $l =~ /F=(.*?)( |$)/ ) { $tlsfp = $1; } + if( $l =~ /R=(.*?)( |$)/ ) { $risk = $1; } + + $l = "$stime|$etime|$l3proto|$l4proto|$source|$sport|$destination|$dport|$ubytes|$dbytes|$upackets|$dpackets|$ifindex|$connmark|$srcnat|$dstnat|$protocol|$hostname|$ja4c|$tlsfp|$risk\n"; + } + my $psvheader = 'stime|etime|l3proto|l4proto|source|sport|destination|dport|ubytes|dbytes|upackets|dpackets|ifindex|connmark|srcnat|dstnat|protocol|hostname|ja4c|tlsfp|risk'; + unshift @log_lines, $psvheader; + + untie @log_lines; +} diff --git a/src/turtlefirewall/setup/domain_blacklist b/src/turtlefirewall/setup/domain_blacklist index 20aec45..c63f4e3 100644 --- a/src/turtlefirewall/setup/domain_blacklist +++ b/src/turtlefirewall/setup/domain_blacklist @@ -4,12 +4,11 @@ # ln -sf /usr/lib/turtlefirewall/domain_blacklist /etc/cron.daily/domain_blacklist # -echo -e "\nTurtle Firewall 2.4 - Domain Blacklist"; -echo -e "Copyright (c) 2001-2024 Andrea Frigido\n"; - -fw_file="/etc/turtlefirewall/fw.xml" +echo -e "\nTurtle Firewall 2.7 - Domain Blacklist"; +echo -e "Copyright (c) 2001-2026 Andrea Frigido \n"; blacklist_file="/etc/turtlefirewall/domain_blacklist.dat" +also_blacklist_file="/etc/turtlefirewall/also_domain_blacklist.dat" never_blacklist_file="/etc/turtlefirewall/never_domain_blacklist.dat" # Some older CPU's cant load large lists @@ -122,6 +121,15 @@ echo -e "Import : \c" if [ -s $blacklist_file ] then + # Ensure include + if [ -s $also_blacklist_file ] + then + while read blacklist_include + do + sed -i "1s/^/$blacklist_include\n/" $blacklist_file + done < $also_blacklist_file + fi + # Ensure exclude if [ -s $never_blacklist_file ] then diff --git a/src/turtlefirewall/setup/fixconfig.sh b/src/turtlefirewall/setup/fixconfig.sh index 846b8c5..610bee0 100644 --- a/src/turtlefirewall/setup/fixconfig.sh +++ b/src/turtlefirewall/setup/fixconfig.sh @@ -15,12 +15,6 @@ if [ $? != 0 ] sed -i '/^<\/options>$/ i\