[v2] misc-progs: getipstat: Refactor + extend

Message ID 20210427200732.6830-1-robin.roevens@disroot.org
State Accepted
Headers
Series [v2] misc-progs: getipstat: Refactor + extend |

Commit Message

Robin Roevens April 27, 2021, 8:07 p.m. UTC
  * Return output of iptables directly instead of writing it to files.
 * Make iptables wait for 5s if xtables is locked by another iptables
 process. (--wait 5 argument)
 * Add optional parameter "-x" to have iptables report exact numbers.
 * Add optional parameter "-f" to display  the filter table  (default).
 * Add optional parameter "-n" to display the nat table.
 * Add optional parameter "-m" to display the mangle table.
  * Adapt iptables.cgi and guardian.cgi to catch getipstat output
  instead of reading temp-files.

Signed-off-by: Robin Roevens <robin.roevens@disroot.org>
---
 html/cgi-bin/guardian.cgi  | 12 ++-----
 html/cgi-bin/iptables.cgi  | 18 ++++------
 src/misc-progs/getipstat.c | 67 +++++++++++++++++++++++++++++++++-----
 3 files changed, 66 insertions(+), 31 deletions(-)
  

Comments

Michael Tremer May 4, 2021, 2:49 p.m. UTC | #1
Hello,

Thank you. This looks very good and I merged it into next.

Best,
-Michael

