What is this?

This knowledgebase contains questions and answers about PRTG Network Monitor and network monitoring in general.

Learn more

PRTG Network Monitor

Intuitive to Use. Easy to manage.
More than 500,000 users rely on Paessler PRTG every day. Find out how you can reduce cost, increase QoS and ease planning, as well.

Free Download

Top Tags


View all Tags

How can we Monitor SMTP SSL Certificates?

Votes:

3

Hi,

we would like to monitor our mail server certificates for tls etc. Any chance to do so? We tried all SSL sensors but they all can not connect correctly. Is there a solution for that problem?

monitoring smtp ssl-certificate

Created on Aug 24, 2016 6:14:38 AM



Best Answer

Accepted Answer

Votes:

6

Solution

Take a Linux/Debian machine and do this:

  • install a Nagios plugin check_smtp which does the real work
  • create a wrapper script for PRTG /var/prtg/scripts/check_smtp_ssl_certificate.pl
  • execute wrapper script from PRTG with the "SSH Script" sensor

Install Nagios plugin on the linux server

# su
# apt-get install monitoring-plugins-basic

Check wether the service works:

/usr/lib/nagios/plugins/check_smtp -H smtp.zirndorf.de -S -D 60

OK - Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.

Create wrapper script for PRTG on the linux server

mkdir -p /var/prtg/scripts
chmod 755 /var/prtg/scripts
touch /var/prtg/scripts/check_smtp_ssl_certificate.pl
chmod 755 /var/prtg/scripts/check_smtp_ssl_certificate.pl
vi /var/prtg/scripts/check_smtp_ssl_certificate.pl

This is the file check_smtp_ssl_certificate.pl:

#!/usr/bin/env perl
# v1, 2019-10-31, init, [email protected]

=head1 SYNOPSIS

Checking fileage for PRTG via ssh

This is /var/prtg/scripts/check_smtp_ssl_certificate.pl

Usage:

/var/prtg/scripts/check_smtp_ssl_certificate.pl --smtp_server=smtp.zirndorf.de --warning_number_of_days=30 --critical_number_of_days=10

=cut

use strict;
use warnings;
use Getopt::Long;

# PRTG-Status from
# https://kb.paessler.com/en/topic/39513-is-there-a-shell-script-example-for-the-prtg-ssh-script-sensor
my $prtg_status_ok      = 0;
my $prtg_status_warning = 1;
my $prtg_status_error   = 2;

# Defaults:
my $smtp_server             = '';
my $warning_number_of_days  = 30;
my $critical_number_of_days = 10;

GetOptions(
    "smtp_server=s",             \$smtp_server,
    "warning_number_of_days=s",  \$warning_number_of_days,
    "critical_number_of_days=s", \$critical_number_of_days,
);

# Sanity check of arguments from commandline
if (  !$smtp_server
    || $smtp_server !~ m/^[a-z0-9\-\.]+$/
    || $critical_number_of_days !~ m/^[0-9]+$/
    || $warning_number_of_days !~ m/^[0-9]+$/ )
{
    print
"$prtg_status_error:0:Usage $0 --smtp_server=smtp.zirndorf.de --warning_number_of_days=30 --critical_number_of_days=10\n";
    exit;
}

# Documentation for the nagios check:
# https://www.monitoring-plugins.org/doc/man/check_smtp.html
my $cmd = sprintf '/usr/lib/nagios/plugins/check_smtp -H %s -S -D %d,%d',
    $smtp_server, $warning_number_of_days, $critical_number_of_days;
my $result_from_nagioscheck = `$cmd`;

# Check result from nagios-check:
# OK - Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.
# WARNING - Certificate '*.zirndorf.de' expires in 532 day(s) (Thu 15 Apr 2021 04:19:00 PM CEST).
# CRITICAL - Certificate '*.zirndorf.de' expires in 532 day(s) (Thu 15 Apr 2021 04:19:00 PM CEST).

# Defaults:
my $prtg_status      = $prtg_status_error;
my $prtg_status_text = 'unknown';

