Rpz in whitelist mode

hi
I’ve been using this mode for several months and I think it works well.

if you want to test here’s the information

in the unbound case

1: creates the local file.d folder

2: Creates the zonefiles folder

in the file unbound local.d

Create the setting.conf file


server:

	# Logging Options
	verbosity: 1
	# log-queries: yes
	# log-replies: yes
	log-tag-queryreply: yes

	# Randomise any cached responses
	rrset-roundrobin: yes

 	# Harden against receiving dnssec-stripped data
 	harden-dnssec-stripped: yes

 	# Harden against queries that fall under dnssec-signed nxdomain names.
 	harden-below-nxdomain: yes

 	# Sent minimum amount of information to upstream servers to enhance
 	# privacy. Only sent minimum required labels of the QNAME and set QTYPE
 	# to A when possible.
 	qname-minimisation: yes

 	# if yes, Unbound doesn't insert authority/additional sections
 	# into response messages when those sections are not required.
 	minimal-responses: yes

 	# if yes, the above default do-not-query-address entries are present.
 	# if no, localhost can be queried (for testing and debugging).
 	# block cname ads using stub-zone
 	do-not-query-localhost: yes

 	# If  yes, deny queries of type ANY with an empty response.
 	# Default is no. If disabled, unbound responds with a short list
 	# of resource records if some can be found in the cache and makes
 	# the upstream type ANY query if there are none.
 	deny-any: yes

 	# Configure a local zone. The type determines the answer to give
 	# if there is no  match  from local-data. The types are deny,
 	# refuse,  static, transparent, redirect, nodefault, typetranspar-
 	# ent, inform, inform_deny, inform_redirect,  always_transparent,
 	# always_refuse, always_nxdomain, noview, and are explained below.
 	# After that the default settings are listed. Use  local-data:  to
 	# enter  data  into  the  local  zone. Answers for local zones are
 	# authoritative DNS answers. By default the zones are class IN.
 	# local-zone: "pc.localdomain" deny

 	# Will trust glue only if it is within the servers authority.
 	# Default is on.
 	harden-glue: yes

 	# Configure  local data, which is served in reply to queries for it.
 	# The query has to match exactly unless you configure the local-zone
 	# as redirect. If not matched exactly, the local-zone type determines 
 	# further processing. If local-data is configured that is not a subdomain 
 	# of a local-zone, a transparent local-zone is configured. For record types 
 	# such as TXT,  use  single  quotes, as in local-data: 'example. TXT "text"'.
 	#local-data: "pc.localdomain A 0.0.0.0"

 	# number of threads to create
 	# of CPU cores in the machine
	num-threads: 4
	msg-cache-slabs: 8
	rrset-cache-slabs: 8
	infra-cache-slabs: 8
	key-cache-slabs: 8

 	# Faster UDP with multithreading (only on Linux).
 	so-reuseport: yes

	# Should additional section of secure message also be kept clean of
	# unsecure data. Useful to shield the users of this validator from
	# potential bogus data in the additional section. All unsigned data
	# in the additional section is removed from secure messages.
	val-clean-additional: yes

 	# DNS Rebinding
 	# For DNS Rebinding prevention
 	private-address: 127.0.0.0/8
 	private-address: 10.0.0.0/8
 	private-address: 169.254.0.0/16
 	private-address: 172.16.0.0/12
 	private-address: 192.168.0.0/16

then creates the filters.conf file

server:
	module-config: "respip validator iterator"

	define-tag: "ipfire block"
	define-tag: "lan block"
	define-tag: "nas block"
	define-tag: "wiffi block"

	# Per client IP
	access-control-tag: 127.0.0.1/32 "ipfire block"
	access-control-tag: 192.168.1.2/32 "lan block"
	access-control-tag: 192.168.1.15/32 "nas block"
	access-control-tag: 192.168.2.0/24 "wiffi block"

rpz:
	# The name of the RPZ authority zone
	name: ipfire

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/ipfire.rpz.zone
 	zonefile: /etc/unbound/zonefiles/ipfire.rpz.zone
 	tags: "ipfire"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: ALLOW-IPFIRE

