require '/var/ipfire/general-functions.pl';
require "${General::swroot}/geoip-functions.pl";
+require "${General::swroot}/ids-functions.pl";
require "${General::swroot}/lang.pl";
require "${General::swroot}/header.pl";
# File which contains the ca-certificates.
my $ca_certs_file = "/etc/ssl/certs/ca-bundle.crt";
+# Server which is used, to determine if the whole DNS system works properly.
+my $dns_test_server = "ping.ipfire.org";
+
+my $check_servers;
+
my %color = ();
my %mainsettings = ();
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
$cgiparams{'ENABLE_SAFE_SEARCH'} = "off";
}
- # Store settings into settings file.
- &General::writehash("$settings_file", \%cgiparams);
+ # Check if using ISP nameservers and TLS is enabled at the same time.
+ if (($cgiparams{'USE_ISP_NAMESERVERS'} eq "on") && ($cgiparams{'PROTO'} eq "TLS")) {
+ $errormessage = $Lang::tr{'dns isp nameservers and tls not allowed'}
+ }
+
+ # Check if there was an error.
+ if ( ! $errormessage) {
+
+ # Store settings into settings file.
+ &General::writehash("$settings_file", \%cgiparams);
+
+ # Call function to handle unbound restart, etc.
+ &_handle_unbound_and_more()
+ }
}
###
# Read-in generic settings.
&General::readhash("$settings_file", \%settings);
+ # Check if an IP-address has been given.
+ if ($cgiparams{"NAMESERVER"} eq "") {
+ $errormessage = "$Lang::tr{'dns no address given'}";
+ }
+
# Check if the given DNS server is valid.
- if(!&General::validip($cgiparams{"NAMESERVER"})) {
+ elsif(!&General::validip($cgiparams{"NAMESERVER"})) {
$errormessage = "$Lang::tr{'invalid ip'}: $cgiparams{'NAMESERVER'}";
}
}
}
- # Check the nameserver.
- my $status = &check_nameserver("$cgiparams{'NAMESERVER'}", "ping.ipfire.org", "$settings{'PROTO'}", "$cgiparams{'TLS_HOSTNAME'}");
-
- # Assign errormessage, if the nameserver does not support dnssec or any other kind of error happened.
- if ($status eq "0") {
- $errormessage = "$Lang::tr{'dns could not add server'} $Lang::tr{'dnssec not supported'}";
- } elsif (($status ne "1") && ($status ne "2")) {
- $errormessage = "$Lang::tr{'dns could not add server'} $status";
- }
-
# Go further if there was no error.
if ( ! $errormessage) {
# Check if a remark has been entered.
# The first allowed id is 3 to keep space for
# possible ISP assigned DNS servers.
- if ($id le "2") {
+ if ($id <= "2") {
$id = "3";
}
}
# Write the changed hash to the config file.
&General::writehasharray($servers_file, \%dns_servers);
+
+ # Call function to handle unbound restart, etc.
+ &_handle_unbound_and_more();
} else {
# Switch back to previous mode.
$cgiparams{'SERVERS'} = $cgiparams{'MODE'};
# Write the changed hash back to the config file.
&General::writehasharray($servers_file, \%dns_servers);
+
+ # Call function to handle unbound restart, etc.
+ &_handle_unbound_and_more();
}
## Remove entry from DNS servers list.
# Write the changed hash to the config file.
&General::writehasharray($servers_file, \%dns_servers);
+
+ # Call function to handle unbound restart, etc.
+ &_handle_unbound_and_more();
+
+## Handle request to check the servers.
+#
+} elsif ($cgiparams{'SERVERS'} eq $Lang::tr{'dns check servers'}) {
+ $check_servers = 1;
}
# Hash to store the generic DNS settings.
# Section to display the configured and used DNS servers.
#
sub show_nameservers () {
- &Header::openbox('100%', 'center', "DNS-Servers");
+ &Header::openbox('100%', 'center', "$Lang::tr{'dns title'}");
+
+ # Determine if we are running in recursor mode
+ my $recursor = 0;
+ my $unbound_forward = qx(unbound-control forward);
+ if ($unbound_forward =~ m/^off/) {
+ $recursor = 1;
+ }
+
+ my $dns_status_string;
+ my $dns_status_col;
+ my $dns_working;
+
+
+ # Test if the DNS system is working.
+ #
+ # Simple send a request to unbound and check if it can resolve the
+ # DNS test server.
+ my $dns_status_ret = &check_nameserver("127.0.0.1", "$dns_test_server", "UDP", undef, "+timeout=5", "+retry=0");
+
+ if ($dns_status_ret eq "2") {
+ $dns_status_string = "$Lang::tr{'working'}";
+ $dns_status_col = "${Header::colourgreen}";
+ $dns_working = 1;
+ } else {
+ $dns_status_string = "$Lang::tr{'broken'}";
+ $dns_status_col = "${Header::colourred}";
+ }
+
+ if ($recursor) {
+ $dns_status_string .= " (" . $Lang::tr{'dns recursor mode'} . ")";
+ }
+
+ print <<END;
+ <table width='100%'>
+ <tr>
+ <td>
+ <strong>$Lang::tr{'status'}: </strong>
+ <strong><font color='$dns_status_col'>$dns_status_string</font></strong>
+ </td>
+ </tr>
+ </table>
+END
+
+ # Check the usage of ISP assigned nameservers is enabled.
+ my $id = 1;
+
+ # Loop through the array which stores the files.
+ foreach my $file (@ISP_nameserver_files) {
+ # Grab the address of the nameserver.
+ my $address = &General::grab_address_from_file($file);
+
+ # Check if we got an address.
+ if ($address) {
+ # Add the address to the hash of nameservers.
+ $dns_servers{$id} = [ "$address", "none",
+ ($settings{'USE_ISP_NAMESERVERS'} eq "on") ? "enabled" : "disabled",
+ "$Lang::tr{'dns isp assigned nameserver'}" ];
+
+ # Increase id by one.
+ $id++;
+ }
+ }
+
+ # Check some DNS servers have been configured. In this case
+ # the hash contains at least one key.
+ my $server_amount;
+ if (keys %dns_servers) {
+ # Sort the keys by their ID and store them in an array.
+ my @keys = sort { $a <=> $b } keys %dns_servers;
+
+ print <<END;
+ <br>
-print <<END;
<table class="tbl" width='100%'>
<tr>
<td align="center">
<td align="center">
<strong>$Lang::tr{'remark'}</strong>
</td>
+END
+ # Check if the status should be displayed.
+ if ($check_servers) {
+ print <<END;
<td align="center">
<strong>$Lang::tr{'status'}</strong>
</td>
+END
+ }
+
+ print <<END;
<td align="center" colspan="3">
<strong>$Lang::tr{'action'}</strong>
</tr>
END
- # Check the usage of ISP assigned nameservers is enabled.
- if ($settings{'USE_ISP_NAMESERVERS'} eq "on") {
- my $id="1";
-
- # Loop through the array which stores the files.
- foreach my $file (@ISP_nameserver_files) {
- # Grab the address of the nameserver.
- my $address = &grab_address_from_file($file);
-
- # Check if we got an address.
- if ($address) {
- # Add the address to the hash of nameservers.
- $dns_servers{$id} = [ "$address", "none", "enabled", "$Lang::tr{'dns isp assigned nameserver'}" ];
-
- # Increase id by one.
- $id++;
- }
- }
- }
-
- # Check some DNS servers have been configured. In this case
- # the hash contains at least one key.
- my $server_amount;
- if (keys %dns_servers) {
- # Sort the keys by their ID and store them in an array.
- my @keys = sort { $a <=> $b } keys %dns_servers;
-
# Loop through all entries of the array/hash.
foreach my $id (@keys) {
# Inrease server_amount.
my $status_colour;
# Only grab the status if the nameserver is enabled.
- if ($enabled eq "enabled") {
+ if (($check_servers) && ($enabled eq "enabled")) {
$status = &check_nameserver("$nameserver", "ping.ipfire.org", "$settings{'PROTO'}", "$tls_hostname");
}
- if (!$status) {
+ if (!defined $status) {
$status_short = "$Lang::tr{'disabled'}";
# DNSSEC Not supported
my $ccode = &GeoIP::lookup($nameserver);
my $flag_icon = &GeoIP::get_flag_icon($ccode);
- my $iaddr = inet_aton($nameserver);
- my $rdns = gethostbyaddr($iaddr, AF_INET);
+ my $rdns;
+
+ # Only do the reverse lookup if the system is online.
+ if ($dns_working) {
+ my $iaddr = inet_aton($nameserver);
+ $rdns = gethostbyaddr($iaddr, AF_INET);
+ }
if (!$rdns) { $rdns = $Lang::tr{'lookup failed'}; }
+ # Mark ISP name servers as disabled
+ if ($id <= 2 && $enabled eq "disabled") {
+ $nameserver = "<del>$nameserver</del>";
+ }
+
print <<END;
<tr>
<td align="center" $col>
<td align="center" $col>
$remark
</td>
-
- <td align="center" $col>
- <strong><font color="$status_colour"><abbr title="$status_message">$status_short</abbr></font></strong>
- </td>
END
;
+ # Display server status if requested.
+ if ($check_servers) {
+print <<END
+ <td align="center" $col>
+ <strong><font color="$status_colour"><abbr title="$status_message">$status_short</abbr></font></strong>
+ </td>
+END
+;
+ }
+
# Check if the id is greater than "2".
#
# Nameservers with an ID's of one or two are ISP assigned,
# and we cannot perform any actions on them, so hide the tools for
# them.
- if ($id gt "2") {
+ if ($id > 2) {
print <<END;
<td align='center' width='5%' $col>
print"<table width='100%'>\n";
# Check if the usage of the ISP nameservers is enabled and there are more than 2 servers.
- if (($settings{'USE_ISP_NAMESERVERS'} eq "on") && ($server_amount gt "2")) {
+ if (($settings{'USE_ISP_NAMESERVERS'} eq "on") && ($server_amount > 2)) {
print <<END;
<tr>
<td class='boldbase'> <b>$Lang::tr{'legend'}:</b></td>
print <<END;
<tr>
<form method="post" action="$ENV{'SCRIPT_NAME'}">
- <td colspan="9" align="right"><input type="submit" name="SERVERS" value="$Lang::tr{'add'}"></td>
+ <td colspan="9" align="right">
+ <input type="submit" name="SERVERS" value="$Lang::tr{'add'}">
+ <input type="submit" name="SERVERS" value="$Lang::tr{'dns check servers'}">
+ </td>
</form>
</tr>
</table>
END
;
-
} else {
-print <<END;
+ print <<END;
<table width="100%">
- <tr>
- <td colspan="6" align="center">
- <br>$Lang::tr{'guardian no entries'}<br>
- </td>
- </tr>
-
<tr>
<form method="post" action="$ENV{'SCRIPT_NAME'}">
<td colspan="6" align="right"><input type="submit" name="SERVERS" value="$Lang::tr{'add'}"></td>
</form>
</tr>
</table>
-
END
-;
}
&Header::closebox();
&Header::openbox('100%', 'left', $Lang::tr{'dnsforward add a new entry'});
}
+ my $tls_required_image;
+
+ # If the protocol is TLS, dispaly the required image.
+ if ($settings{'PROTO'} eq "TLS") {
+ $tls_required_image = "<img src='/blob.gif' alt='*'>";
+ }
+
# Add hidden input to store the mode.
print "<input type='hidden' name='MODE' value='$cgiparams{'SERVERS'}'>\n";
<td width='20%' class='base'>$Lang::tr{'ip address'}: <img src='/blob.gif' alt='*' /></td>
<td><input type='text' name='NAMESERVER' value='$cgiparams{"NAMESERVER"}' size='24' /></td>
</tr>
-END
-;
- # If the protocol is TLS, display the TLS hostname input.
- if ($settings{'PROTO'} eq "TLS") {
-print <<END
+
+
<tr>
- <td width='20%' class='base'>$Lang::tr{'dns tls hostname'}: <img src='/blob.gif' alt='*'></td>
+ <td width='20%' class='base'>$Lang::tr{'dns tls hostname'}: $tls_required_image</td>
<td><input type='text' name='TLS_HOSTNAME' value='$cgiparams{'TLS_HOSTNAME'}' size='24'></td>
</tr>
-END
-;
- }
-print <<END
<tr>
<td width ='20%' class='base'>$Lang::tr{'remark'}:</td>
&Header::closebox();
}
-# Tiny function to grab an IP-address of a given file.
-sub grab_address_from_file($) {
- my ($file) = @_;
-
- my $address;
-
- # Check if the given file exists.
- if(-f $file) {
- # Open the file for reading.
- open(FILE, $file) or die "Could not read from $file. $!\n";
-
- # Read the address from the file.
- $address = <FILE>;
-
- # Close filehandle.
- close(FILE);
-
- # Remove newlines.
- chomp($address);
+# Private function to handle the restart of unbound and more.
+sub _handle_unbound_and_more () {
+ # Check if the IDS is running.
+ if(&IDS::ids_is_running()) {
+ # Re-generate the file which contains the DNS Server
+ # details.
+ &IDS::generate_dns_servers_file();
- # Check if the obtained address is valid.
- if (&General::validip($address)) {
- # Return the address.
- return $address;
- }
+ # Call suricatactrl to perform a reload.
+ &IDS::call_suricatactrl("restart");
}
+ # Restart unbound
+ system('/usr/local/bin/unboundctrl reload >/dev/null');
+}
- # Return nothing.
- return;
+# Check if the system is online (RED is connected).
+sub red_is_active () {
+ # Check if the "active" file is present.
+ if ( -f "${General::swroot}/red/active") {
+ # Return "1" - True.
+ return 1;
+ } else {
+ # Return nothing - False.
+ return;
+ }
}
# Function to check a given nameserver against propper work.
-sub check_nameserver($$$$) {
- my ($nameserver, $record, $proto, $tls_hostname) = @_;
+sub check_nameserver($$$$$) {
+ my ($nameserver, $record, $proto, $tls_hostname, @args) = @_;
+
+ # Check if the system is online.
+ unless (&red_is_active()) {
+ return "$Lang::tr{'system is offline'}";
+ }
# Default values.
- my @command = ("kdig", "+timeout=2", "+retry=0", "+dnssec",
- "+bufsize=1232");
+ my @command = ("kdig", "+dnssec",
+ "+bufsize=1232", @args);
# Handle different protols.
if ($proto eq "TCP") {