# I don't care because I do not get number of days
# of certificate valid on all 3 statuses from Nagios check
my $prtg_number_to_return = 0;

if ($result_from_nagioscheck =~ m/^WARNING/) {
    $prtg_status      = $prtg_status_warning;
    $prtg_status_text = $result_from_nagioscheck;
} elsif ($result_from_nagioscheck =~ m/^CRITICAL/) {
    $prtg_status      = $prtg_status_error;
    $prtg_status_text = $result_from_nagioscheck;
} elsif ($result_from_nagioscheck =~ m/^OK/) {
    $prtg_status      = $prtg_status_ok;
    $prtg_status_text = $result_from_nagioscheck;
}

print join( ':', $prtg_status, $prtg_number_to_return, $prtg_status_text )
  . "\n";

Check the PRTG-check on Linux commandline

/var/prtg/scripts/check_smtp_ssl_certificate.pl --smtp_server=smtp.zirndorf.de --warning_number_of_days=30 --critical_number_of_days=10

0:0:OK - Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.

Create PRTG-SSH-Check

You need to create a public and private key for PRTG to reach the linux-server which runs the check

See https://www.paessler.com/manuals/prtg/ssh_script_sensor

Name of the check in PRTG: smtp-ssl-certificate-validtime

Script must be visible from a dropdown list in the user interface webpage from PRTG.

The parameters for the SSH-Scripts are like this:

--smtp_server=smtp.yourdomain.com --warning_number_of_days=30 --critical_number_of_days=10

You will see the output string of the command like this:

Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.

as "message" in your PRTG-check.

Created on Oct 31, 2019 11:17:56 AM



15 Replies

Votes:

0

Dear 4itsAdmin

Please contact [email protected]. Please state your question again, and include screenshots of one of the SSL Certificate sensors:

  • The sensor overview tab
  • The logs tab
  • The settings tab (multiple screenshots if necessary to cover all settings.)

Created on Aug 24, 2016 12:16:40 PM by  Arne Seifert [Paessler Support]



Votes:

3

Hello, any solution for this question yet?

I'm also looking for a solution to monitor SMTP certificates. The SSL Certifcate Sensor is only able to monitor HTTP/S, not STARTTLS over SMTP.

Created on Jul 12, 2018 9:23:35 AM



Votes:

1

Dear Cesare,

this is correct. We have this planned, but I cannot say when it gets to implementation. We notice the demand (and please consider your voice counted) but again, there is no ETA yet.

Created on Jul 12, 2018 1:04:35 PM by  Arne Seifert [Paessler Support]



Votes:

1

Dear Arne,

I would appreciate if you will offer such an sensor ASAP. Today is important to monitor the email-encryption of the MX Servers.

Created on Apr 1, 2019 5:20:38 PM



Votes:

0

Dear NTTITS,

we have such sensor idea, but I cannot say when, or if a STARTTSL option for SSL monitoring will be available, because other sensors are in higher demand. In order to get a good overview of user demands, the knowledge base can be used to describe a feature request.

Created on Apr 2, 2019 12:34:28 PM by  Arne Seifert [Paessler Support]

Last change on Apr 2, 2019 12:37:21 PM by  Arne Seifert [Paessler Support]



Votes:

0

Dear Arne,

is there any news? I have the same request, need to monitor SMTP-TLS-Certifiactes.

Thanks Golo

Created on Jul 16, 2019 7:27:41 AM



Votes:

0

Dear DerGolo,

for the foreseeable future, such sensor is not planned. If you like, you can create a feature request.

Created on Jul 16, 2019 12:28:09 PM by  Arne Seifert [Paessler Support]



Accepted Answer

Votes:

6

Solution

Take a Linux/Debian machine and do this:

  • install a Nagios plugin check_smtp which does the real work
  • create a wrapper script for PRTG /var/prtg/scripts/check_smtp_ssl_certificate.pl
  • execute wrapper script from PRTG with the "SSH Script" sensor

Install Nagios plugin on the linux server

