mirror of
https://github.com/unraid/webgui.git
synced 2026-05-20 13:19:46 -05:00
Merge pull request #1122 from ljm42/feat-cert-details
add details for self-signed certs
This commit is contained in:
@@ -1153,6 +1153,13 @@ Select **Strict** to enable *exclusive* use of an Unraid.net SSL
|
||||
certificate for https access (see **Provision** below). Note that a DNS
|
||||
server must be reachable.
|
||||
|
||||
**Redirects:** When accessing `http://<server-ip-address>` or `http://<server-name>.<localTLD>`, the
|
||||
behavior will change depending on the value of the Use SSL/TLS setting:
|
||||
|
||||
* If Use SSL/TLS is set to **Strict**, you will be redirected to `https://<lan-ip>.<hash>.myunraid.net`
|
||||
* If Use SSL/TLS is set to **Yes**, you will be redirected to `https://<server-ip-address> or https://<server-name>.<localTLD>`
|
||||
* If Use SSL/TLS is set to **No**, then the http url will load directly.
|
||||
|
||||
Important: **Strict** may not be selectable if your router or upstream DNS server has
|
||||
[DNS rebinding protection](https://en.wikipedia.org/wiki/DNS_rebinding) enabled. DNS rebinding
|
||||
protection prevents DNS from resolving a private IP network range. DNS rebinding protection is meant as
|
||||
@@ -1200,6 +1207,11 @@ Enter the HTTPS port, default port is 443.
|
||||
Enter your local Top Level Domain. May be blank.
|
||||
:end
|
||||
|
||||
:mgmt_local_access_urls_help:
|
||||
The Local Access URLs shown above are based on your current settings.
|
||||
To adjust URLs or redirects, see the help text for "Use SSL/TLS".
|
||||
:end
|
||||
|
||||
:mgmt_certificate_expiration_help:
|
||||
**Provision** may be used to install a *free* Unraid.net SSL Certificate from
|
||||
[Let's Encrypt](https://letsencrypt.org/).
|
||||
|
||||
@@ -38,6 +38,19 @@ function find_tasks() {
|
||||
sort($tasks);
|
||||
return $tasks;
|
||||
}
|
||||
function acceptableCert($certFile, $hostname, $expectedURL) {
|
||||
if (!file_exists($certFile)) return false;
|
||||
$certURLs=null;
|
||||
// get Subject URL and all SAN URLs from cert
|
||||
exec("openssl x509 -noout -subject -nameopt multiline -in $certFile | sed -n 's/ *commonName *= //p' ; openssl x509 -noout -ext subjectAltName -in $certFile | grep -Eo \"DNS:[a-zA-Z 0-9.*-]*\" | sed \"s/DNS://g\"", $certURLs);
|
||||
foreach($certURLs as $certURL) {
|
||||
// adjust for wildcard certs
|
||||
$certURL = str_replace('*', $hostname, $certURL);
|
||||
// case-insensitive compare
|
||||
if (strcasecmp($certURL, $expectedURL) == 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$tasks = find_tasks();
|
||||
$ethX = 'eth0';
|
||||
#$addr = ipaddr($ethX);
|
||||
@@ -45,29 +58,41 @@ $addr = $_SERVER['SERVER_ADDR'];
|
||||
$keyfile = @file_get_contents($var['regFILE']);
|
||||
if ($keyfile !== false) $keyfile = base64_encode($keyfile);
|
||||
|
||||
$certFile = "/boot/config/ssl/certs/certificate_bundle.pem";
|
||||
$certPresent = file_exists("$certFile");
|
||||
if ($certPresent) {
|
||||
$certSubject = exec("/usr/bin/openssl x509 -in $certFile -noout -subject -nameopt multiline 2>/dev/null|sed -n 's/ *commonName *= //p'");
|
||||
$certIssuer = exec("/usr/bin/openssl x509 -in $certFile -noout -text | sed -n -e 's/^.*Issuer: //p'");
|
||||
$certExpires = exec("/usr/bin/openssl x509 -in $certFile -noout -text | sed -n -e 's/^.*Not After : //p'");
|
||||
$isLegacyCert = preg_match('/.*\.unraid\.net$/', $certSubject);
|
||||
$isWildcardCert = preg_match('/.*\.myunraid\.net$/', $certSubject);
|
||||
// self-signed or user-provided cert
|
||||
$cert1File = "/boot/config/ssl/certs/{$var['NAME']}_unraid_bundle.pem";
|
||||
$cert1Present = file_exists("$cert1File");
|
||||
if ($cert1Present) {
|
||||
$cert1URL = $var['NAME'].".".$var['LOCAL_TLD'];
|
||||
// if user replaced cert without reloading nginx, the cert on the flash could be invalid
|
||||
$cert1URLvalid = acceptableCert($cert1File, $var['NAME'], $cert1URL);
|
||||
$cert1Issuer = exec("/usr/bin/openssl x509 -in $cert1File -noout -text | sed -n -e 's/^.*Issuer: //p'");
|
||||
$cert1Expires = exec("/usr/bin/openssl x509 -in $cert1File -noout -text | sed -n -e 's/^.*Not After : //p'");
|
||||
}
|
||||
|
||||
// unraid.net, myunraid.net LE cert. could potentially be user provided as well
|
||||
$cert2File = "/boot/config/ssl/certs/certificate_bundle.pem";
|
||||
$cert2Present = file_exists("$cert2File");
|
||||
if ($cert2Present) {
|
||||
$cert2Subject = exec("/usr/bin/openssl x509 -in $cert2File -noout -subject -nameopt multiline 2>/dev/null|sed -n 's/ *commonName *= //p'");
|
||||
$cert2Issuer = exec("/usr/bin/openssl x509 -in $cert2File -noout -text | sed -n -e 's/^.*Issuer: //p'");
|
||||
$cert2Expires = exec("/usr/bin/openssl x509 -in $cert2File -noout -text | sed -n -e 's/^.*Not After : //p'");
|
||||
$isLegacyCert = preg_match('/.*\.unraid\.net$/', $cert2Subject);
|
||||
$isWildcardCert = preg_match('/.*\.myunraid\.net$/', $cert2Subject);
|
||||
$isLEcert = $isLegacyCert || $isWildcardCert;
|
||||
$subjectURL = $certSubject;
|
||||
$subject2URL = $cert2Subject;
|
||||
if ($isWildcardCert) {
|
||||
if (strpos($addr, ":") === false)
|
||||
$subjectURL = str_replace("*", str_replace(".", "-", $addr), $subjectURL);
|
||||
$subject2URL = str_replace("*", str_replace(".", "-", $addr), $subject2URL);
|
||||
else
|
||||
$subjectURL = str_replace("*", str_replace(":", "-", $addr), $subjectURL);
|
||||
$subject2URL = str_replace("*", str_replace(":", "-", $addr), $subject2URL);
|
||||
}
|
||||
if ($isLEcert) {
|
||||
exec("openssl x509 -checkend 2592000 -noout -in $certFile 2>/dev/null", $arrout, $retval_expired);
|
||||
exec("openssl x509 -checkend 2592000 -noout -in $cert2File 2>/dev/null", $arrout, $retval_expired);
|
||||
if (strpos($addr, ":") === false) {
|
||||
$rebindtest_ip = exec("host -4 -t A rebindtest4.myunraid.net 2>/dev/null|awk '{print \$4}'");
|
||||
$dnsRebindingProtection = ($rebindtest_ip != "192.168.42.42");
|
||||
if (!$dnsRebindingProtection) {
|
||||
$cert_ip = exec("host -4 -t A $subjectURL 2>/dev/null|awk '{print \$4}'");
|
||||
$cert_ip = exec("host -4 -t A $subject2URL 2>/dev/null|awk '{print \$4}'");
|
||||
$dnsValid = $cert_ip==$addr;
|
||||
}
|
||||
} else {
|
||||
@@ -76,18 +101,53 @@ if ($certPresent) {
|
||||
// $dnsRebindingProtection = ($rebindtest_ip != "fd42::42");
|
||||
$dnsRebindingProtection = ($rebindtest_ip != "fd42::42") && ($rebindtest_ip != "fd42::");
|
||||
if (!$dnsRebindingProtection) {
|
||||
$cert_ip = exec("host -6 -t AAAA $subjectURL 2>/dev/null|awk '{print \$4}'");
|
||||
$cert_ip = exec("host -6 -t AAAA $subject2URL 2>/dev/null|awk '{print \$4}'");
|
||||
$dnsValid = $cert_ip==$addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$nginx = parse_ini_file('/var/local/emhttp/nginx.ini');
|
||||
$http_port = $var['PORT'] != 80 ? ":{$var['PORT']}" : '';
|
||||
$https_port = $var['PORTSSL'] != 443 ? ":{$var['PORTSSL']}" : '';
|
||||
|
||||
$http_ip_url = "http://{$nginx['NGINX_LANIP']}{$http_port}/";
|
||||
$http_url = "http://{$nginx['NGINX_LANMDNS']}{$http_port}/";
|
||||
$https_ip_url = "https://{$nginx['NGINX_LANIP']}{$https_port}/";
|
||||
$https_url = "https://{$nginx['NGINX_LANMDNS']}{$https_port}/";
|
||||
$https_2_url = "https://{$nginx['NGINX_LANFQDN']}{$https_port}/";
|
||||
|
||||
$urls = array();
|
||||
// push an array of three values into the $urls array:
|
||||
// 0 - the url
|
||||
// 1 - the url it redirects to, or null
|
||||
// 2 - the certificate file used, or null
|
||||
switch($var['USE_SSL']) {
|
||||
case 'no':
|
||||
$urls[] = [$http_ip_url, null, null];
|
||||
$urls[] = [$http_url, null, null];
|
||||
if ($nginx['NGINX_LANFQDN']) $urls[] = [$https_2_url, null, "certificate_bundle.pem"];
|
||||
break;
|
||||
case 'yes':
|
||||
$urls[] = [$http_ip_url, $https_ip_url, null];
|
||||
$urls[] = [$https_ip_url, null, "{$var['NAME']}_unraid_bundle.pem"];
|
||||
$urls[] = [$http_url, $https_url, null];
|
||||
$urls[] = [$https_url, null, "{$var['NAME']}_unraid_bundle.pem"];
|
||||
if ($nginx['NGINX_LANFQDN']) $urls[] = [$https_2_url, null, "certificate_bundle.pem"];
|
||||
break;
|
||||
case 'auto': // aka strict
|
||||
$urls[] = [$http_ip_url, $https_2_url, null];
|
||||
$urls[] = [$http_url, $https_2_url, null];
|
||||
$urls[] = [$https_2_url, null, "certificate_bundle.pem"];
|
||||
break;
|
||||
}
|
||||
|
||||
$cert_time_format = $display['date'].($display['date']!='%c' ? ', '.str_replace(['%M','%R'],['%M:%S','%R:%S'],$display['time']):'');
|
||||
$provisionlabel = $isLEcert ? _('Renew') : _('Provision');
|
||||
$disabled_provision = $keyfile===false || ($isLEcert && $retval_expired===0) ? 'disabled' : '';
|
||||
$disabled_updatedns = $keyfile!==false && $isLEcert ? '' : 'disabled';
|
||||
$disabled_delete = $certPresent && $var['USE_SSL']!='auto' ? '' : 'disabled';
|
||||
$disabled_delete = $cert2Present && $var['USE_SSL']!='auto' ? '' : 'disabled';
|
||||
$disabled_auto = $isLEcert && !$dnsRebindingProtection && $dnsValid ? '' : 'disabled';
|
||||
$upgradelabel = _('Upgrade Cert');
|
||||
|
||||
@@ -275,22 +335,68 @@ _(Local TLD)_:
|
||||
: <input type="button" value="_(Apply)_" onclick="checkPorts(this.form)" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
|
||||
</form>
|
||||
|
||||
<div style="height:24px"></div>
|
||||
<form markdown="1">
|
||||
|
||||
<?
|
||||
echo "<dl><dt>"._("Local Access URLs").":</dt>\n";
|
||||
echo "<dd><br><ul>\n";
|
||||
foreach($urls as $url) {
|
||||
if ($url[1]) $msg = " ("._("redirects to")." <a href='{$url[1]}'>{$url[1]}</a>)";
|
||||
if ($url[2]) $msg = " ("._("uses certificate")." {$url[2]} )";
|
||||
echo "<li><a href='{$url[0]}'>{$url[0]}</a>{$msg}</li>\n";
|
||||
}
|
||||
echo "</ul></dd></dl>\n";
|
||||
?>
|
||||
|
||||
:mgmt_local_access_urls_help:
|
||||
|
||||
</form>
|
||||
|
||||
<div style="height:24px"></div>
|
||||
<form markdown="1">
|
||||
<?if ($cert1Present):?>
|
||||
_(Self-signed or user-provided certificate)_:
|
||||
: <?=$cert1File?>
|
||||
|
||||
<?if ($cert1URLvalid):?>
|
||||
_(Certificate URL)_:
|
||||
: [<?=$cert1URL?>](https://<?=$cert1URL?>:<?=$var['PORTSSL']?>)
|
||||
<?else:?>
|
||||
_(Certificate URL)_:
|
||||
: Certificate not valid for <?=$cert1URL?>
|
||||
<?endif;?>
|
||||
|
||||
_(Certificate issuer)_:
|
||||
: <?=$cert1Issuer?>
|
||||
|
||||
_(Certificate expiration)_:
|
||||
: <?=_(strftime($cert_time_format, strtotime($cert1Expires)),0)?>
|
||||
|
||||
<?else:?>
|
||||
_(Self-signed certificate file)_:
|
||||
: _(Not present)_
|
||||
<?endif;?>
|
||||
|
||||
</form>
|
||||
|
||||
<div style="height:24px"></div>
|
||||
<form markdown="1" name="Provision" method="POST" target="progressFrame" action="/update.htm" onsubmit="provisionHandler(event, this)">
|
||||
<input type="hidden" name="server_name" value="<?=strtok($_SERVER['HTTP_HOST'],":")?>">
|
||||
<input type="hidden" name="server_addr" value="<?=$_SERVER['SERVER_ADDR']?>">
|
||||
<?if ($certPresent):?>
|
||||
_(CA-signed certificate file)_:
|
||||
: <?=$certFile?>
|
||||
<?if ($cert2Present):?>
|
||||
_(Unraid Let's Encrypt certificate)_:
|
||||
: <?=$cert2File?>
|
||||
|
||||
_(Certificate subject)_:
|
||||
: [<?=$certSubject?>](https://<?=$subjectURL?>:<?=$var['PORTSSL']?>)
|
||||
_(Certificate URL)_:
|
||||
: [<?=$cert2Subject?>](https://<?=$subject2URL?>:<?=$var['PORTSSL']?>)
|
||||
|
||||
_(Certificate issuer)_:
|
||||
: <?=$certIssuer?>
|
||||
: <?=$cert2Issuer?>
|
||||
|
||||
_(Certificate expiration)_:
|
||||
: <?=_(strftime($cert_time_format, strtotime($certExpires)),0)?>
|
||||
: <?=_(strftime($cert_time_format, strtotime($cert2Expires)),0)?>
|
||||
|
||||
<?if ($dnsRebindingProtection):?>
|
||||
|
||||
@@ -309,7 +415,7 @@ _(CA-signed certificate file)_:
|
||||
|
||||
: <button type="submit" name="changePorts" value="Provision" <?=$disabled_provision?>><?=$provisionlabel?></button><button type="submit" name="changePorts" value="Delete" <?=$disabled_delete?> >_(Delete)_</button><!-- <button type="button" onclick="updateDNS(this)" <?=$disabled_updatedns?>>_(Update DNS)_</button> -->
|
||||
|
||||
<?if ($certPresent && $isLegacyCert):?>
|
||||
<?if ($cert2Present && $isLegacyCert):?>
|
||||
|
||||
: <button type="submit" name="changePorts" value="Upgrade"><?=$upgradelabel?></button>
|
||||
<?endif;?>
|
||||
|
||||
Reference in New Issue
Block a user