From mboxrd@z Thu Jan 1 00:00:00 1970 From: Matthias Fischer To: development@lists.ipfire.org Subject: [PATCH] New addon: Portredirect 1.0 Date: Sun, 27 Jun 2021 15:48:19 +0200 Message-ID: <20210627134819.2088-1-matthias.fischer@ipfire.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============8917162308055464818==" List-Id: --===============8917162308055464818== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Marcel Lorenz Please note: This is a new addon written by Marcel Lorenz . It adds a new GUI to IPFire for DNS/NTP *and* user specific port redirections. How its working: It has exactly the same functionalities as "Forcing DNS/NTP..." - and some m= ore. By setting switches, DNS/NTP requests are automatically redirected to the local IPFire DNS/NTP servers. Additionally, the user can specify custom redirections. These rules are added to a new chain in PREROUTING =3D> PORT_REDIRECT. To avoid problems with (e.g.) transparent 'squid' configurations, redirection rules are added automatically before existing 'squid' rules. Signed-off-by: Matthias Fischer --- config/portredir/EX-portredir.menu | 6 + config/portredir/lang/portredir.de.pl | 19 + config/portredir/lang/portredir.en.pl | 19 + config/portredir/portredir-backup | 1 + config/portredir/portredir.cgi | 525 ++++++++++++++++++++++++++ config/rootfiles/common/misc-progs | 1 + config/rootfiles/packages/portredir | 11 + lfs/portredir | 85 +++++ make.sh | 1 + src/initscripts/packages/portredir | 191 ++++++++++ src/misc-progs/Makefile | 2 +- src/misc-progs/portredirctrl.c | 47 +++ src/paks/portredir/install.sh | 32 ++ src/paks/portredir/uninstall.sh | 28 ++ src/paks/portredir/update.sh | 26 ++ 15 files changed, 993 insertions(+), 1 deletion(-) create mode 100644 config/portredir/EX-portredir.menu create mode 100644 config/portredir/lang/portredir.de.pl create mode 100644 config/portredir/lang/portredir.en.pl create mode 100644 config/portredir/portredir-backup create mode 100644 config/portredir/portredir.cgi create mode 100644 config/rootfiles/packages/portredir create mode 100644 lfs/portredir create mode 100644 src/initscripts/packages/portredir create mode 100644 src/misc-progs/portredirctrl.c create mode 100644 src/paks/portredir/install.sh create mode 100644 src/paks/portredir/uninstall.sh create mode 100644 src/paks/portredir/update.sh diff --git a/config/portredir/EX-portredir.menu b/config/portredir/EX-portred= ir.menu new file mode 100644 index 000000000..8376e8053 --- /dev/null +++ b/config/portredir/EX-portredir.menu @@ -0,0 +1,6 @@ + $subfirewall->{'95.portredir'} =3D { + 'caption' =3D> $Lang::tr{'portredir port redirections'}, + 'uri' =3D> '/cgi-bin/portredir.cgi', + 'title' =3D> "$Lang::tr{'portredir port redirections'}", + 'enabled' =3D> 1 + }; diff --git a/config/portredir/lang/portredir.de.pl b/config/portredir/lang/po= rtredir.de.pl new file mode 100644 index 000000000..b932d4a85 --- /dev/null +++ b/config/portredir/lang/portredir.de.pl @@ -0,0 +1,19 @@ +%tr =3D ( +%tr, +'portredir enable addon' =3D> 'Addon aktivieren', +'portredir common settings' =3D> 'Allgemeine Einstellungen', +'portredir port redirections' =3D> 'Portumleitungen', +'portredir fw for interface' =3D> 'Firewalloptionen f=C3=BCr das Interface', +'portredir enable user redirections' =3D> 'Aktiviere benutzerdefinierte Port= umleitungen', +'portredir force local dns' =3D> 'Erzwinge lokale DNS-Server', +'portredir force local ntp' =3D> 'Erzwinge lokale NTP-Server', +'portredir custom redirections' =3D> 'Benutzerdefinierte Portumleitungen', +'portredir remove rule' =3D> 'Entferne Regel', +'portredir add rule' =3D> 'Hinzuf=C3=BCgen', +'portredir no entries' =3D> 'Keine Eintr=C3=A4ge vorhanden.', +'portredir invalid address' =3D> 'Ung=C3=BCltige Host-Addresse.', +'portredir empty input' =3D> 'Fehlende Angabe: Bitte geben Sie einen g=C3=BC= ltigen Host an.', +'portredir save to activate' =3D> 'Speichern, um =C3=84nderungen zu aktivier= en', +); + +#EOF diff --git a/config/portredir/lang/portredir.en.pl b/config/portredir/lang/po= rtredir.en.pl new file mode 100644 index 000000000..f442f3eaa --- /dev/null +++ b/config/portredir/lang/portredir.en.pl @@ -0,0 +1,19 @@ +%tr =3D ( +%tr, +'portredir enable addon' =3D> 'Enable addon', +'portredir common settings' =3D> 'Common settings', +'portredir port redirections' =3D> 'Port redirections', +'portredir fw for interface' =3D> 'Firewall options for interface', +'portredir enable user redirections' =3D> 'Enable user port redirections', +'portredir force local dns' =3D> 'Enforce local DNS servers', +'portredir force local ntp' =3D> 'Enforce local NTP servers', +'portredir custom redirections' =3D> 'Custom port redirections', +'portredir remove rule' =3D> 'Remove rule', +'portredir add rule' =3D> 'Add new', +'portredir no entries' =3D> 'No entries at the moment.', +'portredir invalid address' =3D> 'Invalid host address.', +'portredir empty input' =3D> 'Empty input: Please enter a valid host.', +'portredir save to activate' =3D> 'Save to activate changes', +); + +#EOF diff --git a/config/portredir/portredir-backup b/config/portredir/portredir-b= ackup new file mode 100644 index 000000000..bd2ada742 --- /dev/null +++ b/config/portredir/portredir-backup @@ -0,0 +1 @@ +/var/ipfire/portredir diff --git a/config/portredir/portredir.cgi b/config/portredir/portredir.cgi new file mode 100644 index 000000000..4913dda3f --- /dev/null +++ b/config/portredir/portredir.cgi @@ -0,0 +1,525 @@ +#!/usr/bin/perl +############################################################################= ### +# = # +# IPFire.org - A linux based firewall = # +# Copyright (C) 2021 IPFire Team = # +# = # +# This program is free software: you can redistribute it and/or modify = # +# it under the terms of the GNU General Public License as published by = # +# the Free Software Foundation, either version 3 of the License, or = # +# (at your option) any later version. = # +# = # +# This program is distributed in the hope that it will be useful, = # +# but WITHOUT ANY WARRANTY; without even the implied warranty of = # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the = # +# GNU General Public License for more details. = # +# = # +# You should have received a copy of the GNU General Public License = # +# along with this program. If not, see . = # +# = # +############################################################################= ### + +use strict; + +# enable only the following on debugging purpose +use warnings; +use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; + +# File declarations +my $settingsfile =3D "${General::swroot}/portredir/settings"; +my $redirectsfile =3D "${General::swroot}/portredir/redirects"; + +# Create empty settingsfiles if they does not exist yet +unless (-e "$settingsfile") { system ("touch $settingsfile"); } +unless (-e "$redirectsfile") { system ("touch $redirectsfile"); } + +# load ipfire settings +our %netsettings =3D (); +our %color =3D (); +&General::readhash("${General::swroot}/ethernet/settings", \%netsettings); +&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", = \%color); + +my %settings=3D(); +my %portredirs=3D(); +my %checked=3D(); # Checkbox manipulations +my $errormessage=3D''; +my %selected=3D(); +our %redirects=3D(); + +$settings{'ACTION'} =3D ''; +$settings{'REDIR_ENABLE_ADDON'}=3D"off"; +$settings{'REDIR_CUSTOM_GREEN'}=3D"off"; +$settings{'REDIR_CUSTOM_BLUE'}=3D"off"; +$settings{'REDIR_CUSTOM_ORANGE'}=3D"off"; +$settings{'REDIR_DNS_GREEN'}=3D"off"; +$settings{'REDIR_NTP_GREEN'}=3D"off"; +$settings{'REDIR_DNS_BLUE'}=3D"off"; +$settings{'REDIR_NTP_BLUE'}=3D"off"; +$settings{'REDIR_DNS_ORANGE'}=3D"off"; +$settings{'REDIR_NTP_ORANGE'}=3D"off"; + +&Header::showhttpheaders(); + +# Get GUI values +&Header::getcgihash(\%settings); + +# Save action +if ($settings{'ACTION'} eq $Lang::tr{'save'}) { + + # If custom rules enabled, deactivate default rules on interface + if ($settings{'REDIR_CUSTOM_GREEN'} eq "on" ) { + $settings{'REDIR_DNS_GREEN'}=3D"off"; + $settings{'REDIR_NTP_GREEN'}=3D"off"; + } + + if ($settings{'REDIR_CUSTOM_BLUE'} eq "on" ) { + $settings{'REDIR_DNS_BLUE'}=3D"off"; + $settings{'REDIR_NTP_BLUE'}=3D"off"; + } + + if ($settings{'REDIR_CUSTOM_ORANGE'} eq "on" ) { + $settings{'REDIR_DNS_ORANGE'}=3D"off"; + $settings{'REDIR_NTP_ORANGE'}=3D"off"; + } + + &General::writehash($settingsfile, \%settings); + + if ($settings{'REDIR_ENABLE_ADDON'} eq "on") { + system ('/usr/local/bin/portredirctrl restart >/dev/null 2>&1'); + system ('/usr/local/bin/portredirctrl enable >/dev/null 2>&1'); + &General::log('portredir addon: port redirections enabled'); + } + if ($settings{'REDIR_ENABLE_ADDON'} eq "off") { + system ('/usr/local/bin/portredirctrl disable >/dev/null 2>&1'); + system ('/usr/local/bin/portredirctrl stop >/dev/null 2>&1'); + &General::log('portredir addon: port redirections disabled'); + } + +# Add/edit an entry to the redirectsfile. + +} elsif (($settings{'ACTION'} eq $Lang::tr{'add'}) || ($settings{'ACTION'} e= q $Lang::tr{'update'})) { + + # Check if any input has been performed. + if ($settings{'REDIR_ENTRY_ADDRESS'} ne '') { + + # Check if the given input is no valid IP-address, display an error messag= e. + if (!&General::validip($settings{'REDIR_ENTRY_ADDRESS'})) { + $errormessage =3D "$Lang::tr{'portredir invalid address'}"; + } + } else { + $errormessage =3D "$Lang::tr{'portredir empty input'}"; + } + + # Go further if there was no error. + if ($errormessage eq '') { + my %redirects =3D (); + my $id; + my $status; + + # Assign hash values. + my $new_entry_interface =3D $settings{'REDIR_ENTRY_INTERFACE'}; + my $new_entry_protocol =3D $settings{'REDIR_ENTRY_PROTOCOL'}; + my $new_entry_port =3D $settings{'REDIR_ENTRY_PORT'}; + my $new_entry_address =3D $settings{'REDIR_ENTRY_ADDRESS'}; + my $new_entry_remark =3D $settings{'REDIR_ENTRY_REMARK'}; + + # Read-in redirectsfile. + &General::readhasharray($redirectsfile, \%redirects); + + # Check if we should edit an existing entry and got an ID. + if (($settings{'ACTION'} eq $Lang::tr{'update'}) && ($settings{'ID'})) { + # Assin the provided id. + $id =3D $settings{'ID'}; + + # Undef the given ID. + undef($settings{'ID'}); + + # Grab the configured status of the corresponding entry. + $status =3D $redirects{$id}[4]; + } else { + # Each newly added entry automatically should be enabled. + $status =3D "enabled"; + + # Generate the ID for the new entry. + # + # Sort the keys by their ID and store them in an array. + my @keys =3D sort { $a <=3D> $b } keys %redirects; + + # Reverse the key array. + my @reversed =3D reverse(@keys); + + # Obtain the last used id. + my $last_id =3D @reversed[0]; + + # Increase the last id by one and use it as id for the new entry. + $id =3D ++$last_id; + } + + # Add/Modify the entry to/in the redirects hash. + $redirects{$id} =3D ["$new_entry_interface", "$new_entry_protocol", "$new_= entry_port", "$new_entry_address","$status", "$new_entry_remark"]; + + # Write the changed redirects hash to the redirects file. + &General::writehasharray($redirectsfile, \%redirects); + } + +# Toggle Enabled/Disabled for an existing entry on the redirects list. + +} elsif ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) { + my %redirects =3D (); + + # Only go further, if an ID has been passed. + if ($settings{'ID'}) { + # Assign the given ID. + my $id =3D $settings{'ID'}; + + # Undef the given ID. + undef($settings{'ID'}); + + # Read-in ignoredfile. + &General::readhasharray($redirectsfile, \%redirects); + + # Grab the configured status of the corresponding entry. + my $status =3D $redirects{$id}[4]; + + # Switch the status. + if ($status eq "disabled") { + $status =3D "enabled"; + } else { + $status =3D "disabled"; + } + + # Modify the status of the existing entry. + $redirects{$id} =3D ["$redirects{$id}[0]", "$redirects{$id}[1]", "$redirec= ts{$id}[2]", "$redirects{$id}[3]","$status", "$redirects{$id}[5]"]; + + # Write the changed ignored hash to the redirects file. + &General::writehasharray($redirectsfile, \%redirects); + } + +# Remove entry from redirects list. + +} elsif ($settings{'ACTION'} eq $Lang::tr{'remove'}) { + my %redirects =3D (); + + # Read-in redirectsfile. + &General::readhasharray($redirectsfile, \%redirects); + + # move data on key up + foreach my $key (sort keys %redirects) { + if ($key >=3D $settings{'ID'}) { + my $next =3D $key + 1; + if (exists $redirects{$next}) { + foreach my $i (0 .. $#{$redirects{$next}}) { $redirects{$key}[$i] =3D $r= edirects{$next}[$i]; } + } + } + } + + my $last_key =3D (sort {$a <=3D> $b} keys %redirects)[-1]; + delete $redirects{$last_key}; + + # Undef the given ID. + undef($settings{'ID'}); + + # Write the changed redirects hash to file. + &General::writehasharray($redirectsfile, \%redirects); +} + +# Load settings from file +&General::readhash($settingsfile, \%settings); +&General::readhasharray($redirectsfile, \%redirects); + +# Call functions to generate whole page. +&Header::openpage($Lang::tr{'portredir port redirections'}, 1, ''); +&Header::openbigbox('100%', 'left', '', $errormessage); + +if ($errormessage) { + &Header::openbox('100%', 'left', $Lang::tr{'warning messages'}); + print "$errormessage "; + &Header::closebox(); +} + +$checked{'REDIR_ENABLE_ADDON'}{'off'} =3D ''; +$checked{'REDIR_ENABLE_ADDON'}{'on'} =3D ''; +$checked{'REDIR_ENABLE_ADDON'}{$settings{'REDIR_ENABLE_ADDON'}} =3D "checked= =3D'checked'"; +$checked{'REDIR_CUSTOM_GREEN'}{'off'} =3D ''; +$checked{'REDIR_CUSTOM_GREEN'}{'on'} =3D ''; +$checked{'REDIR_CUSTOM_GREEN'}{$settings{'REDIR_CUSTOM_GREEN'}} =3D "checked= =3D'checked'"; +$checked{'REDIR_CUSTOM_BLUE'}{'off'} =3D ''; +$checked{'REDIR_CUSTOM_BLUE'}{'on'} =3D ''; +$checked{'REDIR_CUSTOM_BLUE'}{$settings{'REDIR_CUSTOM_BLUE'}} =3D "checked= =3D'checked'"; +$checked{'REDIR_CUSTOM_ORANGE'}{'off'} =3D ''; +$checked{'REDIR_CUSTOM_ORANGE'}{'on'} =3D ''; +$checked{'REDIR_CUSTOM_ORANGE'}{$settings{'REDIR_CUSTOM_ORANGE'}} =3D "check= ed=3D'checked'"; +$checked{'REDIR_DNS_GREEN'}{'off'} =3D ''; +$checked{'REDIR_DNS_GREEN'}{'on'} =3D ''; +$checked{'REDIR_DNS_GREEN'}{$settings{'REDIR_DNS_GREEN'}} =3D "checked=3D'ch= ecked'"; +$checked{'REDIR_NTP_GREEN'}{'off'} =3D ''; +$checked{'REDIR_NTP_GREEN'}{'on'} =3D ''; +$checked{'REDIR_NTP_GREEN'}{$settings{'REDIR_NTP_GREEN'}} =3D "checked=3D'ch= ecked'"; +$checked{'REDIR_DNS_BLUE'}{'off'} =3D ''; +$checked{'REDIR_DNS_BLUE'}{'on'} =3D ''; +$checked{'REDIR_DNS_BLUE'}{$settings{'REDIR_DNS_BLUE'}} =3D "checked=3D'chec= ked'"; +$checked{'REDIR_NTP_BLUE'}{'off'} =3D ''; +$checked{'REDIR_NTP_BLUE'}{'on'} =3D ''; +$checked{'REDIR_NTP_BLUE'}{$settings{'REDIR_NTP_BLUE'}} =3D "checked=3D'chec= ked'"; +$checked{'REDIR_DNS_ORANGE'}{'off'} =3D ''; +$checked{'REDIR_DNS_ORANGE'}{'on'} =3D ''; +$checked{'REDIR_DNS_ORANGE'}{$settings{'REDIR_DNS_ORANGE'}} =3D "checked=3D'= checked'"; +$checked{'REDIR_NTP_ORANGE'}{'off'} =3D ''; +$checked{'REDIR_NTP_ORANGE'}{'on'} =3D ''; +$checked{'REDIR_NTP_ORANGE'}{$settings{'REDIR_NTP_ORANGE'}} =3D "checked=3D'= checked'"; + +$selected{'REDIR_ENTRY_INTERFACE'}{$settings{'REDIR_ENTRY_INTERFACE'}} =3D '= selected'; +$selected{'REDIR_ENTRY_PROTOCOL'}{$settings{'REDIR_ENTRY_PROTOCOL'}} =3D 'se= lected'; + +&showMainBox(); +&showRedirectsBox(); + +&Header::closebigbox(); +&Header::closepage(); + +# Function to show main settings and options. +sub showMainBox() { + + &Header::openbox('100%', 'center', "$Lang::tr{'settings'}"); + print "
"; + +print < + $Lang= ::tr{'portredir common settings'} + $Lang::tr{'portredir enable addon'}: + + + +   +END + + # create html table with header line 1 + print ""; + print ""; + if ($netsettings{'GREEN_DEV'}) {print ""; + } else { print ""; } + if ($netsettings{'BLUE_DEV'}) {print ""; + } else { print ""; } + if ($netsettings{'ORANGE_DEV'}) {print ""; + } else { print ""; } + + # the empty right row + print ""; + + # line 2 + print ""; + if ($netsettings{'GREEN_DEV'}) {print "";} else { print "";} + if ($netsettings{'BLUE_DEV'}) {print "";} else { print "";} + if ($netsettings{'ORANGE_DEV'}) {print "";} else { print "";} + + # line 3 + print ""; + if ($netsettings{'GREEN_DEV'}) {print "";} else { print "";} + if ($netsettings{'BLUE_DEV'}) {print "";} else { print "";} + if ($netsettings{'ORANGE_DEV'}) {print "";} else { print "";} + + # line 4 + print ""; + if ($netsettings{'GREEN_DEV'}) {print "";} else { print "";} + if ($netsettings{'BLUE_DEV'}) {print "";} else { print "";} + if ($netsettings{'ORANGE_DEV'}) {print "";} else { print "";} + + print <
$Lang::tr{'portre= dir fw for interface'}$Lang::tr{'green'}$Lang::tr{'blue'}$Lang::tr{'orange'}
$Lang::tr{'portredir force local dns'}
$Lang::tr{'portredir force local ntp'}
$Lang::tr{'portredir enable user redirections'}
+ + + = +
 