# su
# apt-get install monitoring-plugins-basic

Check wether the service works:

/usr/lib/nagios/plugins/check_smtp -H smtp.zirndorf.de -S -D 60

OK - Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.

Create wrapper script for PRTG on the linux server

mkdir -p /var/prtg/scripts
chmod 755 /var/prtg/scripts
touch /var/prtg/scripts/check_smtp_ssl_certificate.pl
chmod 755 /var/prtg/scripts/check_smtp_ssl_certificate.pl
vi /var/prtg/scripts/check_smtp_ssl_certificate.pl

This is the file check_smtp_ssl_certificate.pl:

#!/usr/bin/env perl
# v1, 2019-10-31, init, [email protected]

=head1 SYNOPSIS

Checking fileage for PRTG via ssh

This is /var/prtg/scripts/check_smtp_ssl_certificate.pl

Usage:

/var/prtg/scripts/check_smtp_ssl_certificate.pl --smtp_server=smtp.zirndorf.de --warning_number_of_days=30 --critical_number_of_days=10

=cut

use strict;
use warnings;
use Getopt::Long;

# PRTG-Status from
# https://kb.paessler.com/en/topic/39513-is-there-a-shell-script-example-for-the-prtg-ssh-script-sensor
my $prtg_status_ok      = 0;
my $prtg_status_warning = 1;
my $prtg_status_error   = 2;

# Defaults:
my $smtp_server             = '';
my $warning_number_of_days  = 30;
my $critical_number_of_days = 10;

GetOptions(
    "smtp_server=s",             \$smtp_server,
    "warning_number_of_days=s",  \$warning_number_of_days,
    "critical_number_of_days=s", \$critical_number_of_days,
);

# Sanity check of arguments from commandline
if (  !$smtp_server
    || $smtp_server !~ m/^[a-z0-9\-\.]+$/
    || $critical_number_of_days !~ m/^[0-9]+$/
    || $warning_number_of_days !~ m/^[0-9]+$/ )
{
    print
"$prtg_status_error:0:Usage $0 --smtp_server=smtp.zirndorf.de --warning_number_of_days=30 --critical_number_of_days=10\n";
    exit;
}

# Documentation for the nagios check:
# https://www.monitoring-plugins.org/doc/man/check_smtp.html
my $cmd = sprintf '/usr/lib/nagios/plugins/check_smtp -H %s -S -D %d,%d',
    $smtp_server, $warning_number_of_days, $critical_number_of_days;
my $result_from_nagioscheck = `$cmd`;

# Check result from nagios-check:
# OK - Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.
# WARNING - Certificate '*.zirndorf.de' expires in 532 day(s) (Thu 15 Apr 2021 04:19:00 PM CEST).
# CRITICAL - Certificate '*.zirndorf.de' expires in 532 day(s) (Thu 15 Apr 2021 04:19:00 PM CEST).

# Defaults:
my $prtg_status      = $prtg_status_error;
my $prtg_status_text = 'unknown';

# I don't care because I do not get number of days
# of certificate valid on all 3 statuses from Nagios check
my $prtg_number_to_return = 0;

if ($result_from_nagioscheck =~ m/^WARNING/) {
    $prtg_status      = $prtg_status_warning;
    $prtg_status_text = $result_from_nagioscheck;
} elsif ($result_from_nagioscheck =~ m/^CRITICAL/) {
    $prtg_status      = $prtg_status_error;
    $prtg_status_text = $result_from_nagioscheck;
} elsif ($result_from_nagioscheck =~ m/^OK/) {
    $prtg_status      = $prtg_status_ok;
    $prtg_status_text = $result_from_nagioscheck;
}

print join( ':', $prtg_status, $prtg_number_to_return, $prtg_status_text )
  . "\n";

Check the PRTG-check on Linux commandline

/var/prtg/scripts/check_smtp_ssl_certificate.pl --smtp_server=smtp.zirndorf.de --warning_number_of_days=30 --critical_number_of_days=10

0:0:OK - Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.

Create PRTG-SSH-Check