rpz:
	# The name of the RPZ authority zone
	name: nas

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/nas.rpz.zone
 	zonefile: /etc/unbound/zonefiles/nas.rpz.zone
 	tags: "nas"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: ALLOW-NAS

rpz:
	# The name of the RPZ authority zone
	name: wiffi

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/wiffi.rpz.zone
 	zonefile: /etc/unbound/zonefiles/wiffi.rpz.zone
 	tags: "wiffi"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: ALLOW-WIFI

rpz:
	# The name of the RPZ authority zone
	name: lan

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: zonefiles/lan.rpz.zone
 	zonefile: /etc/unbound/zonefiles/lan.rpz.zone
 	tags: "lan"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: passthru

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: ALLOW-LAN_1

rpz:
	# The name of the RPZ authority zone
	name: block

	# The location of the remote RPZ zonefile.
	# url: http://www.example.com/example.org.zone (not a real RPZ file)
 	#zonefile: block.rpz.zone
 	zonefile: /etc/unbound/zonefiles/block.rpz.zone
	tags: "block"

 	# Always use this RPZ action for matching triggers from this zone.
	# Possible action are: nxdomain, nodata, passthru, drop, disabled,
	# and cname.
	rpz-action-override: nxdomain

	# Log all applied RPZ actions for this RPZ zone. Default is no.
	rpz-log: yes

	# Specify a string to be part of the log line.
	rpz-log-name: BLOK-ALL

in define-tag: definish your tag
in access-control-tag: definish your ip

in the unbound zonefiles folder

1: creates the file ipfire.rpz.zone
Edit file ipfire.rpz.zone

* CNAME .

2: creates the block.rpz.zone file
Edit file block.rpz.zone file

* CNAME .

3: creates the file lan.rpz.zone

in the file write to you your url address in the syntax surport by unbound
e.g.
*.site.com
site.com
www.site.com

(in the zonefiles folder you create an more than ever of areas that you veil and name them as you want)

and to block the ip configure the ipfire in block mode
in mode you to clear the rules for each ip that you want to allow

ty

1 Like

Thank you for documenting this!

I’ve read this a couple of times and I need to give this a try to understand what all it does. Especially the items in the setting.conf and the filters.conf file. Honestly what you’ve documented is over my head!

Short term:

  1. we need to get approval from the IPFire Core Developers for the RPZ add-on already submitted.
  2. Once that happens, then we need to get a WebGUI built, tested and approved.
  3. then get a WebGUI for logs/metrics built, tested and approved.

After that I can focus and try and understand what you created.

hy
for setting.conf I searched the Internet for information that I’ve put together
I also searched the unbound documentation

for the 1,2,3 I am well aware that only the devs are the only ones able to verify and decide thank you for their knowledge

if this completed project will have been very good

for a WebGUI I have a lot of ideas but I’m not dev

ty

1 Like

for
define-tag:
access-control-tag:
the lists are created locally to distributes the different equipment
define-tag: used to name a list and its configuration
access-control-tag: used to define ip or ip group
define-tag: name is use for create rule for example
list1 list2
the name list1 maybe use alone or with list2
for example : list1 use alone

define-tag: "ipfire"

Per client IP
access-control-tag: 127.0.0.1/32 "ipfire"

for example : list1 and list2

define-tag: "lan block"

Per client IP
access-control-tag: 192.168.1.2/32 "lan block"

list1 (lan) allow and list2 (block) blocked together list1 is priority on list2

hi
I wrote a new script but I can’t do the action to save with the bonton saves scipt if you can help me thank you
This is the script.:

#!/usr/bin/perl

use strict;
use warnings;

use File::Copy;
use IO::Socket;

require '/var/ipfire/general-functions.pl';
require "${General::swroot}/lang.pl";
require "${General::swroot}/header.pl";

&Header::showhttpheaders();

&Header::openpage($Lang::tr{'urlfilter configuration'}, 1, );

my $script_name = $ENV{'SCRIPT_NAME'};

print "<form method='post' action='$script_name' enctype='multipart/form-data'>\n";

&Header::openbox('100%', 'left', "$Lang::tr{'Parametres Unbound'}");

