Since using Docker as the underlying environment, I wanted to write a panel that can be used to manage services in a unified and centralized manner. On the one hand, I don't want to use widely used panels on the market because I can do better than them. On the other hand, it can also be considered as a practice.
Overview#
Looking at the website certificate, yes! It has been changed to a wildcard certificate~
Let me briefly explain the buggy features that have been implemented so far. As mentioned earlier, I manage the certificates centrally in a panel. The panel integrates a file called getcerfile.php
that can be accessed directly (of course, with authentication. Certificates should not be put on the public network without authentication). The certificates are issued using Let's Encrypt wildcard certificates, so there is no need to worry about which server the certificates are issued to. No need to reinvent the wheel, yay!
Certificate Checking#
This part is mainly inspired by Axton. For details, please refer to this article. Since I am relatively weak and currently do not want to use a database to store data, I am using files and shell scripts to perform certificate checks, and then using PHP to output the results in a more presentable format and embed them in the panel.
Screenshot:
Hmmmmmmmm, I found that my self-built image hosting service seems to have some problems when uploading... Should I consider building my own? I'll think about it later.
Here is the code:
#!/bin/sh
cat urlfile.list | while read line
do
touch "data/$line"
touch "data/$line.ca"
curl https://$line -v -s -o /dev/null 2>"data/$line.ca"
datee=$(date +'%F %H:%M')
echo "Last check: " $datee > "data/$line"
data=$(cat "data/$line.ca" | grep 'subject:')
echo "Certificate domain: " ${data##* subject: } >> "data/$line"
data=$(cat "data/$line.ca" | grep 'start date:')
data=$(date -d "${data##* start date: }" +'%F %H:%M:%S')
echo "Issue date: "${data} >> "data/$line"
startdate=$data
data=$(cat "data/$line.ca" | grep 'expire date: ')
data=$(date -d "${data##* expire date: }" +'%F %H:%M:%S')
echo "Expiration date: " $data >> "data/$line"
enddate=$data
data=$(cat "data/$line.ca" | grep 'issuer: ')
echo "Issuer: "${data##* issuer: } >> "data/$line"
data=$(cat "data/$line.ca" | grep 'SSL certificate verify ok.')
echo "Certificate status: "${data##* } >> "data/$line"
startdate=$(date -d "${startdate}" +%s)
enddate=$(date -d "${enddate}" +%s)
datee=$(date -d "${datee}" +%s)
long=$(($enddate-$startdate))
datee=$(($datee-$startdate))
datee=$(($datee*100))
hundred=100
persent=$(($datee/$long))
echo "<div class=\"mdui-progress\"><div class=\"mdui-progress-determinate\" style=\"width: ${persent}%;\"></div></div>" >> "data/$line"
rm "data/$line.ca"
done
The code for display is as follows:
<?php
include_once 'config.php';
if ($_COOKIE["user"] == md5($username.$userpasswd)) {
echo '<div class="mdui-panel" mdui-panel>';
function listDir($dir)
{
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if ($file != "." && $file != "..") {
echo '<div class="mdui-panel-item">';
echo '<div class="mdui-panel-item-header">'.'<div class="mdui-panel-item-title">'.$file.'</div>'.'<i class="mdui-panel-item-arrow mdui-icon material-icons">keyboard_arrow_down</i>'.'</div>';
echo '<div class="mdui-panel-item-body">';
$myfile = fopen("$dir/$file", "r") or die("Unable to open file!");
while (!feof($myfile)) {
echo '<p>'.fgets($myfile) . '</p>';
}
echo '</div></div>';
fclose($myfile);
}
}
closedir($dh);
}
} else {
echo $dir . '<br>';
}
}
listDir("./data");
echo '</div>';
} else {
echo 'error';
}
?>
Certificate Distribution#
Emmmm, as you can see from above, I use the username and password to generate an MD5 hash and store it in a cookie for authentication. The domain names that need to be authenticated are directly stored in the urlfile.list
file (I'm really not good at this).
Similarly, certificate distribution also uses cookies for authentication.
<?php
include_once 'config.php';
if ($_COOKIE["user"] == md5($username.$userpasswd)) {
$myfile = fopen($_GET['file'], "r") or die("Unable to open file!");
echo fread($myfile, filesize($_GET['file']));
fclose($myfile);
} else {
header("Location: /index.php");
}
?>
Then, the certificate file is read and directly output. At the same time, the file directory is controlled by Nginx to restrict access to the files. To obtain the certificate, use the following command:
curl https://****/getcerfile.php?file=ssl/lvcshu.com/lvcshu.com.key -H 'cookie: user=???' > lvcshu.com.key
This way, the script can be executed periodically on the certificate server to update the certificates. Meanwhile, the wildcard certificate is automatically renewed using acme.sh. Well, that's about it. If any of you experts find anything inappropriate, please contact me in a timely manner. QAQ
Telegram:@johnpoint