Testing DNS Redirect code snippet

I think it would need a new file in src/misc-progs - there doesn’t seem to be an existing file that does the firewall restart, but it’s easy enough to add a new one.

Hi Jon,
I just got your mail. So if I understand you correctly, you need a “Restart Firewall” button (which executes system('/etc/rc.d/init.d/firewall restart >/dev/null');) added to optionsfw.cgi?
Regards, Leo

Leo - You may want to read thru the above. When the above command runs nothing happens.

Hi,

@luani:

Just to clear things up: the Save and Restart-button already exists.

He should do (Code snippet from above):

    system("/usr/local/bin/firewallctrl");
	system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1 ");  # <=== THIS IS NOT WORKING FROM GUI!

The line /usr/local/bin/firwallctrl is working. Settings are saved.

The problem comes with either /etc/rc.d/init.d/firewall restart or with a new command system("/usr/local/bin/optionsfw.ctrl"); You mentioned this.

Code for optionsfwctrl.c can be found here.

The second command(s) only run from a root console.

I’m searching for a practical and safe solution for this…

Best,
Matthias

Hi Jon, hi Matthias,
I’m sorry, I misread your last messages and thought you got it working. Thanks for the clarification.

So actually you are looking for a secure way to execute specific root commands from the web interface?

Hi Leo,

Exactly.

I have a few ideas - but no breakthrough…

Hi Matthias,
I had a quick look around the sources and I think I have an idea.
There is a file called “unboundctrl.c” which apparently is able to call init scripts. So I tried to figure out what they did differently.

This unboundctrl is used in three CGIs and I’m pretty sure it works as intended.

Now I think the missing piece of the puzzle is hidden in the Makefile. There is a list called “SUID_PROGS”:

I think your “optionsfwctrl.c” must be included in this list…? And then it should work. At least, I hope you haven’t tried that yet :sweat_smile:
I am not at all familiar with the IPFire 2 build system, so I could be wrong. Might be worth investigating though.

1 Like

Hi Leo,

Many thanks for this tip - but sorry, I did this. But since I didn’t know it better, I used firewallctrl.c as “source” file.

Result (optionsfwctrl.c):