# Affichage du fichier /etc/unbound/local.d/setting.conf
print "<td class='base' colspan='4'><b>modifier le fichier parametre de Unbound</b></td>\n";
print "</table>\n";
print "<td>&nbsp;</td>\n";

# Menu pour editer le fichier /etc/unbound/local.d/setting.conf
my $setting_conf = `/bin/cat /etc/unbound/local.d/setting.conf`;
print "<table border='1' cellpadding='5'>\n";
print "</th><td><textarea rows='10' cols='125'>$setting_conf</textarea></td></tr>\n";
print "</table>\n";  # ferme la table avant d'imprimer le button
print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$setting_conf');\">\n";
print "\n\n";

print "</table>\n";

&Header::closebox();

&Header::openbox('100%', 'left', "$Lang::tr{'>Parametres de zone'}");

# Affichage du fichier /etc/unbound/local.d/filtres.conf
print "<td class='base' colspan='4'><b>modifier le fichier parametre de zone</b></td>\n";
print "</table>\n";
print "<td>&nbsp;</td>\n";

# Menu pour editer le fichier /etc/unbound/local.d/filtres.conf
my $filtre_conf = `/bin/cat /etc/unbound/local.d/filtres.conf`;
print "<table border='1' cellpadding='5'>\n";
print "</th><td><textarea rows='10' cols='125'>$filtre_conf</textarea></td></tr>\n";
print "</table>\n";  # ferme la table avant d'imprimer le button
# Bouton submit pour enregistrer le fichier /etc/unbound/local.d/filtres.conf
print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$filtre_conf');\">\n";
print "</table>\n";

&Header::closebox();

&Header::openbox('100%', 'left', "$Lang::tr{'Unbound zone files'}");

print "<table border='1' cellpadding='5'>\n";
print "<tr><th>Fichier</th><th>liste de regle de domaine</th></tr>\n";

my @zone_files = `ls /etc/unbound/zonefiles`;
foreach my $file (@zone_files) {
    print "<tr>";
    print "<td>$file</td>";  # Aligner le nom du fichier
    print "<td style='vertical-align: top'>";
    print "<textarea rows='10' cols='115'>";  # Aligner le textarea
    system("/bin/cat /etc/unbound/zonefiles/$file");
    print "</textarea>\n";
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$file'); location.reload();\">";
    print "</td>";  # Fermer la cellule du textarea
    print "</tr>\n";
}

sub saveFile {
    my $filename = shift;

        # Vérifiez si le fichier existe avant de tenter de l'enregistrer
    if (-e "/etc/unbound/zonefiles/$filename") {
        system("cp /etc/unbound/zonefiles/$filename /tmp/$filename");
        system("cp /tmp/$filename /etc/unbound/zonefiles");
        print "<script>alert('Les modifications du fichier '$filename' ont été enregistrées avec succès !');</script>";
     } else {
        print "<script>alert('Le fichier '$filename' n\'existe pas !');</script>";
     }
}

print "</table>\n";
&Header::closepage();


and an image to see what it gives

1 Like

Ive loaded the cgi up and a few minor tweaks might be needed for things like the save function and little layout work but other then that i think its pretty cool. oh and language file changes

edit:

made a few changes because it got a little distorted when it showed all the blacklists. Haven’t messed with the save function yet but it looks promising.

I think some of this could be incorporated into @jons RPZ addon he is working on.

hi
Thank you for testing the code I think also it’s good to bring together into ‘jons RP’ addon
I’ve added something else to the code I’d put the new code sooner I’m trying to make the buttons to save the different files it’s not simple the right on the folders or file with the formatting
ty

hi
I added what was missing to the code for the visual part, all that’s missing is the buttons to save.

#!/usr/bin/perl

use strict;
use warnings;

use File::Copy;
use IO::Socket;
use File::Basename;

require '/var/ipfire/general-functions.pl';
require "${General::swroot}/lang.pl";
require "${General::swroot}/header.pl";

&Header::showhttpheaders();

&Header::openpage($Lang::tr{'urlfilter configuration'}, 1, );

my $script_name = $ENV{'SCRIPT_NAME'};

print "<form method='post' action='$script_name' enctype='multipart/form-data'>\n";

&Header::openbox('100%', 'left', "$Lang::tr{'Parametres Unbound'}");

