Compare commits

..

No commits in common. "144d8a23b3474d1f294ce29b01c89de80d4d0267" and "48830851b8c5b0dedb550d34859273cc0ed26cf8" have entirely different histories.

16 changed files with 33 additions and 553 deletions

View File

@ -1,106 +0,0 @@
<?php
/**
* vpanel-stack
* https://git.stack-source.com/msb/vpanel-stack
* Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
* GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
*/
namespace Panel;
class Vdns extends \Panel {
function beforeRoute($f3) {
parent::beforeRoute($f3);
if ($f3->get('PDNSADMIN') != '1') {
$f3->reroute('/');
}
}
public static function verifyZoneExists($zone) {
global $f3;
exec("/usr/local/bin/vdns-zone-ext.sh -z $zone", $output, $result_code);
if ($result_code == 0 && $output[0] == 'true') {
return TRUE;
} else {
return FALSE;
}
}
public static function returnZoneDefaultsArray($zone) {
global $f3;
if ($defaults_array = $f3->call('\Panel::vGet', array("vdns-zone-def.sh -z $zone -c", FALSE))) {
return $defaults_array;
} else {
return FALSE;
}
}
public static function returnZoneDefaultsNameserverArray($zone) {
global $f3;
if ($defaults_array = $f3->call('\Panel\Vdns::returnZoneDefaultsArray', $zone)) {
$defaults_ns_array = array();
foreach($defaults_array as $record_array) {
if ($record_array['type'] == "NS") {
$defaults_ns_array[] = $record_array['content'];
}
}
sort($defaults_ns_array);
return $defaults_ns_array;
} else {
return FALSE;
}
}
public static function returnNameserverArray($zone) {
global $f3;
$ns_array = array();
if ($dns_ns_array = dns_get_record("$zone", DNS_NS)) {
foreach ($dns_ns_array as $record_array) {
$ns_array[] = $record_array['target'];
}
sort($ns_array);
return $ns_array;
} else {
return FALSE;
}
}
public static function returnNameserverStatus($zone) {
global $f3;
if ($defaults_ns_array = $f3->call('\Panel\Vdns::returnZoneDefaultsNameserverArray', $zone)) {
if ($ns_array = $f3->call('\Panel\Vdns::returnNameserverArray', $zone)) {
if ($defaults_ns_array === $ns_array) {
return "Verified";
} else {
return "Pending";
}
} else {
return "Unknown";
}
} else {
return "Error";
}
}
}

View File

@ -1,73 +0,0 @@
<?php
/**
* vpanel-stack
* https://git.stack-source.com/msb/vpanel-stack
* Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
* GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
*/
namespace Panel\Vdns;
class Zones extends \Panel\Vdns {
/* use this to make query */
function beforeRoute($f3) {
parent::beforeRoute($f3);
if ($f3->exists('PARAMS.zone')) {
$zone = $f3->get('PARAMS.zone');
if ($f3->call('\Panel\Vdns::verifyZoneExists', $zone)) {
if ($zone_array = $f3->call('\Panel::vGet', array("vdns-zone-exp.sh -z $zone -c", FALSE))) {
$f3->set('zone_array', $zone_array);
}
$ns_info_array = array();
$ns_info_array['zone'] = $zone;
$ns_info_array['status'] = $f3->call('\Panel\Vdns::returnNameserverStatus', $zone);
if ($ns_info_array['status'] != "Verified") {
$ns_info_array['defaults_ns_array'] = $f3->call('\Panel\Vdns::returnZoneDefaultsNameserverArray', $zone);
$ns_info_array['ns_array'] = $f3->call('\Panel\Vdns::returnNameserverArray', $zone);
}
$f3->set('ns_info_array', $ns_info_array);
}
} else {
if ($zones_array = $f3->call('\Panel::vGet', array("vdns-zone-lst.sh", FALSE))) {
foreach ($zones_array as $k=>$zone_array) {
$zones_array[$k]['ns_status'] = $f3->call('\Panel\Vdns::returnNameserverStatus', $zone_array['zone']);
}
$f3->set('zones_array', $zones_array);
}
}
}
static function get($f3) {
if ($f3->exists('PARAMS.zone')) {
$zone = $f3->get('PARAMS.zone');
if (is_array($f3->get('zone_array'))) {
$f3->set('page_header', "DNS Zone records for $zone");
echo \Template::instance()->render('vdns/zones-zone.html');
} else {
$messages[] = "Zone $zone not found.";
$f3->set('SESSION.messages', $messages);
$f3->reroute("/DNS");
}
} else {
$f3->set('page_header', "DNS Zones");
echo \Template::instance()->render('vdns/zones.html');
}
}
}