$Lang::tr{'portredir save to activate'}
+END + +&Header::closebox(); +} + +# Function to show elements of the redirects file and allow to add or remove= single members of it. +sub showRedirectsBox() { + &Header::openbox('100%', 'center', "$Lang::tr{'portredir custom redi= rections'}"); + + print < + + $La= ng::tr{'interface'} + $La= ng::tr{'protocol'} + $La= ng::tr{'port'} + $La= ng::tr{'ip address'} + $La= ng::tr{'remark'} + + +END + # Check if some rules have been added to be redirects. + if (keys (%redirects)) { + my $col =3D ""; + + # List all entries of the hash. + foreach my $key (sort keys %redirects){ + + # Assign data array positions to some nice variable names. + my $interface =3D $redirects{$key}[0]; + my $protocol =3D $redirects{$key}[1]; + my $port =3D $redirects{$key}[2]; + my $address =3D $redirects{$key}[3]; + my $status =3D $redirects{$key}[4]; + my $remark =3D $redirects{$key}[5]; + + # Check if the key (id) number is even or not. + if ($settings{'ID'} eq $key) { + $col=3D"bgcolor=3D'${Header::colouryellow}'"; + } elsif ($key % 2) { + $col=3D"bgcolor=3D'$color{'color22'}'"; + } else { + $col=3D"bgcolor=3D'$color{'color20'}'"; + } + + # Choose icon for the checkbox. + my $gif; + my $gdesc; + + # Check if the status is enabled and select the correct image and descr= iption. + if ($status eq 'enabled' ) { + $gif =3D 'on.gif'; + $gdesc =3D $Lang::tr{'click to disable'}; + } else { + $gif =3D 'off.gif'; + $gdesc =3D $Lang::tr{'click to enable'}; + } + + print < + $Lang::tr{$interface} + $protocol + $port +  $address<= /td> +  $remark + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ + +END + } + } else { + # Print notice that currently no ports are redirected. + print "\n"; + print "$Lang::tr{'portredir no entries'= }\n"; + print "\n"; + } + + print "\n"; + + # Section to add new elements or edit existing ones. + print < +
+
+
+ +END + + # Assign correct headline and button text. + my $buttontext; + my $entry_interface; + my $entry_protocol; + my $entry_port; + my $entry_address; + my $entry_remark; + + # Check if an ID (key) has been given, in this case an existing entry shoul= d be edited. + if ($settings{'ID'} ne '') { + $buttontext =3D $Lang::tr{'update'}; + print "\n"; + + # Grab address and remark for the given key. + $entry_interface =3D $redirects{$settings{'ID'}}[0]; + $entry_protocol =3D $redirects{$settings{'ID'}}[1]; + $entry_port =3D $redirects{$settings{'ID'}}[2]; + $entry_address =3D $redirects{$settings{'ID'}}[3]; + $entry_remark =3D $redirects{$settings{'ID'}}[5]; + + } else { + $buttontext =3D $Lang::tr{'add'}; + print "\n"; + print "\n"; + } + + print < + + + + + + + + + + + + + + + + + + + + + + +
$Lang::tr{'update'}=
$Lang::tr{'dnsforward = add a new entry'}
 