You need to create a public and private key for PRTG to reach the linux-server which runs the check

See https://www.paessler.com/manuals/prtg/ssh_script_sensor

Name of the check in PRTG: smtp-ssl-certificate-validtime

Script must be visible from a dropdown list in the user interface webpage from PRTG.

The parameters for the SSH-Scripts are like this:

--smtp_server=smtp.yourdomain.com --warning_number_of_days=30 --critical_number_of_days=10

You will see the output string of the command like this:

Certificate '*.zirndorf.de' will expire on Thu 15 Apr 2021 04:19:00 PM CEST.

as "message" in your PRTG-check.

Created on Oct 31, 2019 11:17:56 AM



Votes:

0

Hey,

Thanks for sharing your work with us.

We appreciate that.


Kind regards,
Birk Guttmann, Tech Support Team

Created on Oct 31, 2019 2:24:45 PM by  Birk Guttmann [Paessler Support]

Last change on Oct 31, 2019 2:41:12 PM by  Birk Guttmann [Paessler Support]



Votes:

2

I needed something for this too. I don't have the option of deploying Nagios, so wrote something that works for us (we only care about the days remaining and our mail relays). Treat the below as a functional barebones/alpha release as it only started and completed yesterday. Unless it breaks for us, there won't be any changes.

Code is .C# NET CORE 5 console app, but will probably work in older versions. .NET 4.8 is possible, just untested. Download Visual Studio Community Edition 2019+/VS Code to compile it

If you use this, please feel free, but leave the credit line at the top somewhere in your code.

TY