View File

@ -1,69 +0,0 @@
<?php
/**
* vpanel-stack
* https://git.stack-source.com/msb/vpanel-stack
* Copyright (c) 2024 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
* GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
*/
namespace Panel\Vdns;
class ZonesAdd extends \Panel\Vdns {
function beforeRoute($f3) {
parent::beforeRoute($f3);
}
static function get($f3) {
echo \Template::instance()->render('vdns/zones-add.html');
}
function post($f3) {
// print_r($_POST);
/* force zone to be all lower case */
$zone = strtolower($_POST['zone']);
/* strip spaces */
$zone = trim($zone);
/* remove leading www. */
$zone = preg_replace('/^www\./', '', $zone);
/* remove trailing . (dot) */
$zone = rtrim($zone, '.');
if ($f3->call('\Panel::validateDomain', $zone)) {
/* check if zone exists */
if ($f3->call('\Panel\Vdns::verifyZoneExists', $zone)) {
$messages[] = "Zone $zone already exists in DNS.";
$messages[] = "Note if $zone should be associated with this server but it's now showing up in the list below please contact support.";
$f3->set('SESSION.messages', $messages);
$f3->call('\Panel\Vdns\ZonesAdd::get', $f3);
} else {
$hostname = $f3->get('NAV.hostname');
exec("/usr/local/bin/vdns-zone-add.sh -z $zone -w hostname=$hostname/$zone", $output, $result_code);
if ($result_code == 0) {
$messages[] = "Zone (Domain Name) $zone has been added to DNS.";
$f3->set('SESSION.messages', $messages);
$f3->reroute("/DNS");
} else {
if (count($output) > 0) {
foreach ($output as $k=>$output_message) {
$messages[] = "$output_message";
}
} else {
$messages[] = "Unknown error adding Zone $zone to DNS.";
}
$f3->set('SESSION.messages', $messages);
$f3->call('\Panel\Vdns\ZonesAdd::get', $f3);
}
}
} else {
$f3->call('\Panel\Vdns\ZonesAdd::get', $f3);
}
}
}

View File

@ -1,46 +0,0 @@
<?php
/**
* vpanel-stack
* https://git.stack-source.com/msb/vpanel-stack
* Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
* GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
*/
namespace Panel\Vdns;
class ZonesDelete extends \Panel\Vdns {
function beforeRoute($f3) {
parent::beforeRoute($f3);
/* verify zone exists */
$zone = $f3->get('PARAMS.zone');
if (!$f3->call('\Panel\Vdns::verifyZoneExists', $zone)) {
$messages[] = "Zone '$zone' does not exist.";
$f3->set('SESSION.messages', $messages);
$f3->reroute("/DNS");
}
}
static function get($f3) {
$f3->set('confirm', 'true');
echo \Template::instance()->render('vdns/zones-delete.html');
}
function post($f3) {
/* run delete command here */
$zone = $f3->get('PARAMS.zone');
exec("/usr/local/bin/vdns-zone-del.sh -z $zone -x", $output, $result_code);
$messages[] = "Zone '$zone' has been deleted from DNS.";
$f3->set('SESSION.messages', $messages);
$f3->reroute("/DNS");
}
}

View File