$Lang::tr{'interface'}$Lang::tr{'protocol'} $Lang::tr{'port'} $Lang::tr{'ip address'} $Lang::tr{'remark'}
+
+END + &Header::closebox(); +} diff --git a/config/rootfiles/common/misc-progs b/config/rootfiles/common/mis= c-progs index d6594b3f8..fbad2af8b 100644 --- a/config/rootfiles/common/misc-progs +++ b/config/rootfiles/common/misc-progs @@ -17,6 +17,7 @@ usr/local/bin/logwatch #usr/local/bin/mpfirectrl usr/local/bin/openvpnctrl usr/local/bin/pakfire +#usr/local/bin/portredirctrl usr/local/bin/qosctrl usr/local/bin/rebuildhosts usr/local/bin/rebuildroutes diff --git a/config/rootfiles/packages/portredir b/config/rootfiles/packages/= portredir new file mode 100644 index 000000000..4b4ba8366 --- /dev/null +++ b/config/rootfiles/packages/portredir @@ -0,0 +1,11 @@ +etc/rc.d/init.d/portredir +etc/rc.d/rc0.d/K77portredir +etc/rc.d/rc3.d/S23portredir +etc/rc.d/rc6.d/K77portredir +srv/web/ipfire/cgi-bin/portredir.cgi +usr/local/bin/portredirctrl +var/ipfire/addon-lang/portredir.de.pl +var/ipfire/addon-lang/portredir.en.pl +var/ipfire/backup/addons/includes/portredir +var/ipfire/menu.d/EX-portredir.menu +var/ipfire/portredir diff --git a/lfs/portredir b/lfs/portredir new file mode 100644 index 000000000..a4911f71f --- /dev/null +++ b/lfs/portredir @@ -0,0 +1,85 @@ +############################################################################= ### +# = # +# IPFire.org - A linux based firewall = # +# Copyright (C) 2007-2021 IPFire Team = # +# = # +# This program is free software: you can redistribute it and/or modify = # +# it under the terms of the GNU General Public License as published by = # +# the Free Software Foundation, either version 3 of the License, or = # +# (at your option) any later version. = # +# = # +# This program is distributed in the hope that it will be useful, = # +# but WITHOUT ANY WARRANTY; without even the implied warranty of = # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the = # +# GNU General Public License for more details. = # +# = # +# You should have received a copy of the GNU General Public License = # +# along with this program. If not, see . = # +# = # +############################################################################= ### + +############################################################################= ### +# Definitions +############################################################################= ### + +include Config + +VER =3D 1.0 + +THISAPP =3D portredir-$(VER) +DIR_APP =3D $(DIR_SRC)/$(THISAPP) +TARGET =3D $(DIR_INFO)/$(THISAPP) +PROG =3D portredir +PAK_VER =3D 1 + +############################################################################= ### +# Top-level Rules +############################################################################= ### + +install : $(TARGET) + +check : + +download : + +md5 : + +dist:=20 + @$(PAK) + +############################################################################= ### +# Installation Details +############################################################################= ### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) + + #install cgi=20 + install -v -m 755 $(DIR_CONF)/portredir/portredir.cgi /srv/web/ipfire/cgi-b= in/ + + #create configuration dir=20 + -mkdir -pv /var/ipfire/portredir/ + chown -R nobody:nobody /var/ipfire/portredir/ + + # Install include file for backup + install -v -m 644 $(DIR_CONF)/portredir/portredir-backup /var/ipfire/backup= /addons/includes/portredir + + # Install menu file + install -v -m 644 $(DIR_CONF)/portredir/EX-portredir.menu /var/ipfire/menu.= d/ + chown nobody:nobody /var/ipfire/menu.d/EX-portredir.menu + + # Install addon-specific language-files + install -v -m 644 $(DIR_CONF)/portredir/lang/portredir.*.pl /var/ipfire/add= on-lang/ + + #install initscripts + $(call INSTALL_INITSCRIPT,portredir) + + # Create symlinks for runlevel interaction. + ln -svf /etc/rc.d/init.d/portredir /etc/rc.d/rc3.d/S23portredir + ln -svf /etc/rc.d/init.d/portredir /etc/rc.d/rc0.d/K77portredir + ln -svf /etc/rc.d/init.d/portredir /etc/rc.d/rc6.d/K77portredir + + @rm -rf $(DIR_APP) + @$(POSTBUILD) + diff --git a/make.sh b/make.sh index fc03ebcd5..ab9fe881a 100755 --- a/make.sh +++ b/make.sh @@ -1623,6 +1623,7 @@ buildipfire() { lfsmake2 socat lfsmake2 libcdada lfsmake2 pmacct + lfsmake2 portredir } =20 buildinstaller() { diff --git a/src/initscripts/packages/portredir b/src/initscripts/packages/po= rtredir new file mode 100644 index 000000000..cc57fb9cc --- /dev/null +++ b/src/initscripts/packages/portredir @@ -0,0 +1,191 @@ +#!/bin/sh +######################################################################## +# Begin $rc_base/init.d/portredir +# +# Description : portredir init script for DNS/NTP and custom=20 +# port redirection rules +# +######################################################################## + +. /etc/sysconfig/rc +. ${rc_functions} + +IPT=3D"/sbin/iptables"; +parent_chain=3D"PREROUTING"; +chain=3D"PORT_REDIRECT"; + +confdir=3D"/var/ipfire/portredir"; +settingsfile=3D"${confdir}/settings"; +redirectsfile=3D"${confdir}/redirects"; +SYSLOG=3D"NO"; +VERBOSE=3D"NO"; + +eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings); +eval $(/usr/local/bin/readhash ${settingsfile}); + +logtext() { + if [ "${SYSLOG}" =3D "YES" ]; then logger -t "portredir" ${1}; fi; + if [ "${VERBOSE}" =3D "YES" ]; then echo ${1}; fi;} + +create_chain() { + + local line=3D$(${IPT} -t nat -L ${parent_chain} --line-numbers |grep "SQUID= " |awk '{printf($1)}'); + + if [[ "${REDIR_ENABLE_ADDON}" =3D=3D "off" || -z "${REDIR_ENABLE_ADDON}" ]]= ; then + logtext "addon not enabled in web interface..."; + echo "Portredir addon not enabled in web interface..."; + exit 0; + fi; + + if [ -z "$(${IPT} -t nat -L ${parent_chain} |grep ${chain})" ]; then + ${IPT} -t nat -N ${chain}; + + if [ ! -z "${line}" ]; then + logtext "create chain ${chain} and link in ${parent_chain} at position ${= line}..."; + ${IPT} -t nat -I ${parent_chain} ${line} -j ${chain}; + else + logtext "create chain ${chain} and link in ${parent_chain} at last positi= on..."; + ${IPT} -t nat -A ${parent_chain} -j ${chain}; + fi + else + return 1; + fi; + return 0; +} + +remove_chain() { + if [ ! -z "$(${IPT} -t nat -L ${parent_chain} |grep ${chain})" ]; then + logtext "remove chain ${chain} and link in ${parent_chain} from system..."; + ${IPT} -t nat -D "${parent_chain}" -j ${chain}; + ${IPT} -t nat -F ${chain}; + ${IPT} -t nat -X ${chain}; + else + return 1; + fi; + return 0; +} + +activate_custom_redirections() { +=09 + local array=3D(); + local redirects=3D(); + local i; + index=3D(); + iface=3D(); + protocol=3D(); + port=3D(); + targetip=3D(); + enabled=3D(); + + IFS=3D$'\n' read -d '' -ra redirects < ${redirectsfile}; + + for i in "${!redirects[@]}" + do + IFS=3D$',' read -ra array <<< ${redirects[i]}; + index[i]=3D${array[0]}; + iface[i]=3D${array[1]}; + protocol[i]=3D${array[2]}; + port[i]=3D${array[3]}; + targetip[i]=3D${array[4]}; + enabled[i]=3D${array[5]}; + done + + for i in "${!index[@]}" + do + if [[ ! -z "${GREEN_DEV}" && "${iface[i]}" =3D "green" && "${enabled[i]}"= =3D "enabled" ]]; then + + logtext "add redirect in ${chain} on ${GREEN_DEV} ip ${targetip[i]} proto= col ${protocol[i]} port ${port[i]} "; + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d ${targetip[i]} -p ${protocol= [i]} -m ${protocol[i]} --dport ${port[i]} -j RETURN; + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p ${protocol[i]} -m ${protocol= [i]} --dport ${port[i]} -j REDIRECT; + fi + if [[ ! -z "${BLUE_DEV}" && "${iface[i]}" =3D "blue" && "${enabled[i]}" = =3D "enabled" ]]; then + logtext "add redirect in ${chain} on ${BLUE_DEV} ip ${targetip[i]} protoc= ol ${protocol[i]} port ${port[i]} "; + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d ${targetip[i]} -p ${protocol[= i]} -m ${protocol[i]} --dport ${port[i]} -j RETURN; + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p ${protocol[i]} -m ${protocol[= i]} --dport ${port[i]} -j REDIRECT; + fi + if [[ ! -z "${ORANGE_DEV}" && "${iface[i]}" =3D "orange" && "${enabled[i]= }" =3D "enabled" ]]; then + logtext "add redirect in ${chain} on ${ORANGE_DEV} ip ${targetip[i]} prot= ocol ${protocol[i]} port ${port[i]} "; + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d ${targetip[i]} -p ${protoco= l[i]} -m ${protocol[i]} --dport ${port[i]} -j RETURN; + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p ${protocol[i]} -m ${protoco= l[i]} --dport ${port[i]} -j REDIRECT; + fi + done + unset array redirects i index iface protocol port targetip enabled; + return 0; +} + +activate_redirections() { + + if ! create_chain; then return 1; fi; +=09 + # Force DNS REDIRECTs on GREEN (udp, tcp, 53) + if [[ "${REDIR_DNS_GREEN}" =3D=3D "on" && "${REDIR_CUSTOM_GREEN}" =3D "off= " ]]; then + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d ${GREEN_ADDRESS} -p udp -m ud= p --dport domain -j RETURN; + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p udp -m udp --dport domain -j = REDIRECT; + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d ${GREEN_ADDRESS} -p tcp -m tc= p --dport domain -j RETURN; + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p tcp -m tcp --dport domain -j = REDIRECT; + fi + + # Force DNS REDIRECTs on BLUE (udp, tcp, 53) + if [[ "${REDIR_DNS_BLUE}" =3D=3D "on" && "${REDIR_CUSTOM_BLUE}" =3D "off" = ]]; then + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d ${BLUE_ADDRESS} -p udp -m udp = --dport domain -j RETURN + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p udp -m udp --dport domain -j R= EDIRECT + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d ${BLUE_ADDRESS} -p tcp -m tcp = --dport domain -j RETURN + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p tcp -m tcp --dport domain -j R= EDIRECT + fi + + # Force DNS REDIRECTs on ORANGE (udp, tcp, 53) + if [[ "${REDIR_DNS_ORANGE}" =3D=3D "on" && "${REDIR_CUSTOM_ORANGE}" =3D "o= ff" ]]; then + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d ${ORANGE_ADDRESS} -p udp -m = udp --dport domain -j RETURN + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p udp -m udp --dport domain -j= REDIRECT + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d ${ORANGE_ADDRESS} -p tcp -m = tcp --dport domain -j RETURN + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p tcp -m tcp --dport domain -j= REDIRECT + fi + + # Force NTP REDIRECTs on GREEN (udp, 123) + if [[ "${REDIR_NTP_GREEN}" =3D=3D "on" && "${REDIR_CUSTOM_GREEN}" =3D "off= " ]]; then + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -d ${GREEN_ADDRESS} -p udp -m ud= p --dport ntp -j RETURN + ${IPT} -t nat -A ${chain} -i ${GREEN_DEV} -p udp -m udp --dport ntp -j RED= IRECT + fi + + # Force NTP REDIRECTs on BLUE (udp, 123) + if [[ "${REDIR_NTP_BLUE}" =3D=3D "on" && "${REDIR_CUSTOM_BLUE}" =3D "off" = ]]; then + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -d ${BLUE_ADDRESS} -p udp -m udp = --dport ntp -j RETURN + ${IPT} -t nat -A ${chain} -i ${BLUE_DEV} -p udp -m udp --dport ntp -j REDI= RECT + fi + + # Force NTP REDIRECTs on ORANGE (udp, 123) + if [[ "${REDIR_NTP_ORANGE}" =3D=3D "on" && "${REDIR_CUSTOM_ORANGE}" =3D "o= ff" ]]; then + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -d ${ORANGE_ADDRESS} -p udp -m = udp --dport ntp -j RETURN + ${IPT} -t nat -A ${chain} -i ${ORANGE_DEV} -p udp -m udp --dport ntp -j RE= DIRECT + fi + + if ! activate_custom_redirections; then return 1; fi; + + return 0; +} + +case "${1}" in + start) + boot_mesg "Loading port redirections..." + activate_redirections; + evaluate_retval; + ;; + + stop)=09 + boot_mesg "Removing port redirections..." + remove_chain; + evaluate_retval; + ;; + + restart) + ${0} stop + ${0} start + ;; + + *) + echo "Usage: ${0} {start|stop|restart}" + exit 1 + ;; +esac + +# End $rc_base/init.d/portredir diff --git a/src/misc-progs/Makefile b/src/misc-progs/Makefile index 7c3ef7529..850f8fdcc 100644 --- a/src/misc-progs/Makefile +++ b/src/misc-progs/Makefile @@ -30,7 +30,7 @@ SUID_PROGS =3D squidctrl sshctrl ipfirereboot \ wirelessctrl getipstat qosctrl \ redctrl syslogdctrl extrahdctrl sambactrl \ smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl \ - setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes \ + setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes portredi= rctrl \ getconntracktable wirelessclient torctrl ddnsctrl unboundctrl \ captivectrl =20 diff --git a/src/misc-progs/portredirctrl.c b/src/misc-progs/portredirctrl.c new file mode 100644 index 000000000..7897d711c --- /dev/null +++ b/src/misc-progs/portredirctrl.c @@ -0,0 +1,47 @@ +/* This file is part of the IPFire Firewall. + * + * This program is distributed under the terms of the GNU General Public + * Licence. See the file COPYING for details. + * + */ + +#include +#include +#include +#include +#include +#include +#include "setuid.h" + +int main(int argc, char *argv[]) { + if (!(initsetuid())) + exit(1); + + // Check what command is asked + if (argc < 2) { + fprintf(stderr, "\nNo argument given.\n\nportredirctrl (star= t|stop|restart|enable|disable)\n\n"); + exit(1); + } + + if (strcmp(argv[1], "start") =3D=3D 0) { + safe_system("/etc/rc.d/init.d/portredir start"); + } else if (strcmp(argv[1], "stop") =3D=3D 0) { + safe_system("/etc/rc.d/init.d/portredir stop"); + } else if (strcmp(argv[1], "restart") =3D=3D 0) { + safe_system("/etc/rc.d/init.d/portredir restart"); + } else if (strcmp(argv[1], "enable") =3D=3D 0) { + safe_system("touch /var/ipfire/portredir/enable"); + safe_system("ln -snf /etc/rc.d/init.d/portredir /etc/rc.d/rc3.d/S23portred= ir >/dev/null 2>&1"); + safe_system("ln -snf /etc/rc.d/init.d/portredir /etc/rc.d/rc0.d/K77portred= ir >/dev/null 2>&1"); + safe_system("ln -snf /etc/rc.d/init.d/portredir /etc/rc.d/rc6.d/K77portred= ir >/dev/null 2>&1"); + } else if (strcmp(argv[1], "disable") =3D=3D 0) { + safe_system("/etc/rc.d/init.d/portredir stop"); + safe_system("unlink /var/ipfire/portredir/enable"); + safe_system("rm -rf /etc/rc.d/rc*.d/*portredir >/dev/null 2>&1"); + } else { + fprintf(stderr, "\nBad argument given.\n\nportredirctrl (sta= rt|stop|restart|enable|disable)\n\n"); + exit(1); + } + + return 0; +} diff --git a/src/paks/portredir/install.sh b/src/paks/portredir/install.sh new file mode 100644 index 000000000..9f69aeae2 --- /dev/null +++ b/src/paks/portredir/install.sh @@ -0,0 +1,32 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2021 IPFire-Team . = # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +extract_files +restore_backup ${NAME} + +/usr/local/bin/update-lang-cache + +chown root:nobody /usr/local/bin/portredirctrl +chmod 4750 /usr/local/bin/portredirctrl +chmod u+s /usr/local/bin/portredirctrl diff --git a/src/paks/portredir/uninstall.sh b/src/paks/portredir/uninstall.sh new file mode 100644 index 000000000..df9270125 --- /dev/null +++ b/src/paks/portredir/uninstall.sh @@ -0,0 +1,28 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2007 IPFire-Team . = # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +make_backup ${NAME} +remove_files + +/usr/local/bin/update-lang-cache diff --git a/src/paks/portredir/update.sh b/src/paks/portredir/update.sh new file mode 100644 index 000000000..89c40d0d7 --- /dev/null +++ b/src/paks/portredir/update.sh @@ -0,0 +1,26 @@ +#!/bin/bash +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2007 IPFire-Team . = # +# # +############################################################################ +# +. /opt/pakfire/lib/functions.sh +./uninstall.sh +./install.sh --=20 2.18.0 --===============8917162308055464818==--