# Affichage du fichier /etc/unbound/local.d/setting.conf
    print "<td class='base' colspan='4'><b>modifier le fichier parametre de Unbound</b></td>\n";
    print "</table>\n";
    print "<td>&nbsp;</td>\n";

# Menu pour editer le fichier /etc/unbound/local.d/setting.conf
my $setting_conf = `/bin/cat /etc/unbound/local.d/setting.conf`;
    print "<table border='1' cellpadding='5'>\n";
    print "<td style='vertical-align: top'>";   # Aligner le textarea
    print "<textarea rows='10' cols='128'>$setting_conf</textarea>";
    print "</table>\n";  # ferme la table avant d'imprimer le button
    
# Bouton pour enregistrer le fichier /etc/unbound/local.d/setting.conf
    print "<hr size='1'><form>\n";
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$setting_conf');\">\n";
    print "\n\n";
    print "<hr size='1'><form>\n";
    print "</table>\n";

&Header::closebox();

&Header::openbox('100%', 'left', "$Lang::tr{'>Parametres de zone'}");

# Affichage du fichier /etc/unbound/local.d/filtres.conf
    print "<td class='base' colspan='4'><b>modifier le fichier parametre de zone</b></td>\n";
    print "</table>\n";
    print "<td>&nbsp;</td>\n";

# Menu pour editer le fichier /etc/unbound/local.d/filtres.conf
my $filtre_conf = `/bin/cat /etc/unbound/local.d/filtres.conf`;
    print "<table border='1' cellpadding='5'>\n";
    print "<td style='vertical-align: top'>";   # Aligner le textarea
    print "<textarea rows='10' cols='128'>$filtre_conf</textarea>";
    print "</table>\n";  # ferme la table avant d'imprimer le button
    
# Bouton pour enregistrer le fichier /etc/unbound/local.d/filtres.conf
    print "<hr size='1'><form>\n";
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$filtre_conf');\">\n";
    print "<hr size='1'><form>\n";
    print "</table>\n";

&Header::closebox();

&Header::openbox('100%', 'left', "$Lang::tr{'Unbound zone files'}");

# Menu pour ajouter des fichiers au dossier /etc/unbound/zonefiles/
print "<hr size='1'><form>\n";
my $file = "${General::swroot}/etc/unbound/zonefiles";
print "ajoutez une nouvelle liste de domaine : <input type='text' name='nouveau_nom_fichier' placeholder='Entrez le nom du fichier'>\n";
print "<button onclick=\"saveFile('$file', document.getElementById('nouveau_nom_fichier').value, '/etc/unbound/zonefiles/');\">Sauvegarder</button>\n";
print "<hr size='1'><form>\n";
print "</hr size='1'></form>\n";

sub saveFile {
    my ($file) = @_;
    # Code pour créer un nouveau fichier avec le nom donné
}

# cadre avec titre liste de regle de domaine
print "<table border='1' cellpadding='5'>\n";
print "<tr><th>Fichier</th><th>liste de regle de domaine</th></tr>\n";

# Menu pour afficher les fichier du dossier /etc/unbound/zonefiles
my @zone_files = `ls /etc/unbound/zonefiles`;
foreach my $file (@zone_files) {
    print "<tr>";
    print "<td>$file</td>";   # Aligner le nom du fichier
    print "<td style='vertical-align: top'>";   # Aligner le textarea
    print "<textarea rows='10' cols='115'>";   # Aligner le textarea
    system("/bin/cat /etc/unbound/zonefiles/$file");
    print "</textarea>\n";
    print "<hr size='1'><form>\n";
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$file'); location.reload();\">";
    print "<hr size='1'><form>\n";
    print "</td>";   # Fermer la cellule du textarea
    print "</tr>\n";
}

print "</table>\n";

&Header::openbox('100%', 'left', "$Lang::tr{'chek Unbound conf'}");

# Bouton pour vérifier la configuration de Unbound
    print "<hr size='1'><form>\n";
    print "<input type='button' value='vérifier la configuration de Unbound');\">\n";
    print "<input type='button' value='appliquer les regles et redémarer Unbound');\">\n";
    print "<hr size='1'><form>\n";
    print "</table>\n";

