Need a whack with a clue-bat for my broken LetsEncrypt e-mail system

Discussion in 'Installation/Configuration' started by IntnsRed, Oct 9, 2025 at 9:32 PM.

  1. IntnsRed

    IntnsRed Member

    Okay, I've had a working ISPConfig system all set up and happily running with Let's Encrypt for SSL. Using the instructions on this page things worked perfectly -- for months or years. Certs with Let's Encrypt auto-updated with each new certificate and I was a happy camper.

    But then Let's Encrypt "broke" and didn't renew my cert and it expired. So I got on my Debian command line as root, and I ran "letsencrypt_renew_hook.sh" a couple of times, waited, and my certificate was renewed. Cool. My web site https was working fine with its new valid certificate and all seemed well.

    But my e-mail was/is broken!

    Looking at the symlinks for PostFix and the directed input for DoveCot, those look golden/great! (They should, they haven't changed.) They point at the proper LetsEncrypt key/cert.

    Again, smtpd.cert
    and smtpd.key files point to the web server's LetsEncrypt cert and key like they should. The key has "600" permissions and the cert "644" permissions.

    I've restarted PostFix and DoveCot but they're broken and I can't make a secure connection.

    Can someone whack me with a clue-bat and tell me what I'm doing wrong?
     
    Last edited: Oct 9, 2025 at 9:43 PM
  2. Taleman

    Taleman Well-Known Member HowtoForge Supporter

  3. IntnsRed

    IntnsRed Member

    This is my htf-common-issues.php file:
    -----------------------------------


    Code:
    #!/usr/bin/php -q
    <?php
    
    /**
     * Howtoforge common-issues-checker (c) 2013 - M. Cramer <[email protected]>
     * Version 0.5
     */
    
    
    define('DEBUG', false);
    define('ANONYMIZE', true);
    define('REPORT_FILE', './htf_report.txt');
    define('POSTFIX_MASTER', '/etc/postfix/master.cf') ;
    
    if(isset($argv[1]) && $argv[1] == '--debug') {
        define('OUTPUT', true);
    } else {
        define('OUTPUT', false);
    }
    
    $netstat_out = '';
    $iptables_out = '';
    $ifconfig_out = '';
    
    if(!function_exists('readline')) {
        function readline($prompt = '') {
            print $prompt;
            return rtrim(fgets(STDIN), "\n");
        }
    
    }
    
    // clean up report file
    $fp = fopen(REPORT_FILE, 'w');
    fclose($fp);
    
    function outlog($line, $anonymize = true) {
        if(OUTPUT == true) {
            print $line . "\n";
        }
        $fp = fopen(REPORT_FILE, 'a');
        fwrite($fp, ($anonymize ? anonip($line) : $line) . "\n");
        fclose($fp);
    }
    
    function anonip($data) {
        if(ANONYMIZE == false) {
            return $data;
        }
    
        $data = preg_replace('/(\D)0\.0\.0\.0(\D)/', '$1[anywhere]$2', $data);
        $data = preg_replace('/(127\.0\.0\.1|(\D):::1)/', '$2[localhost]', $data);
        $data = preg_replace('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', '***.***.***.***', $data);
        $data = preg_replace('/(\:\:([a-f0-9]{1,4}\:){0,6}?[a-f0-9]{0,4}|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){0,6}?\:\:|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){1,6}?\:\:([a-f0-9]{1,4}\:){1,6}?[a-f0-9]{1,4})(\/\d{1,3})?/', '*:*:*:*::*', $data);
        return $data;
    }
    
    function checkport($port, $name) {
        global $netstat_out, $iptables_out;
    
        $ok = preg_match('/:' . $port . '\s/', $netstat_out);
        if(!$ok) {
            outlog("[WARN] Port $port ($name) seems NOT to be listening");
        } else {
            if(DEBUG == true) {
                outlog("[OK] Port $port ($name) seems to be listening");
            }
        }
    
        $ok = preg_match('/DROP.*(dpt:' . $port . '\b|dports.*\b' . $port . '\b)/', $iptables_out);
        if($ok) {
            outlog("[WARN] Port $port ($name) seems to be BLOCKED in firewall");
        } else {
            if(DEBUG == true) {
                outlog("[OK] Port $port ($name) seems to be available");
            }
        }
    }
    
    function processname($name) {
        switch($name) {
            case 'apache2':
            case 'httpd2':
                return 'Apache 2';
            case 'lighttpd':
                return 'lighttpd';
            case 'nginx':
                return 'Nginx';
            case 'mysql':
                return 'MySQL Server';
            case 'courier':
            case 'courier-pop3':
            case 'courier-imap':
            case 'courier-pop3-ssl':
            case 'courier-imap-ssl':
            case 'couriertcpd':
                return 'Courier Mailserver';
            case 'dovecot':
            case 'pop3-login':
            case 'imap-login':
                return 'Dovecot';
            case 'master':
                return 'Postfix';
            case 'sendmail':
            case 'sendmail-':
                return 'Sendmail';
            case 'exim':
            case 'exim4':
                return 'Exim';
            case 'proftpd':
                return 'ProFTP';
            case 'pure-ftpd':
                return 'PureFTP';
            default:
                return 'Unknown process (' . $name . ')';
        }
    }
    
    function checkservice($port) {
        global $netstat_out;
    
        $services = array();
        $match = null;
        $ok = preg_match_all('/:' . $port . '\s+\((\d+)\/(\S+)\)/', $netstat_out, $match, PREG_SET_ORDER);
        if($ok) {
            foreach($match as $set) {
                $name = $set[2];
                if(!isset($services[$name])) {
                    $services[$name] = array('name' => processname($name), 'pid' => $set[1]);
                } else {
                    if(preg_match('/(^|,)' . $set[1] . '(,|$)/', $services[$name]['pid']) == false) {
                        $services[$name]['pid'] .= ', ' . $set[1];
                    }
                }
            }
        }
        return $services;
    }
    
    
    /* MAIN PROGRAM STARTS */
    
    $has_ispconfig = false;
    
    
    // check for listening ports
    $netstat_out = shell_exec('netstat -ntlp | awk \'{print $4 "\t\t(" $7 ")"}\' 2>/dev/null');
    $iptables_out = shell_exec('iptables -L -n 2>/dev/null');
    $ifconfig_out = shell_exec('ifconfig 2>/dev/null');
    
    $acme = explode("\n", shell_exec('which /usr/local/ispconfig/server/scripts/acme.sh /root/.acme.sh/acme.sh 2>/dev/null'));
    $acme = reset($acme);
    if(is_executable($acme)) {
        $acme_installed = $acme;
    } else {
        $acme_installed = false;
    }
    
    $letsencrypt = explode("\n", shell_exec('which letsencrypt certbot /root/.local/share/letsencrypt/bin/letsencrypt /opt/eff.org/certbot/venv/bin/certbot 2>/dev/null'));
    $letsencrypt = reset($letsencrypt);
    if(is_executable($letsencrypt)) {
        $certbot_installed = $letsencrypt;
    } else {
        $certbot_installed = false;
    }
    
    $letsencrypt_out = '';
    
    if($certbot_installed && $acme_installed) {
        $letsencrypt_out = '[WARN] You have both certbot and acme.sh installed. This can lead to problems.' . "\n";
        $letsencrypt_out .= 'Certbot: ' . $certbot_installed . "\n";
        $letsencrypt_out .= 'acme.sh: ' . $acme_installed;
    } elseif($certbot_installed) {
        $letsencrypt_out .= 'Certbot is installed in ' . $certbot_installed;
    } elseif($acme_installed) {
        $letsencrypt_out .= 'acme.sh is installed in ' . $acme_installed;
        if(is_dir('/etc/letsencrypt/live')) {
            $letsencrypt_out .= "\n" . '[WARN] You have /etc/letsencrypt/live in place, although only acme.sh is installed. This might indicate a problem.';
        }
    }
    
    outlog("\n##### SERVER #####");
    
    $ips = array();
    // try to find main ip of server
    $ok = preg_match_all('/encap:Ethernet.*?inet\s+\w+:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+/s', $ifconfig_out, $match, PREG_SET_ORDER);
    if($ok) {
        foreach($match as $set) {
            $ips[] = $set[1];
        }
    }
    
    $ip_address = gethostbyname(gethostname());
    if(!$ip_address) {
        outlog("[WARN] could not determine server's ip address by hostname");
    } else {
        outlog("IP-address (as per hostname): {$ip_address}");
    }
    
    if(count($ips) > 0) {
        outlog("IP-address(es) (as per ifconfig): " . implode(', ', $ips));
    } else {
        outlog("[WARN] could not determine server's ip address by ifconfig");
    }
    
    if($ip_address && count($ips) > 0 && in_array($ip_address, $ips, true) == false) {
        outlog("[WARN] ip addresses from hostname differ from ifconfig output. Please check your ip settings.");
    }
    
    // Check OS version
    $lsbrel='/usr/bin/lsb_release';
    $rhatrel = '/etc/redhat-release';
    $osrelease='/etc/os-release';
    $suserel = '/etc/SuSE-release';
    $gentoorel = '/etc/gentoo-release';
    
    if (file_exists($lsbrel)) {
        $os_version = shell_exec($lsbrel.' -d -s');
    } elseif (file_exists($rhatrel)) {
        $os_version = shell_exec('cat '.$rhatrel);
    } elseif (file_exists($suserel)) {
        $os_version = shell_exec('cat '.$suserel);
    } elseif (file_exists($gentoorel)) {
        $os_version = shell_exec('cat '.$gentoorel);
    } elseif (file_exists($osrelease)) {
        $os_version = shell_exec('cat '.$osrelease.' | grep "PRETTY_NAME" | cut --characters=13-');
    } else {
        $lslisting = shell_exec('ls -lhd /etc/*versio* /etc/*releas* /etc/*issue*');
    }
    
    if ($os_version == '') {
      outlog("ls listing to help show OS:\n".$lslisting);
    } else {
      outlog("[INFO] OS version is $os_version ");
    }
    
    // Show uptime, also shows average loads
    if (file_exists('/bin/uptime')) {
      $os_uptime = shell_exec('/bin/uptime');
    } elseif (file_exists('/usr/bin/uptime')) {
      $os_uptime = shell_exec('/usr/bin/uptime');
    }
    if ($os_uptime == '') {
      outlog("Could not detect uptime.");
    } else {
      outlog("[INFO] uptime: $os_uptime ");
    }
    
    // Show memory use and swap
    if (file_exists('/bin/free')) {
      $os_free = shell_exec('/bin/free -h');
    } elseif (file_exists('/usr/bin/free')) {
      $os_free = shell_exec('/usr/bin/free -h');
    }
    if ($os_free == '') {
      outlog("Could not detect memory usage.");
    } else {
      outlog("[INFO] memory:\n$os_free ");
    }
    
    // check all services are running
    $systemctl='/usr/bin/systemctl';
    if (file_exists($systemctl)) {
       $sctlstatus = shell_exec($systemctl.' --state=failed');
       outlog("[INFO] systemd failed services status:");
       outlog("$sctlstatus");
    }
    
    // check for ISPConfig
    if(@is_dir("/usr/local/ispconfig")) {
        $has_ispconfig = true;
    }
    
    
    if($has_ispconfig) {
        outlog("[INFO] ISPConfig is installed.");
        if(!@is_readable('/usr/local/ispconfig/server/lib/config.inc.php')) {
            outlog("[WARN] /usr/local/ispconfig/server/lib/config.inc.php is missing.");
        } else {
            include '/usr/local/ispconfig/server/lib/config.inc.php';
            outlog("\n##### ISPCONFIG #####\nISPConfig version is " . ISPC_APP_VERSION . "\n", false);
            if(!@is_readable('/usr/local/ispconfig/server/lib/mysql_clientdb.conf')) {
                outlog("[WARN] /usr/local/ispconfig/server/lib/mysql_clientdb.conf is missing.");
            } else {
                include '/usr/local/ispconfig/server/lib/mysql_clientdb.conf';
    
                // make db check
                $res = mysqli_connect($clientdb_host, $clientdb_user, $clientdb_password);
                if(!$res) {
                    outlog("[WARN] Could not connect to mysql with given user data.");
                } else {
                    $ok = mysqli_select_db($res, $conf['db_database']);
                    if(!$ok) {
                        outlog("[WARN] Could not open configured ISPConfig database ({$conf['db_database']}).");
                    }
                    mysqli_close($res);
                }
    
                $retcode = 0;
                $retout = array();
                if($clientdb_password) {
                    exec('mysql -h ' . escapeshellarg($clientdb_host) . ' -u ' . escapeshellarg($clientdb_user) . ' -D ' . escapeshellarg($conf['db_database']) . ' -p' . escapeshellarg($clientdb_password) . ' -e "SHOW TABLES"', $retout, $retcode);
                } else {
                    exec('mysql -h ' . escapeshellarg($clientdb_host) . ' -u ' . escapeshellarg($clientdb_user) . ' -D ' . escapeshellarg($conf['db_database']) . ' -e "SHOW TABLES"', $retout, $retcode);
                }
                if($retcode != 0) {
                    outlog("[WARN] Could not use mysql command line to connect to the database. Check your mysql config!");
                }
            }
    
            // try to check connection to interface
            if($ip_address) {
    
    
            }
        }
    } else {
        outlog("[INFO] No ISPConfig found.");
    }
    
    outlog("\n##### VERSION CHECK #####\n");
    $php_version = phpversion();
    outlog("[INFO] php (cli) version is $php_version");
    
    $php_cgi_version = false;
    
    $php_cgi_bin = null;
    if(is_executable('/usr/bin/php-cgi')) {
        $php_cgi_bin = '/usr/bin/php-cgi';
    } elseif(is_file('/usr/lib/cgi-bin/php5') || is_link('/usr/lib/cgi-bin/php5')) {
        $php_cgi_bin = '/usr/lib/cgi-bin/php5';
    }
    
    if($php_cgi_bin) {
        $check = shell_exec($php_cgi_bin . ' -v');
        $ok = preg_match('/^PHP\s+((\d+)\.(\d+)\.(\d+))/', $check, $match);
        if($ok) {
            $php_cgi_version = $match[1];
            outlog("[INFO] php-cgi (used for cgi php in default vhost!) is version $php_cgi_version");
            if($match[2] < 7) {
                outlog("[WARN] You are using an outdated php version.");
            } elseif(($match[2] == 7 && $match[3] < 2)) {
                outlog("[WARN] Your php-cgi in ' . $php_cgi_bin . ' seems to be outdated and might contain known exploits.");
            }
        }
    }
    
    
    outlog("\n##### PORT CHECK #####\n");
    
    // check if port 8080 is listening if ISPConfig is installed
    if($has_ispconfig) {
        checkport(8080, "ISPConfig");
        checkport(8081, "ISPConfig Apps");
    }
    
    // check for common ports
    checkport(80, "Webserver");
    checkport(443, "Webserver SSL");
    checkport(143, "IMAP server");
    checkport(993, "IMAP server SSL");
    checkport(110, "POP3 server");
    checkport(995, "POP3 server SSL");
    checkport(25, "SMTP server");
    checkport(465, "SMTP server SSL");
    checkport(21, "FTP server");
    checkport(22, "SSH server");
    checkport(25, "SMTP server");
    
    // check for entries in master.cf
    
    outlog("\n##### MAIL SERVER CHECK #####\n");
    
    
    $FILE = file_get_contents(POSTFIX_MASTER);
    
    $ok = preg_match('/^smtp\s+inet\s/m', $FILE);
    if(!$ok) {
        outlog("[WARN] I found no \"smtp\" entry in your postfix master.cf");
    }
    
    $ok = preg_match('/^submission\s+inet\s/m', $FILE);
    if(!$ok) {
        outlog("[WARN] I found no \"submission\" entry in your postfix master.cf");
        outlog("[INFO] this is not critical, but if you want to offer port 587 for smtp connections you have to enable this.");
    }
    
    $ok = preg_match('/^smtps\s+inet\s/m', $FILE);
    if(!$ok) {
        outlog("[WARN] I found no \"smtps\" entry in your postfix master.cf");
        outlog("[INFO] this is not critical, but if you want to offer SSL for smtp (not TLS) connections you have to enable this.");
    }
    
    
    outlog("\n##### RUNNING SERVER PROCESSES #####\n");
    
    $check_services = array('web server' => 80,
                            'mail server' => 25,
                            'pop3 server' => 110,
                            'imap server' => 143,
                            'ftp server' => 21);
    
    foreach($check_services as $name => $port) {
        $servers = checkservice($port);
        if(count($servers) < 1) {
            outlog("[WARN] I could not determine which " . $name . " is running.");
        } else {
            $out = "[INFO] I found the following " . $name . "(s):";
            foreach($servers as $server) {
                $out .= "\n\t";
                $out .= $server['name'] . ' (PID ' . $server['pid'] . ')';
            }
            outlog($out);
        }
    }
    
    outlog("\n##### LISTENING PORTS #####\n" . $netstat_out . "\n\n");
    outlog("\n##### IPTABLES #####\n" . $iptables_out . "\n\n");
    
    outlog("\n##### LET'S ENCRYPT #####\n" . $letsencrypt_out . "\n\n");
    
    if(OUTPUT == false) {
        print "\n##### SCRIPT FINISHED #####\n";
        print "Results can be found in htf_report.txt\n";
        print "To view results use your favourite text editor or type 'cat htf_report.txt | more' on the server console.\n";
        print "\nIf you want to see the non-anonymized output start the script with --debug as parameter (php -q htf-common-issues.php --debug).\n\n";
    }
    
    exit;
    
     
  4. IntnsRed

    IntnsRed Member

    It looks like I'll have to chop my "htf_report.txt" file into 2 parts since it exceeds the site's 20k character limit.

    PART 1 of 2:

    Code:
    #!/usr/bin/php -q
    <?php
    
    /**
     * Howtoforge common-issues-checker (c) 2013 - M. Cramer <[email protected]>
     * Version 0.5
     */
    
    
    define('DEBUG', false);
    define('ANONYMIZE', true);
    define('REPORT_FILE', './htf_report.txt');
    define('POSTFIX_MASTER', '/etc/postfix/master.cf') ;
    
    if(isset($argv[1]) && $argv[1] == '--debug') {
        define('OUTPUT', true);
    } else {
        define('OUTPUT', false);
    }
    
    $netstat_out = '';
    $iptables_out = '';
    $ifconfig_out = '';
    
    if(!function_exists('readline')) {
        function readline($prompt = '') {
            print $prompt;
            return rtrim(fgets(STDIN), "\n");
        }
    
    }
    
    // clean up report file
    $fp = fopen(REPORT_FILE, 'w');
    fclose($fp);
    
    function outlog($line, $anonymize = true) {
        if(OUTPUT == true) {
            print $line . "\n";
        }
        $fp = fopen(REPORT_FILE, 'a');
        fwrite($fp, ($anonymize ? anonip($line) : $line) . "\n");
        fclose($fp);
    }
    
    function anonip($data) {
        if(ANONYMIZE == false) {
            return $data;
        }
    
        $data = preg_replace('/(\D)0\.0\.0\.0(\D)/', '$1[anywhere]$2', $data);
        $data = preg_replace('/(127\.0\.0\.1|(\D):::1)/', '$2[localhost]', $data);
        $data = preg_replace('/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/', '***.***.***.***', $data);
        $data = preg_replace('/(\:\:([a-f0-9]{1,4}\:){0,6}?[a-f0-9]{0,4}|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){0,6}?\:\:|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){1,6}?\:\:([a-f0-9]{1,4}\:){1,6}?[a-f0-9]{1,4})(\/\d{1,3})?/', '*:*:*:*::*', $data);
        return $data;
    }
    
    function checkport($port, $name) {
        global $netstat_out, $iptables_out;
    
        $ok = preg_match('/:' . $port . '\s/', $netstat_out);
        if(!$ok) {
            outlog("[WARN] Port $port ($name) seems NOT to be listening");
        } else {
            if(DEBUG == true) {
                outlog("[OK] Port $port ($name) seems to be listening");
            }
        }
    
        $ok = preg_match('/DROP.*(dpt:' . $port . '\b|dports.*\b' . $port . '\b)/', $iptables_out);
        if($ok) {
            outlog("[WARN] Port $port ($name) seems to be BLOCKED in firewall");
        } else {
            if(DEBUG == true) {
                outlog("[OK] Port $port ($name) seems to be available");
            }
        }
    }
    
    function processname($name) {
        switch($name) {
            case 'apache2':
            case 'httpd2':
                return 'Apache 2';
            case 'lighttpd':
                return 'lighttpd';
            case 'nginx':
                return 'Nginx';
            case 'mysql':
                return 'MySQL Server';
            case 'courier':
            case 'courier-pop3':
            case 'courier-imap':
            case 'courier-pop3-ssl':
            case 'courier-imap-ssl':
            case 'couriertcpd':
                return 'Courier Mailserver';
            case 'dovecot':
            case 'pop3-login':
            case 'imap-login':
                return 'Dovecot';
            case 'master':
                return 'Postfix';
            case 'sendmail':
            case 'sendmail-':
                return 'Sendmail';
            case 'exim':
            case 'exim4':
                return 'Exim';
            case 'proftpd':
                return 'ProFTP';
            case 'pure-ftpd':
                return 'PureFTP';
            default:
                return 'Unknown process (' . $name . ')';
        }
    }
    
    function checkservice($port) {
        global $netstat_out;
    
        $services = array();
        $match = null;
        $ok = preg_match_all('/:' . $port . '\s+\((\d+)\/(\S+)\)/', $netstat_out, $match, PREG_SET_ORDER);
        if($ok) {
            foreach($match as $set) {
                $name = $set[2];
                if(!isset($services[$name])) {
                    $services[$name] = array('name' => processname($name), 'pid' => $set[1]);
                } else {
                    if(preg_match('/(^|,)' . $set[1] . '(,|$)/', $services[$name]['pid']) == false) {
                        $services[$name]['pid'] .= ', ' . $set[1];
                    }
                }
            }
        }
        return $services;
    }
    
    
    /* MAIN PROGRAM STARTS */
    
    $has_ispconfig = false;
    
    
    // check for listening ports
    $netstat_out = shell_exec('netstat -ntlp | awk \'{print $4 "\t\t(" $7 ")"}\' 2>/dev/null');
    $iptables_out = shell_exec('iptables -L -n 2>/dev/null');
    $ifconfig_out = shell_exec('ifconfig 2>/dev/null');
    
    $acme = explode("\n", shell_exec('which /usr/local/ispconfig/server/scripts/acme.sh /root/.acme.sh/acme.sh 2>/dev/null'));
    $acme = reset($acme);
    if(is_executable($acme)) {
        $acme_installed = $acme;
    } else {
        $acme_installed = false;
    }
    
    $letsencrypt = explode("\n", shell_exec('which letsencrypt certbot /root/.local/share/letsencrypt/bin/letsencrypt /opt/eff.org/certbot/venv/bin/certbot 2>/dev/null'));
    $letsencrypt = reset($letsencrypt);
    if(is_executable($letsencrypt)) {
        $certbot_installed = $letsencrypt;
    } else {
        $certbot_installed = false;
    }
    
    $letsencrypt_out = '';
    
    if($certbot_installed && $acme_installed) {
        $letsencrypt_out = '[WARN] You have both certbot and acme.sh installed. This can lead to problems.' . "\n";
        $letsencrypt_out .= 'Certbot: ' . $certbot_installed . "\n";
        $letsencrypt_out .= 'acme.sh: ' . $acme_installed;
    } elseif($certbot_installed) {
        $letsencrypt_out .= 'Certbot is installed in ' . $certbot_installed;
    } elseif($acme_installed) {
        $letsencrypt_out .= 'acme.sh is installed in ' . $acme_installed;
        if(is_dir('/etc/letsencrypt/live')) {
            $letsencrypt_out .= "\n" . '[WARN] You have /etc/letsencrypt/live in place, although only acme.sh is installed. This might indicate a problem.';
        }
    }
    
    outlog("\n##### SERVER #####");
    
    $ips = array();
    // try to find main ip of server
    $ok = preg_match_all('/encap:Ethernet.*?inet\s+\w+:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+/s', $ifconfig_out, $match, PREG_SET_ORDER);
    if($ok) {
        foreach($match as $set) {
            $ips[] = $set[1];
        }
    }
    
    $ip_address = gethostbyname(gethostname());
    if(!$ip_address) {
        outlog("[WARN] could not determine server's ip address by hostname");
    } else {
        outlog("IP-address (as per hostname): {$ip_address}");
    }
    
    if(count($ips) > 0) {
        outlog("IP-address(es) (as per ifconfig): " . implode(', ', $ips));
    } else {
        outlog("[WARN] could not determine server's ip address by ifconfig");
    }
    
    if($ip_address && count($ips) > 0 && in_array($ip_address, $ips, true) == false) {
        outlog("[WARN] ip addresses from hostname differ from ifconfig output. Please check your ip settings.");
    }
    
     
  5. IntnsRed

    IntnsRed Member

    It looks like I'll have to chop my "htf_report.txt" file into 2 parts since it exceeds the site's 20k character limit.

    PART 2 of 2:

    Code:
    // Check OS version
    $lsbrel='/usr/bin/lsb_release';
    $rhatrel = '/etc/redhat-release';
    $osrelease='/etc/os-release';
    $suserel = '/etc/SuSE-release';
    $gentoorel = '/etc/gentoo-release';
    
    if (file_exists($lsbrel)) {
        $os_version = shell_exec($lsbrel.' -d -s');
    } elseif (file_exists($rhatrel)) {
        $os_version = shell_exec('cat '.$rhatrel);
    } elseif (file_exists($suserel)) {
        $os_version = shell_exec('cat '.$suserel);
    } elseif (file_exists($gentoorel)) {
        $os_version = shell_exec('cat '.$gentoorel);
    } elseif (file_exists($osrelease)) {
        $os_version = shell_exec('cat '.$osrelease.' | grep "PRETTY_NAME" | cut --characters=13-');
    } else {
        $lslisting = shell_exec('ls -lhd /etc/*versio* /etc/*releas* /etc/*issue*');
    }
    
    if ($os_version == '') {
      outlog("ls listing to help show OS:\n".$lslisting);
    } else {
      outlog("[INFO] OS version is $os_version ");
    }
    
    // Show uptime, also shows average loads
    if (file_exists('/bin/uptime')) {
      $os_uptime = shell_exec('/bin/uptime');
    } elseif (file_exists('/usr/bin/uptime')) {
      $os_uptime = shell_exec('/usr/bin/uptime');
    }
    if ($os_uptime == '') {
      outlog("Could not detect uptime.");
    } else {
      outlog("[INFO] uptime: $os_uptime ");
    }
    
    // Show memory use and swap
    if (file_exists('/bin/free')) {
      $os_free = shell_exec('/bin/free -h');
    } elseif (file_exists('/usr/bin/free')) {
      $os_free = shell_exec('/usr/bin/free -h');
    }
    if ($os_free == '') {
      outlog("Could not detect memory usage.");
    } else {
      outlog("[INFO] memory:\n$os_free ");
    }
    
    // check all services are running
    $systemctl='/usr/bin/systemctl';
    if (file_exists($systemctl)) {
       $sctlstatus = shell_exec($systemctl.' --state=failed');
       outlog("[INFO] systemd failed services status:");
       outlog("$sctlstatus");
    }
    
    // check for ISPConfig
    if(@is_dir("/usr/local/ispconfig")) {
        $has_ispconfig = true;
    }
    
    
    if($has_ispconfig) {
        outlog("[INFO] ISPConfig is installed.");
        if(!@is_readable('/usr/local/ispconfig/server/lib/config.inc.php')) {
            outlog("[WARN] /usr/local/ispconfig/server/lib/config.inc.php is missing.");
        } else {
            include '/usr/local/ispconfig/server/lib/config.inc.php';
            outlog("\n##### ISPCONFIG #####\nISPConfig version is " . ISPC_APP_VERSION . "\n", false);
            if(!@is_readable('/usr/local/ispconfig/server/lib/mysql_clientdb.conf')) {
                outlog("[WARN] /usr/local/ispconfig/server/lib/mysql_clientdb.conf is missing.");
            } else {
                include '/usr/local/ispconfig/server/lib/mysql_clientdb.conf';
    
                // make db check
                $res = mysqli_connect($clientdb_host, $clientdb_user, $clientdb_password);
                if(!$res) {
                    outlog("[WARN] Could not connect to mysql with given user data.");
                } else {
                    $ok = mysqli_select_db($res, $conf['db_database']);
                    if(!$ok) {
                        outlog("[WARN] Could not open configured ISPConfig database ({$conf['db_database']}).");
                    }
                    mysqli_close($res);
                }
    
                $retcode = 0;
                $retout = array();
                if($clientdb_password) {
                    exec('mysql -h ' . escapeshellarg($clientdb_host) . ' -u ' . escapeshellarg($clientdb_user) . ' -D ' . escapeshellarg($conf['db_database']) . ' -p' . escapeshellarg($clientdb_password) . ' -e "SHOW TABLES"', $retout, $retcode);
                } else {
                    exec('mysql -h ' . escapeshellarg($clientdb_host) . ' -u ' . escapeshellarg($clientdb_user) . ' -D ' . escapeshellarg($conf['db_database']) . ' -e "SHOW TABLES"', $retout, $retcode);
                }
                if($retcode != 0) {
                    outlog("[WARN] Could not use mysql command line to connect to the database. Check your mysql config!");
                }
            }
    
            // try to check connection to interface
            if($ip_address) {
    
    
            }
        }
    } else {
        outlog("[INFO] No ISPConfig found.");
    }
    
    outlog("\n##### VERSION CHECK #####\n");
    $php_version = phpversion();
    outlog("[INFO] php (cli) version is $php_version");
    
    $php_cgi_version = false;
    
    $php_cgi_bin = null;
    if(is_executable('/usr/bin/php-cgi')) {
        $php_cgi_bin = '/usr/bin/php-cgi';
    } elseif(is_file('/usr/lib/cgi-bin/php5') || is_link('/usr/lib/cgi-bin/php5')) {
        $php_cgi_bin = '/usr/lib/cgi-bin/php5';
    }
    
    if($php_cgi_bin) {
        $check = shell_exec($php_cgi_bin . ' -v');
        $ok = preg_match('/^PHP\s+((\d+)\.(\d+)\.(\d+))/', $check, $match);
        if($ok) {
            $php_cgi_version = $match[1];
            outlog("[INFO] php-cgi (used for cgi php in default vhost!) is version $php_cgi_version");
            if($match[2] < 7) {
                outlog("[WARN] You are using an outdated php version.");
            } elseif(($match[2] == 7 && $match[3] < 2)) {
                outlog("[WARN] Your php-cgi in ' . $php_cgi_bin . ' seems to be outdated and might contain known exploits.");
            }
        }
    }
    
    
    outlog("\n##### PORT CHECK #####\n");
    
    // check if port 8080 is listening if ISPConfig is installed
    if($has_ispconfig) {
        checkport(8080, "ISPConfig");
        checkport(8081, "ISPConfig Apps");
    }
    
    // check for common ports
    checkport(80, "Webserver");
    checkport(443, "Webserver SSL");
    checkport(143, "IMAP server");
    checkport(993, "IMAP server SSL");
    checkport(110, "POP3 server");
    checkport(995, "POP3 server SSL");
    checkport(25, "SMTP server");
    checkport(465, "SMTP server SSL");
    checkport(21, "FTP server");
    checkport(22, "SSH server");
    checkport(25, "SMTP server");
    
    // check for entries in master.cf
    
    outlog("\n##### MAIL SERVER CHECK #####\n");
    
    
    $FILE = file_get_contents(POSTFIX_MASTER);
    
    $ok = preg_match('/^smtp\s+inet\s/m', $FILE);
    if(!$ok) {
        outlog("[WARN] I found no \"smtp\" entry in your postfix master.cf");
    }
    
    $ok = preg_match('/^submission\s+inet\s/m', $FILE);
    if(!$ok) {
        outlog("[WARN] I found no \"submission\" entry in your postfix master.cf");
        outlog("[INFO] this is not critical, but if you want to offer port 587 for smtp connections you have to enable this.");
    }
    
    $ok = preg_match('/^smtps\s+inet\s/m', $FILE);
    if(!$ok) {
        outlog("[WARN] I found no \"smtps\" entry in your postfix master.cf");
        outlog("[INFO] this is not critical, but if you want to offer SSL for smtp (not TLS) connections you have to enable this.");
    }
    
    
    outlog("\n##### RUNNING SERVER PROCESSES #####\n");
    
    $check_services = array('web server' => 80,
                            'mail server' => 25,
                            'pop3 server' => 110,
                            'imap server' => 143,
                            'ftp server' => 21);
    
    foreach($check_services as $name => $port) {
        $servers = checkservice($port);
        if(count($servers) < 1) {
            outlog("[WARN] I could not determine which " . $name . " is running.");
        } else {
            $out = "[INFO] I found the following " . $name . "(s):";
            foreach($servers as $server) {
                $out .= "\n\t";
                $out .= $server['name'] . ' (PID ' . $server['pid'] . ')';
            }
            outlog($out);
        }
    }
    
    outlog("\n##### LISTENING PORTS #####\n" . $netstat_out . "\n\n");
    outlog("\n##### IPTABLES #####\n" . $iptables_out . "\n\n");
    
    outlog("\n##### LET'S ENCRYPT #####\n" . $letsencrypt_out . "\n\n");
    
    if(OUTPUT == false) {
        print "\n##### SCRIPT FINISHED #####\n";
        print "Results can be found in htf_report.txt\n";
        print "To view results use your favourite text editor or type 'cat htf_report.txt | more' on the server console.\n";
        print "\nIf you want to see the non-anonymized output start the script with --debug as parameter (php -q htf-common-issues.php --debug).\n\n";
    }
    
    exit;
    
     
  6. Taleman

    Taleman Well-Known Member HowtoForge Supporter

    OK, so you managed to download it from the forum?
    Maybe so. However, you did not post the report. The post is again the script file.
     

Share This Page