//Author: Wayne Evans
//Date: 2021-10-07
//URL: https://kb.paessler.com/en/topic/70942-how-can-we-monitor-smtp-ssl-certificates

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace MailrelayCertificates
{
    public class certInfo
    {
        public int DaysToExpiration { get; set; }
        public string Issuer { get; set; }
        public DateTime NotAfter { get; set; }
        public DateTime NotBefore { get; set; }
        public string SerialNumber { get; set; }
        public string Subject { get; set; }
        public string Thumbprint { get; set; }
        public int PublicKeyLength { get; set; }
        public int SelfSign { get; set; }
    }

    public class root
    {
        public prtg prtg { get; set; }
    }

    public class prtg
    {
        public List<result> result { get; set; }
        public string text { get; set; }
    }

    public class result
    {
        public string channel { get; set; }
        public string value { get; set; }
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
        public string valuelookup { get; set; }
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
        public int LimitMinWarning { get; set; }
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
        public int LimitMinError { get; set; }
    }



    class Program
    {
        private static certInfo extractedCertificate;

        static void Main(string[] args)
        {
            if ((args.Count() == 0) || (args.Count() > 2))
            {
                Console.WriteLine("Mandatory Argument 1 should be the server or load balancer name, e.g. myinternalmailserver.internal.com");
                Console.WriteLine("Optional Argument 2 port number to test against.  Defaults to port 25");
            }

            string server = args[0];
            int port = 25;

            if (args.Count() == 2)
            {
                try
                {
                    port = Convert.ToInt32(args[1]);
                }
                catch
                {
                    Console.WriteLine("Second arguement needs to be a number for the port number");
                }
            }

            System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteServerCertificateValidationCallback);

            using (System.Net.Mail.SmtpClient S = new System.Net.Mail.SmtpClient(server, port))
            {
                S.EnableSsl = true;
                using (System.Net.Mail.MailMessage M = new System.Net.Mail.MailMessage("[email protected]", "[email protected]", "Certification Validataion Test", "Certification Validataion Test"))
                {
                    try
                    {
                        S.Send(M);
                    }
                    catch (Exception ex)
                    {
                        //return;
                    }


                }
            }

            root output = new root();
            output.prtg = new prtg();
            output.prtg.result = new List<result>();
            output.prtg.result.Add(new result() { channel = "Days to Expiration", value = extractedCertificate.DaysToExpiration.ToString(), LimitMinError = 4, LimitMinWarning = 14 });
            output.prtg.result.Add(new result() { channel = "Public Key Length", value = extractedCertificate.PublicKeyLength.ToString(), valuelookup = "prtg.standardlookups.sslcertificatesensor.publickey" });
            output.prtg.result.Add(new result() { channel = "Self-Signed", value = extractedCertificate.SelfSign.ToString(), valuelookup = "prtg.standardlookups.sslcertificatesensor.selfsigned" });
            output.prtg.text = "Certificate Issuer: " + extractedCertificate.Issuer + " - Certificate Thumbprint: " + extractedCertificate.Thumbprint;

            Console.WriteLine(JsonSerializer.Serialize(output));

        }

        private static bool RemoteServerCertificateValidationCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            //Console.WriteLine(certificate);
            extractedCertificate = new certInfo()
            {
                Issuer = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).Issuer,
                NotAfter = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).NotAfter,
                NotBefore = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).NotBefore,
                PublicKeyLength = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).PublicKey.Key.KeySize,
                SerialNumber = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).SerialNumber,
                SelfSign = IsSelfSigned(new X509Certificate2(certificate)),
                Subject = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).Subject,
                Thumbprint = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).Thumbprint
            };

            TimeSpan remainingUntilExpiry = ((System.Security.Cryptography.X509Certificates.X509Certificate2)certificate).NotAfter.Subtract(DateTime.UtcNow);
            extractedCertificate.DaysToExpiration = (int)remainingUntilExpiry.TotalDays;

            //I don't think we have a full cert path deployed.  Looks like an CA cert deploy, so can't test.  Leaving commented out

            //// You can alter how the chain is built/validated.
            //chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
            //chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;

            //// Do the preliminary validation.
            //var primaryCert = new X509Certificate2(certificate);
            //if (!chain.Build(primaryCert))
            //    return false;

            //// Make sure we have the same number of elements.
            //if (chain.ChainElements.Count != chain.ChainPolicy.ExtraStore.Count + 1)
            //    return false;

            //// Make sure all the thumbprints of the CAs match up.
            //// The first one should be 'primaryCert', leading up to the root CA.
            //for (var i = 1; i < chain.ChainElements.Count; i++)
            //{
            //    if (chain.ChainElements[i].Certificate.Thumbprint != chain.ChainPolicy.ExtraStore[i - 1].Thumbprint)
            //        return false;
            //}

            return true;
        }

        //https://stackoverflow.com/questions/34174435/how-can-i-check-if-a-certificate-is-self-signed
        public static int IsSelfSigned(X509Certificate2 cert)
        {
            if (cert.SubjectName.RawData.SequenceEqual(cert.IssuerName.RawData))
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

    }
}

Created on Oct 7, 2021 2:05:56 PM



Votes:

0

Hey,

Thanks for sharing your work as well. We really appreciate that.


Kind regards,
Birk Guttmann, Tech Support Team

Created on Oct 7, 2021 3:37:51 PM by  Birk Guttmann [Paessler Support]



Votes:

0

I really want this feature.. been wanting it for 6 years or so and still not implemented.

Created on Apr 24, 2022 12:50:54 PM



Votes:

0

@Wayne;

Just what I've been looking for! How do you create a PRTG sensor to pass the site's https: address to your C# code??

Created on Aug 31, 2022 3:37:09 PM



Votes:

0

Really, in the 2023 the only way to monitor a super common piece of infrastructure, like the certificate issued with STARTTLS by a SMTP relay, is to use a custom script or nagios?

Created on Aug 3, 2023 4:47:07 PM



Votes:

0

Hello Dear customer,

Thank you for your interest! Our dedicated development team is actively working on implementing various features, including the one you mentioned. While we're committed to delivering the best experience, we currently don't have a specific estimated timeframe for when this feature will be fully implemented. We appreciate your patience and will keep you updated on our progress.

Regards

Created on Aug 8, 2023 12:43:47 PM by  Ricardo Sanchez [Paessler Technical Support]




Disclaimer: The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.