/* 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 <stdlib.h>
#include "setuid.h"

int main(void)
{
	if (!(initsetuid()))
		exit(1);

	safe_system("/etc/rc.d/init.d/firewall restart >/dev/null 2>&1");

	return 0;
}

The compiled file doesn’t work from GUI - but as root from a root console.

Did I miss something? In the ‘include’-lines? Or syntax?

Check the ownership and permissions - it should probably be owned by root and have the sticky bit set.

Hi Tim,

Done.

Doesn’t work. Its exactly the same as before. Saving settings is ok, but the second command is only executed from root console.

CGI contains:

system("/usr/local/bin/firewallctrl");
system("/usr/local/bin/optionsfwctrl >/dev/null 2>&1 ");

Current rights:

root@ipfire: /usr/local/bin # ls optionsfwctrl -ls
16 -rwsr-x--T 1 root nobody 14640 Dec 24 13:31 optionsfwctrl

Hi Matthias,

I wrote a quick optionsfwctrl based on unboundctrl on my development system. Compiled and started from web interface via “system();”, I got this output:

Setting up firewall [ OK ]

Exit code was “0”

Is there a log entry or something so I can verify that this really worked?

Edit: Here is what I did after compile & copy to /usr/local/bin:

#: chown root:nobody optionsfwctrl
#: chmod 4750 optionsfwctrl
#: ls optionsfwctrl -l
-rwsr-x— 1 root nobody 18064 Dec 24 18:27 optionsfwctrl

Hi Leo,

interesting… -v please. :wink:

How did you do this? Starting from GUI never showed me an exit code!?

Based on your hint I modified unboundctrl.c - now testing.

Changing my existing optionsfwctrl.c to ‘root:nobody / 4750’ had no effect.

(Time passes…)

Ok - Done.

  1. I took unboundctrl.c and rewrote it to execute safe_system("/etc/rc.d/init.d/firewall restart"); or safe_system("/etc/rc.d/init.d/firewall reload");
  2. Used the same owner / rights as you.
  3. Saving settings works but firewall does NOT restart. sigh

I still think that the main goal is the fact that the command /etc/rc.d/init.d/firewall restart needs to start a whole lot of ‘iptables’-commands with root privileges. And I just can’t get this to work from within GUI.

Add notation or popup “reboot required”

@hvacguy
Hi Shaun,

this is already done automatically while hitting Save.

I’ll just add a few screenshots to demonstrate:

  1. The patched optionsfw.cgi looks like this. I added DNS, NTP-switches. And: options for BLUE are only shown if BLUE exists:

  1. These switches (should!) add a few REDIRECT rules - or delete them, if they exist - in the CUSTOMPREROUTING chain:

  1. The adding - or deleting - of these rules has to be done with the command /etc/rc.d/init.d/firewall restart - and I like to trigger this through an added Save and Restart button at the end of optionsfw.cgi:

So when hitting Save not only the page settings are saved - as before - but additionally the firewall settings should be restarted “for changes to take effect”…

And because its the same procedure as before - plus a “few” tuning measures - the usual message appears after choosing Save And Restart:

Note that I changed the Force DNS on GREEN option.

But the CUSTOMPREROUTING chain isn’t changed, the rules for GREEN are still there:

And I’d like to avoid a complete reboot…

Doing exactly the same through a root console with executing /usr/local/bin/optionsfwctrl restart - a newly added program - works.

Hi,

Problem solved. Everything is working.

Thanks to Shaun - explaining the whole thing once more helped me to find the solution. :wink:

It could have worked much earlier, there was just one line missing.

To make things short:

In the relevant code block from optionsfw.cgi the Save command-string system("/usr/local/bin/firewallctrl"); is used twice. Duh!

And so I had to add the Restart-command twice, too.

The complete block now reads (beginning with line 96):

...
#Get GUI values
&Header::getcgihash(\%settings);
if ($settings{'ACTION'} eq $Lang::tr{'save'}) {
<->if ($settings{'defpol'} ne '1'){
<-><->$errormessage .= $Lang::tr{'new optionsfw later'};
<-><->&General::writehash($filename, \%settings);             # Save good settings
<-><->system("/usr/local/bin/firewallctrl");
<->}else{
<-><->if ($settings{'POLICY'} ne ''){
<-><-><->$fwdfwsettings{'POLICY'} = $settings{'POLICY'};
<-><->}
<-><->if ($settings{'POLICY1'} ne ''){
<-><-><->$fwdfwsettings{'POLICY1'} = $settings{'POLICY1'};
<-><->}
<-><->my $MODE = $fwdfwsettings{'POLICY'};
<-><->my $MODE1 = $fwdfwsettings{'POLICY1'};
<-><->%fwdfwsettings = ();
<-><->$fwdfwsettings{'POLICY'} = "$MODE";
<-><->$fwdfwsettings{'POLICY1'} = "$MODE1";
<-><->&General::writehash("${General::swroot}/firewall/settings", \%fwdfwsettings);
<-><->&General::readhash("${General::swroot}/firewall/settings", \%fwdfwsettings);
<-><->system("/usr/local/bin/firewallctrl");
<->}
<->&General::readhash($filename, \%settings);             # Load good settings
}

if ($settings{'ACTION'} eq $Lang::tr{'fw settings save and restart'}) {
<->if ($settings{'defpol'} ne '1'){
<-><->$errormessage .= $Lang::tr{'new optionsfw later'};
<-><->&General::writehash($filename, \%settings);             # Save good settings
<-><->system("/usr/local/bin/firewallctrl");
<-><->system("/usr/local/bin/optionsfwctrl restart >/dev/null 2>&1");
<->}else{
<-><->if ($settings{'POLICY'} ne ''){
<-><-><->$fwdfwsettings{'POLICY'} = $settings{'POLICY'};
<-><->}
<-><->if ($settings{'POLICY1'} ne ''){
<-><-><->$fwdfwsettings{'POLICY1'} = $settings{'POLICY1'};
<-><->}
<-><->my $MODE = $fwdfwsettings{'POLICY'};
<-><->my $MODE1 = $fwdfwsettings{'POLICY1'};
<-><->%fwdfwsettings = ();
<-><->$fwdfwsettings{'POLICY'} = "$MODE";
<-><->$fwdfwsettings{'POLICY1'} = "$MODE1";
<-><->&General::writehash("${General::swroot}/firewall/settings", \%fwdfwsettings);
<-><->&General::readhash("${General::swroot}/firewall/settings", \%fwdfwsettings);
<-><->system("/usr/local/bin/firewallctrl");
<-><->system("/usr/local/bin/optionsfwctrl restart >/dev/null 2>&1");
<->}
<->&General::readhash($filename, \%settings);             # Load good settings
}
...

That was all folks… :sweat_smile:

Best,
Matthias

4 Likes

Matthias @mfischer -

Can you post the latest & greatest optionsfw.cgi (and any other files related to DNS/NTP redirect)? I’d like to load it up and give it a try.

Thanks!

@jon

You got a PM…

Fixed!

Patch here:
https://git.ipfire.org/?p=ipfire-2.x.git;a=commit;h=21b37391f9769718df7bd726453140f4ec8ff1c0