> On 27 Apr 2021, at 21:07, Robin Roevens <robin.roevens@disroot.org> wrote:
> 
> * Return output of iptables directly instead of writing it to files.
> * Make iptables wait for 5s if xtables is locked by another iptables
> process. (--wait 5 argument)
> * Add optional parameter "-x" to have iptables report exact numbers.
> * Add optional parameter "-f" to display  the filter table  (default).
> * Add optional parameter "-n" to display the nat table.
> * Add optional parameter "-m" to display the mangle table.
>  * Adapt iptables.cgi and guardian.cgi to catch getipstat output
>  instead of reading temp-files.
> 
> Signed-off-by: Robin Roevens <robin.roevens@disroot.org>
> ---
> html/cgi-bin/guardian.cgi  | 12 ++-----
> html/cgi-bin/iptables.cgi  | 18 ++++------
> src/misc-progs/getipstat.c | 67 +++++++++++++++++++++++++++++++++-----
> 3 files changed, 66 insertions(+), 31 deletions(-)
> 
> diff --git a/html/cgi-bin/guardian.cgi b/html/cgi-bin/guardian.cgi
> index fb16be00e..552c67211 100644
> --- a/html/cgi-bin/guardian.cgi
> +++ b/html/cgi-bin/guardian.cgi
> @@ -829,12 +829,9 @@ sub GetBlockedHosts() {
> 	my @hosts;
> 
> 	# Launch helper to get chains from iptables.
> -	system('/usr/local/bin/getipstat');
> +	open (FILE, '/usr/local/bin/getipstat | ');
> 
> -	# Open temporary file which contains the chains and rules.
> -	open (FILE, '/var/tmp/iptables.txt');
> -
> -	# Loop through the entire file.
> +	# Loop through the entire output.
> 	while (<FILE>) {
> 		my $line = $_;
> 
> @@ -864,11 +861,6 @@ sub GetBlockedHosts() {
> 	# Close filehandle.
> 	close(FILE);
> 
> -	# Remove recently created temporary files of the "getipstat" binary.
> -	system("rm -f /var/tmp/iptables.txt");
> -	system("rm -f /var/tmp/iptablesmangle.txt");
> -	system("rm -f /var/tmp/iptablesnat.txt");
> -
> 	# Convert entries, sort them, write back and store the sorted entries into new array.
> 	my @sorted = map  { $_->[0] }
>              sort { $a->[1] <=> $b->[1] }
> diff --git a/html/cgi-bin/iptables.cgi b/html/cgi-bin/iptables.cgi
> index b52d74fcf..f900562d9 100644
> --- a/html/cgi-bin/iptables.cgi
> +++ b/html/cgi-bin/iptables.cgi
> @@ -44,8 +44,6 @@ my %cgiparams=();
> 
> &Header::getcgihash(\%cgiparams);
> 
> -system('/usr/local/bin/getipstat');
> -
> &Header::showhttpheaders();
> &Header::openpage($Lang::tr{'ipts'}, 1, '');
> &Header::openbigbox('100%', 'LEFT');
> @@ -84,11 +82,11 @@ print <<END
> END
> ;
> 
> -# We´ll open the txt files and extract each line, if the line
> +# We´ll get iptables output and examine each line, if the line
> # start with an Chain the the name, start- and endline of the
> # chain is extracted into a hash
> 
> -	open (FILE, '/var/tmp/iptables.txt');
> +	open (FILE, '/usr/local/bin/getipstat | ');
> 	while (<FILE>){
> 
> 		$iplines[$lines] = $_;
> @@ -206,11 +204,11 @@ print <<END
> END
> ;
> 
> -# We´ll open the txt files and extract each line, if the line
> +# We´ll get iptables output and examine each line, if the line
> # start with an Chain the the name, start- and endline of the
> # chain is extracted into a hash
> 
> -	open (FILE, '/var/tmp/iptablesmangle.txt');
> +	open (FILE, '/usr/local/bin/getipstat -m | ');
> 	while (<FILE>){
> 
> 		$ipmlines[$manlines] = $_;
> @@ -333,11 +331,11 @@ print <<END
> END
> ;
> 
> -# We´ll open the txt files and extract each line, if the line
> +# We´ll get iptables output and examine each line, if the line
> # start with an Chain the the name, start- and endline of the
> # chain is extracted into a hash
> 
> -	open (FILE, '/var/tmp/iptablesnat.txt');
> +	open (FILE, '/usr/local/bin/getipstat -n | ');
> 	while (<FILE>){
> 
> 		$ipnatlines[$natlines] = $_;
> @@ -433,7 +431,3 @@ print "</table></div><br />";
> &Header::closebox();
> &Header::closebigbox();
> &Header::closepage();
> -
> -system("rm -f /var/tmp/iptables.txt");
> -system("rm -f /var/tmp/iptablesmangle.txt");
> -system("rm -f /var/tmp/iptablesnat.txt");
> diff --git a/src/misc-progs/getipstat.c b/src/misc-progs/getipstat.c
> index c806d54a9..99d053bbf 100644
> --- a/src/misc-progs/getipstat.c
> +++ b/src/misc-progs/getipstat.c
> @@ -2,6 +2,15 @@
>  *
>  * Get the list from IPTABLES -L
>  * 
> + * Optional commandline parameters:
> + *  -x 
> + *   instruct iptables to expand numbers
> + *  -f 
> + *   display filter table 
> + *  -n
> + *   display nat table
> + *  -m
> + *   display mangle table
>  */
> 
> #include <stdio.h>
> @@ -9,20 +18,60 @@
> #include <unistd.h>
> #include <stdlib.h>
> #include <sys/types.h>
> -#include <fcntl.h>
> #include "setuid.h"
> 
> -
> -int main(void)
> +int main(int argc, char** argv)
> {
> +	// Set defaults
> +	// first argument has to be "iptables" since execve executes the program pointed to by filename
> +	// but /sbin/iptables is actually a symlink to /sbin/xtables-legacy-multi hence that program is executed
> +	// however without the notion that it was called as "iptables". So we have to pass "iptables" as first
> +	// argument.
> +	char *args[10] = {"iptables", "--list", "--verbose", "--numeric", "--wait", "5", NULL, NULL, NULL, NULL};
> +	char *usage = "getipstat [-x][-f|-n|-m]";
> +	unsigned int pcount = 6;
> +	unsigned int table_set = 0;
> +
> +	int opt;
> +	
> 	if (!(initsetuid()))
> 		exit(1);
> 
> -	safe_system("/sbin/iptables -L -v -n > /var/tmp/iptables.txt");
> -	safe_system("/sbin/iptables -L -v -n -t nat > /var/tmp/iptablesnat.txt");
> -	safe_system("/sbin/iptables -t mangle -L -v -n > /var/tmp/iptablesmangle.txt");
> -	safe_system("chown nobody.nobody /var/tmp/iptables.txt /var/tmp/iptablesnat.txt /var/tmp/iptablesmangle.txt");
> -	
> -	return 0;
> +	// Parse command line arguments
> +	if (argc > 1) {
> +		while ((opt = getopt(argc, argv, "xfnm")) != -1) {
> +			switch(opt) {
> +				case 'x':
> +					args[pcount++] = "--exact";
> +					break;
> +				case 'f':
> +					table_set++;
> +					break;
> +				case 'n':
> +					if (table_set == 0) {
> +						args[pcount++] = "--table";
> +						args[pcount++] = "nat";
> +					}
> +					table_set++;
> +					break;
> +				case 'm':
> +					if (table_set == 0) {
> +						args[pcount++] = "--table";
> +						args[pcount++] = "mangle";
> +					}
> +					table_set++;
> +					break;
> +				default:
> +					fprintf(stderr, "\nBad argument given.\n\n%s\n", usage);
> +					exit(1);
> +			}
> +		}
> +		if (table_set > 1) {
> +			fprintf(stderr, "\nArguments -f/-n/-m are mutualy exclusive.\n\n%s\n", usage);
> +			exit(1);
> +		}
> +	}
> +
> +	return run("/sbin/iptables", args);
> }
> 
> -- 
> 2.31.1
> 
> 
> -- 
> Dit bericht is gescanned op virussen en andere gevaarlijke
> inhoud door MailScanner en lijkt schoon te zijn.
>
  

Patch

diff --git a/html/cgi-bin/guardian.cgi b/html/cgi-bin/guardian.cgi
index fb16be00e..552c67211 100644
--- a/html/cgi-bin/guardian.cgi
+++ b/html/cgi-bin/guardian.cgi
@@ -829,12 +829,9 @@  sub GetBlockedHosts() {
 	my @hosts;
 
 	# Launch helper to get chains from iptables.
-	system('/usr/local/bin/getipstat');
+	open (FILE, '/usr/local/bin/getipstat | ');
 
-	# Open temporary file which contains the chains and rules.
-	open (FILE, '/var/tmp/iptables.txt');
-
-	# Loop through the entire file.
+	# Loop through the entire output.
 	while (<FILE>) {
 		my $line = $_;
 
@@ -864,11 +861,6 @@  sub GetBlockedHosts() {
 	# Close filehandle.
 	close(FILE);
 
-	# Remove recently created temporary files of the "getipstat" binary.
-	system("rm -f /var/tmp/iptables.txt");
-	system("rm -f /var/tmp/iptablesmangle.txt");
-	system("rm -f /var/tmp/iptablesnat.txt");
-
 	# Convert entries, sort them, write back and store the sorted entries into new array.
 	my @sorted = map  { $_->[0] }
              sort { $a->[1] <=> $b->[1] }
diff --git a/html/cgi-bin/iptables.cgi b/html/cgi-bin/iptables.cgi
index b52d74fcf..f900562d9 100644
--- a/html/cgi-bin/iptables.cgi
+++ b/html/cgi-bin/iptables.cgi
@@ -44,8 +44,6 @@  my %cgiparams=();
 
 &Header::getcgihash(\%cgiparams);
 
-system('/usr/local/bin/getipstat');
-
 &Header::showhttpheaders();
 &Header::openpage($Lang::tr{'ipts'}, 1, '');
 &Header::openbigbox('100%', 'LEFT');
@@ -84,11 +82,11 @@  print <<END
 END
 ;
 
-# We´ll open the txt files and extract each line, if the line
+# We´ll get iptables output and examine each line, if the line
 # start with an Chain the the name, start- and endline of the
 # chain is extracted into a hash
 
-	open (FILE, '/var/tmp/iptables.txt');
+	open (FILE, '/usr/local/bin/getipstat | ');
 	while (<FILE>){
 
 		$iplines[$lines] = $_;
@@ -206,11 +204,11 @@  print <<END
 END
 ;
 
-# We´ll open the txt files and extract each line, if the line
+# We´ll get iptables output and examine each line, if the line
 # start with an Chain the the name, start- and endline of the
 # chain is extracted into a hash
 
-	open (FILE, '/var/tmp/iptablesmangle.txt');
+	open (FILE, '/usr/local/bin/getipstat -m | ');
 	while (<FILE>){
 
 		$ipmlines[$manlines] = $_;
@@ -333,11 +331,11 @@  print <<END
 END
 ;
 
-# We´ll open the txt files and extract each line, if the line
+# We´ll get iptables output and examine each line, if the line
 # start with an Chain the the name, start- and endline of the
 # chain is extracted into a hash
 
-	open (FILE, '/var/tmp/iptablesnat.txt');
+	open (FILE, '/usr/local/bin/getipstat -n | ');
 	while (<FILE>){
 
 		$ipnatlines[$natlines] = $_;
@@ -433,7 +431,3 @@  print "</table></div><br />";
 &Header::closebox();
 &Header::closebigbox();
 &Header::closepage();
-
-system("rm -f /var/tmp/iptables.txt");
-system("rm -f /var/tmp/iptablesmangle.txt");
-system("rm -f /var/tmp/iptablesnat.txt");
diff --git a/src/misc-progs/getipstat.c b/src/misc-progs/getipstat.c
index c806d54a9..99d053bbf 100644
--- a/src/misc-progs/getipstat.c
+++ b/src/misc-progs/getipstat.c
@@ -2,6 +2,15 @@ 
  *
  * Get the list from IPTABLES -L
  * 
+ * Optional commandline parameters:
+ *  -x 
+ *   instruct iptables to expand numbers
+ *  -f 
+ *   display filter table 
+ *  -n
+ *   display nat table
+ *  -m
+ *   display mangle table
  */
 
 #include <stdio.h>
@@ -9,20 +18,60 @@ 
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/types.h>
-#include <fcntl.h>
 #include "setuid.h"
 
-
-int main(void)
+int main(int argc, char** argv)
 {
+	// Set defaults
+	// first argument has to be "iptables" since execve executes the program pointed to by filename
+	// but /sbin/iptables is actually a symlink to /sbin/xtables-legacy-multi hence that program is executed
+	// however without the notion that it was called as "iptables". So we have to pass "iptables" as first
+	// argument.
+	char *args[10] = {"iptables", "--list", "--verbose", "--numeric", "--wait", "5", NULL, NULL, NULL, NULL};
+	char *usage = "getipstat [-x][-f|-n|-m]";
+	unsigned int pcount = 6;
+	unsigned int table_set = 0;
+
+	int opt;
+	
 	if (!(initsetuid()))
 		exit(1);
 
-	safe_system("/sbin/iptables -L -v -n > /var/tmp/iptables.txt");
-	safe_system("/sbin/iptables -L -v -n -t nat > /var/tmp/iptablesnat.txt");
-	safe_system("/sbin/iptables -t mangle -L -v -n > /var/tmp/iptablesmangle.txt");
-	safe_system("chown nobody.nobody /var/tmp/iptables.txt /var/tmp/iptablesnat.txt /var/tmp/iptablesmangle.txt");
-	
-	return 0;
+	// Parse command line arguments
+	if (argc > 1) {
+		while ((opt = getopt(argc, argv, "xfnm")) != -1) {
+			switch(opt) {
+				case 'x':
+					args[pcount++] = "--exact";
+					break;
+				case 'f':
+					table_set++;
+					break;
+				case 'n':
+					if (table_set == 0) {
+						args[pcount++] = "--table";
+						args[pcount++] = "nat";
+					}
+					table_set++;
+					break;
+				case 'm':
+					if (table_set == 0) {
+						args[pcount++] = "--table";
+						args[pcount++] = "mangle";
+					}
+					table_set++;
+					break;
+				default:
+					fprintf(stderr, "\nBad argument given.\n\n%s\n", usage);
+					exit(1);
+			}
+		}
+		if (table_set > 1) {
+			fprintf(stderr, "\nArguments -f/-n/-m are mutualy exclusive.\n\n%s\n", usage);
+			exit(1);
+		}
+	}
+
+	return run("/sbin/iptables", args);
 }