print "</table>\n";

&Header::closebox();

&Header::closebigbox();

&Header::closepage();

with an image for additions


and then the translation files will remain

I Modified the code for the visual part, all that’s missing is the buttons to save.

#!/usr/bin/perl

use strict;

# debugging
#use warnings;
#use CGI::Carp 'fatalsToBrowser';
#use Data::Dumper;

require '/var/ipfire/general-functions.pl';
require "${General::swroot}/lang.pl";
require "${General::swroot}/header.pl";

# chemin du fichier setting.conf /etc/unbound/local.d/setting.conf
my $SETTING_CONF = "${General::swroot}/etc/unbound/local.d/setting.conf";

# chemin du fichier /etc/unbound/local.d/filtres.conf
my $FILTRE_CONF = "${General::swroot}/etc/unbound/local.d/filtres.conf";

# chemin du dossier /etc/unbound/zonefiles
my $ZONE_FILES = "${General::swroot}/etc/unbound/zonefiles";

&Header::showhttpheaders();

&Header::openpage("Unbound configuration", 1, );
&Header::openbox('100%', 'left', "Parametres Unbound");

my $script_name = $ENV{'SCRIPT_NAME'};

    print "<form method='post' action='$script_name' enctype='multipart/form-data'>\n";

# Affichage du titre modifier le fichier parametre de Unbound
    print "<td class='base' colspan='4'><b>modifier le fichier parametre de Unbound</b></td>\n";
    print "</table>\n";
    print "<td>&nbsp;</td>\n";

# Menu pour editer le fichier /etc/unbound/local.d/setting.conf
my $SETTING_CONF = `/bin/cat  /etc/unbound/local.d/setting.conf`;
    print "<table border='1' cellpadding='5'>\n";
    print "<td style='vertical-align: top'>";
    print "<textarea rows='10' cols='128'>$SETTING_CONF</textarea>";
    print "</table>\n";   # ferme la table avant d'imprimer le button

# Bouton pour enregistrer le fichier  /etc/unbound/local.d/setting.conf
my $CONF_VALUE = <TEXTAREA_NAME>;  # Stockez la valeur du textarea dans une variable
    print "<hr size='1'><form>\n";
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$CONF_VALUE');\">\n";
    print "\n\n";

# fonction de sauvegarde
sub saveFile {
    my $value = shift;
    # Traitement du fichier setting.conf (par exemple, enregistrement dans un fichier)
    open(my $fh, '>', '/etc/unbound/local.d/setting.conf');
    print $fh $value;
    close($fh);
}

print "</form>\n";

&Header::closebox();

&Header::openbox('100%', 'left', "Parametres de zone");

# # Affichage du titre modifier le fichier parametre de zone
    print "<td class='base' colspan='4'><b>modifier le fichier parametre de zone</b></td>\n";
    print "</table>\n";
    print "<td>&nbsp;</td>\n";

# Menu pour editer le fichier /etc/unbound/local.d/filtres.conf
my $FILTRE_CONF = `/bin/cat /etc/unbound/local.d/filtres.conf`;
    print "<table border='1' cellpadding='5'>\n";
    print "<td style='vertical-align: top'>";   # Aligner le textarea
    print "<textarea rows='10' cols='128'>$FILTRE_CONF</textarea>";
    print "</table>\n";  # ferme la table avant d'imprimer le button
    
# Bouton pour enregistrer le fichier /etc/unbound/local.d/filtres.conf
my $FILTRE_VALUE = <TEXTAREA_NAME>;  # Stockez la valeur du textarea dans une variable
    print "<hr size='1'><form>\n";
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:saveFile('$FILTRE_VALUE');\">\n";
    print "<hr size='1'><form>\n";
print "\n\n";

# fonction de sauvegarde
sub saveFile {
    my $value = shift;
    # Traitement du fichier filtres.conf (par exemple, enregistrement dans un fichier)
    open(my $fh, '>', '/etc/unbound/local.d/filtres.conf');
    print $fh $value;
    close($fh);
}

&Header::closebox();

&Header::openbox('100%', 'left', "Unbound zone files");