@ -104,22 +104,7 @@ class Domains extends \Panel\Vmail {
$dnsinfo['dkim']['status'] = "Create"; $dnsinfo['dkim']['status'] = "Create";
} }
# DMARC (TXT) record if ($dnsinfo['verified_count'] == 4) {
$dnsinfo['dmarc']['status'] = "Create";
$dnsinfo['dmarc']['color'] = "red";
if ($dns_txt_records = dns_get_record("_dmarc.$domain", DNS_TXT)) {
foreach ($dns_txt_records as $k=>$dns_txt_record) {
if (str_starts_with($dns_txt_record['txt'], 'v=DMARC1')) {
$dnsinfo['dmarc']['status'] = "Verified";
$dnsinfo['dmarc']['color'] = "black";
$dnsinfo['verified_count']++;
} else {
$dnsinfo['dmarc']['status'] = "Update";
}
}
}
if ($dnsinfo['verified_count'] == 5) {
$dnsinfo['status'] = 'Verified'; $dnsinfo['status'] = 'Verified';
} else { } else {
$dnsinfo['status'] = 'Update'; $dnsinfo['status'] = 'Update';

View File

@ -28,9 +28,3 @@ FPMMAX=4
WRITEUSERINFO=1 WRITEUSERINFO=1
; Show "Write User Info" & "Write DB Info" options. If no then just use defaults above without giving users the option to change. 1 = Yes, blank or 0 = No ; Show "Write User Info" & "Write DB Info" options. If no then just use defaults above without giving users the option to change. 1 = Yes, blank or 0 = No
SHOWWRITEINFO=0 SHOWWRITEINFO=0
; DNS admin. 1 = Yes, blank or 0 = No
PDNSADMIN=0
; Maximum number of results returned for DNS listings. Defaults to 100 if unspecified.
;PDNSMAX=100
; URL to phpMyPDNS. If this is set, and PDNSADMIN is enabled, show link to phpMyPDNS
PHPMYPDNSURL=

View File

@ -1,11 +0,0 @@
; vpanel-stack
; https://git.stack-source.com/msb/vpanel-stack
; Copyright (c) 2024 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
; GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
[maps]
; Vdns
/DNS [sync] = Panel\Vdns\Zones
/DNS/@zone [sync] = Panel\Vdns\Zones
/DNS/Add [sync] = Panel\Vdns\ZonesAdd
/DNS/@zone/Delete [sync] = Panel\Vdns\ZonesDelete

View File

@ -84,3 +84,4 @@
/Certs/@cert/Delete [sync] = Panel\Cert\CertsDelete /Certs/@cert/Delete [sync] = Panel\Cert\CertsDelete
/Databases [sync] = Panel\MySQL\Databases /Databases [sync] = Panel\MySQL\Databases

View File

@ -38,11 +38,6 @@ if ($f3->get('HOST') == $f3->get('NAV.hostname')) {
$f3->set('NAV.mapping', $mapping); $f3->set('NAV.mapping', $mapping);
$f3->config("config/maps-$mapping.ini"); $f3->config("config/maps-$mapping.ini");
/* load DNS mapping, if enabled */
if ($f3->get('PDNSADMIN') == '1') {
$f3->config("config/maps-vdns.ini");
}
/* custom error page */ /* custom error page */
$f3->set('ONERROR',function($f3){ $f3->set('ONERROR',function($f3){
echo \Template::instance()->render('error.html'); echo \Template::instance()->render('error.html');

View File

@ -33,7 +33,6 @@
<a href="{{@BASE}}/Databases">Databases</a> | <a href="{{@BASE}}/Databases">Databases</a> |
<a href="{{@BASE}}/Certs">Certificates</a> | <a href="{{@BASE}}/Certs">Certificates</a> |
<a href="{{@BASE}}/Users">Users</a> | <a href="{{@BASE}}/Users">Users</a> |
<check if="{{ @PDNSADMIN=='1' }}"><a href="{{@BASE}}/DNS">DNS</a> |</check>
<a href="{{@BASE}}/Logout">Logout</a> <a href="{{@BASE}}/Logout">Logout</a>
</check> </check>

View File

@ -1,5 +1,5 @@
<include href="header.html" /> <include href="header.html" />
Welcome to {{@PACKAGE}}! Welcome to {{@PACKAGE}}. Get cracking!
<include href="footer.html" /> <include href="footer.html" />

View File

@ -1,20 +0,0 @@
<include href="header.html" />
<form action="{{@REALM}}" method="POST">
<h4 id="Add_New_Zone">Add New Zone</h4>
<fieldset>
<legend>Domain name to be added to DNS</legend>
<label for="zone">Zone <small>(Domain Name)</small></label>
<input id="zone" name="zone" type="text" placeholder="example.com" value="" required>
<br>
<input type="submit" value="Submit">
<button id="reset" type="reset" disabled>Reset</button>
<!-- <small>Any other form instructions go here.</small> -->
</fieldset>
</form>
<p>
<b>Zone</b> Enter the Domain Name that will be added to DNS.<br>
</p>
<include href="footer.html" />

View File

@ -1,17 +0,0 @@
<include href="header.html" />
<check if="isset(@confirm)">
<form action="{{@NAV.fullpath}}" method="POST">
<fieldset>
<legend>Really Delete Zone {{ @PARAMS.zone }} from DNS</legend>
<br>
<input type="submit" value="Delete {{ @PARAMS.zone }}">
<br>
<small><b>CAUTION:</b> This will permanently remove the zone {{ @PARAMS.zone }} and all associated records from DNS. There is no undo after this!</small>
</fieldset>
</form>
</check>
<include href="footer.html" />

View File

@ -1,86 +0,0 @@
<include href="header.html" />
<check if="isset(@zone_array)">
<p>
<small>
<check if="{{ @ns_info_array.status=='Verified' }}">
<true>
Nameservers for {{ @ns_info_array.zone }} verified. The DNS records below are active.<br>
<check if="isset(@PHPMYPDNSURL)">
You can manage these DNS entries here: <a href="{{ @PHPMYPDNSURL }}">{{ @PHPMYPDNSURL }}</a>
</check>
</true>
<false>
<section style="color:red">NOTICE:</section>
</false>
</check>
<check if="{{ @ns_info_array.status=='Pending' }}">
The Nameservers for {{ @ns_info_array.zone }} are not pointing to this DNS system.<br>
To make this DNS active update the Nameservers at your current Domain Name Registrar to:<br>
<repeat group="{{ @ns_info_array.defaults_ns_array }}" value="{{ @nameserver }}">
<b>{{ @nameserver }}</b><br>
</repeat>
Note that after making this change it can take up to 24 hours for the changes to go through.<br>
<br>
If you are intentionally using another provider for DNS you can reference the records below for what should be added to your DNS (excluding the NS & SOA records).
</check>
<check if="{{ @ns_info_array.status=='Unknown' }}">
The Nameserver verification system could not find nameserver information for {{ @ns_info_array.zone }}.<br>
Make sure the domain name is registered and has the folowing nameservers set:<br>
<repeat group="{{ @ns_info_array.defaults_ns_array }}" value="{{ @nameserver }}">
<b>{{ @nameserver }}</b><br>
</repeat>
</check>
<check if="{{ @ns_info_array.status=='Error' }}">
There was an error verifying the Namservers for {{ @ns_info_array.zone }}.<br>
If this persists please contact tech support.
</check>
</small>
</p>
<true>
<table>
<tr>
<th>Name</th>
<th>TTL</th>
<th>Class</th>
<th>Type</th>
<th>Value</th>
</tr>
<repeat group="{{ @zone_array }}" value="{{ @record_array }}">
<tr>
<td>{{ @record_array.name }}</td>
<td>{{ @record_array.ttl }}</td>
<td>{{ @record_array.class }}</td>
<td>{{ @record_array.type }}</td>
<check if="{{ @record_array.type=='TXT' }}">
<true><td>"{{ @record_array.value }}"</td></true>
<false><td>{{ @record_array.value }}</td></false>
</check>
</tr>
</repeat>
</table>
<p><b>Notes:</b><br>
<ul>
<li>Zone info is displayed in BIND format.<br>You should be able to cut-and-past above records directly into a BIND file, if desired.</li>
<li>MX & SRV records will show the Priority as part of the record.<br>e.g. "10 mail.example.com" indicates a Priority of "10" for "mail.example.com".<br>Only MX & SRV records use Priority, all other records have an unused priority of "0".</li>
</ul>
</p>
<check if="isset(@PHPMYPDNSURL)">
<p><b>phpMyPDNS</b> can be used to manage DNS entries here: <a href="{{ @PHPMYPDNSURL }}">{{ @PHPMYPDNSURL }}</a></p>
</check>
</true>
<false>
<p>No Zone info.</p>
</false>
</check>
<include href="footer.html" />

View File

@ -1,47 +0,0 @@
<include href="header.html" />
<check if="isset(@zones_array)">
<true>
<table>
<tr>
<th>Zone</th>
<th>Nameservers</th>
<th>Action</th>
</tr>
<repeat group="{{ @zones_array }}" value="{{ @zone }}">
<tr>
<td>{{ @zone.zone }}</td>
<check if="{{ @zone.ns_status=='Verified' }}">
<true><td>&check; {{ @zone.ns_status }}</td></true>
<false><td style="color:red">{{ @zone.ns_status }} <small>- click view for details &rarr;</small></td></false>
</check>
<td><a href="{{@REALM}}/{{ @zone.zone }}">View</a> <a href="{{@REALM}}/{{ @zone.zone }}/Delete">Delete</a></td>
</tr>
</repeat>
</table>
</true>
<false>
<p>There are no DNS Zones on this server.</p>
</false>
</check>
<p>
<b>Zone</b> is what a Domain Name is called in DNS.<br>
<b>View</b> zone to see list of all DNS entries.<br>
<b>Delete</b> will remove the zone from DNS entirely.<br>
</p>
<check if="isset(@PHPMYPDNSURL)">
<p><b>phpMyPDNS</b> can be used to manage DNS entries here: <a href="{{ @PHPMYPDNSURL }}">{{ @PHPMYPDNSURL }}</a></p>
</check>
<p>
<a href="{{@NAV.fullpath}}/Add">Add new DNS Zone</a>
</p>
<include href="footer.html" />

View File

@ -124,7 +124,6 @@
<tr><td>Value:</td><td>"v=spf1 a mx -all"</td></tr> <tr><td>Value:</td><td>"v=spf1 a mx -all"</td></tr>
<tr><td>TTL:</td><td>3600 (or default)</td></tr> <tr><td>TTL:</td><td>3600 (or default)</td></tr>
<tr><td></td><td><small>There may be other TXT records for {{ @domain_array.domain }}.</small></td></tr> <tr><td></td><td><small>There may be other TXT records for {{ @domain_array.domain }}.</small></td></tr>
</false>
</check> </check>
</table> </table>
@ -152,24 +151,6 @@
</true> </true>
</check> </check>
</table> </table>
<br><br>
<table>
<tr><th style="color:{{ @dnsinfo.dmarc.color }}" colspan="2">{{ @dnsinfo.dmarc.status }} DMARC (TXT) Record for {{ @domain_array.domain }}</th></tr>
<check if="{{ @dnsinfo.dmarc.status=='Verified' }}">
<true>
<tr><td colspan="2">This DNS record is all set, nothing to do.</td></tr>
</true>
<false>
<tr><td>Type:</td><td>TXT</td></tr>
<tr><td>Host:</td><td>_dmarc.{{ @domain_array.domain }}</td></tr>
<tr><td>Value:</td><td>"v=DMARC1; p=none;"</td></tr>
<tr><td>TTL:</td><td>3600 (or default)</td></tr>
</false>
</check>
</table>
</false> </false>
</check> </check>