# champ de saisi pour ajouter des fichiers au dossier /etc/unbound/zonefiles/
my $ZONE_FILES = "/etc/unbound/zonefiles/";
    print "<hr size='1'><form>\n";
    print "Ajoutez une nouvelle liste de domaine: <input type='text' name='nouveau_nom_fichier' placeholder='Entrez le nom du fichier'>\n";
    print "<button onclick=\"saveFile('$ZONE_FILES', document.getElementById('nouveau_nom_fichier').value);\">Sauvegarder</button>\n";
    print "<hr size='1'><form>\n";

sub saveFile {
    my ($zone_files, $new_file_name) = @_;

# Vérifiez si le fichier existe déjà et écrivez un message d'erreur si c'est le cas
    if (-e "$zone_files/$new_file_name") {
        print "Erreur : Le fichier '$new_file_name' existe déjà !<br>";
        return;
    }

# Créez le nouveau fichier avec les droits appropriés (par exemple, 644)
    open(my $fh, '>', "$zone_files/$new_file_name")
        or die "Impossible de créer le fichier '$new_file_name' : $!";
    close($fh);

    print "Fichier '$new_file_name' créé avec succès !<br>";
}

# Cadre avec titre liste de regle de domaine
    print "<table border='1' cellpadding='5'>\n";
    print "<tr><th>Fichier</th><th>liste de regle de domaine</th></tr>\n";

# Menu pour afficher les fichier du dossier  /etc/unbound/zonefiles
my @ZONE_FILES = `ls /etc/unbound/zonefiles`;
foreach my $file (@ZONE_FILES) {
    print "<tr>";
    print "<td>$file</td>";    # Aligner le nom du fichier
    print "<td style='vertical-align: top'>";    # Aligner le textarea
    print "<textarea rows='10' cols='115'>";    # Aligner le textarea
    system("/bin/cat /etc/unbound/zonefiles/$file");
    print "</textarea>\n";
    print "<hr size='1'><form>\n";
    my $SAVE_FILE = 'function saveFile($value) { ... }';  # Définissez la fonction de sauvegarde
    print "<input type='button' value='Sauvegarder' onclick=\"javascript:$SAVE_FILE('$file'); location.reload();\">";
    print "<hr size='1'><form>\n";
    print "</td>";   # Fermer la cellule du textarea
    print "</tr>\n";
}

print "</table>\n";

&Header::closebox();

&Header::openbox('100%', 'left', "valider la configuration de Unbound");

# Bouton pour vérifier la configuration de Unbound
    print "<hr size='1'><form>\n";
    print "<input type='button' value='vérifier la configuration de Unbound');\">\n";
    print "<input type='button' value='appliquer les regles et redémarer Unbound');\">\n";
    print "<hr size='1'><form>\n";
    print "</table>\n";

print "</table>\n";

&Header::closebox();

&Header::closepage();

with an image for additions

I can’t see a real benefit of such a WUI page.
The main purpose is to edit the config files directly with the WUI.
This is

  1. contradictory to the IPFire philosophy:
    • config by WUI
  • save constructs the .conf files from the settings and restarts the service
  • special configurations can mostly added in .conf.local files ;
  1. not easy ( and error-prone! ) without knowing the syntax and semantics of unbound configuration;
  2. partly false ( editing RPZ files is not recommended, they are regularily updated by unbound )

@jon 's framework with command line programs (rpz-…) and the WUI using the latter is much more adequate. The knowledge about unbound configuration is implemented in these programs.
If you are able and want to edit the config files directly, why not do this directly with an editor?

The main purpose is to edit the config files directly with the WUI.
This is
contradictory to the IPFire philosophy:
config by WUI
save constructs the .conf files from the settings and restarts the service
special configurations can mostly added in .conf.local files ;

I understand I’m not a builder
I wanted to mount with the code I wanted to get
it possible to define another way with fixed options and boxes to be ticked for the settings of the conf file.

If you are able and want to edit the config files directly, why not do this directly with an editor?

I practice ssh editing with winscp but it’s a long time I wanted to do it with a WUI page much faster for everyone to manage

if @jon could add this possibility to his project would have been fine and much more consistent in the writing of the code
Thank you for your response.
ty