bash的smtp.gmail.com给出“证书错误:无法识别对等证书颁发者。”


11

如果出现问题,我需要我的脚本向管理员发送电子邮件,并且该公司仅使用Gmail。按照一些发布说明,我能够使用.mailrc文件设置mailx。首先是nss-config-dir的错误,我通过从firefox目录复制一些.db文件解决了该问题。到./certs并以mailrc为目标。已发送邮件。

但是,上面的错误出现了。出于某种奇迹,.db中有一个Google证书。它通过以下命令显示:

~]$ certutil -L -d certs

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

GeoTrust SSL CA                                              ,,
VeriSign Class 3 Secure Server CA - G3                       ,,
Microsoft Internet Authority                                 ,,
VeriSign Class 3 Extended Validation SSL CA                  ,,
Akamai Subordinate CA 3                                      ,,
MSIT Machine Auth CA 2                                       ,,
Google Internet Authority                                    ,,

很可能会忽略它,因为该邮件仍然有效。最后,在拉了一些头发和许多谷歌之后,我发现了如何摆脱烦恼。

首先,将现有证书导出到ASSCII文件:

~]$ certutil -L -n 'Google Internet Authority'  -d certs -a > google.cert.asc

现在重新导入该文件,并将其标记为受SSL证书信任,例如:

~]$ certutil -A -t "C,," -n 'Google Internet Authority'  -d certs -i google.cert.asc

此后,清单显示它受信任:

~]$ certutil -L -d certs

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI
...
Google Internet Authority                                    C,,

mailx毫不费力地发送出去。

~]$ /bin/mailx -A gmail -s "Whadda ya no" somebody@acompany.com
ho ho ho
EOT
~]$

希望对希望解决错误的人有所帮助。

另外,我对某些事情很好奇。

如果偶然不在mozilla数据库中,该如何获得该证书?例如是否有类似的东西?

    ~]$ certutil -A -t "C,," \
                 -n 'gmail.com'  \
                 -d certs \
                 -i 'http://google.com/cert/this...'

Answers:


13

好吧,这不是我想要的那种,但是这是如何从头开始获取和导入证书的方法:

# Create a certificate directory
~]$ mkdir certs

# Create a new database in the certs dir
~]$ certutil -N -d certs 

# Need now a chain certificate - May 18, 2015
~]$ wget https://www.geotrust.com/resources/root_certificates/certificates/GeoTrust_Global_CA.cer

# Need now a chain certificate part 2 - May 18, 2015
~]$ mv GeoTrust_Global_CA.cer certs/

# Fetch the certificate from Gmail, saving in the text file GMAILCERT
# Added the CA opion - May 18, 2015
~]$ echo -n | openssl s_client -connect smtp.gmail.com:465 -CAfile certs/GeoTrust_Global_CA.cer | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > GMAILCERT

# Import the new cert file into the new database in the new dir
~]$ certutil -A -n "Google Internet Authority" -t "C,," -d certs -i GMAILCERT 

# Double Check
~]$ certutil -L -d certs

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

Google Internet Authority                                    C,,  

耶!还要感谢这张票上的答案


1
我再次遇到错误,“证书错误:无法识别对等证书颁发者。” 我摄取的gmail证书已过期,看起来新的是链式证书。 openssl s_client -showcerts -connect smtp.gmail.com:465 </dev/null查看全部。
spazm

1
通过下载发行者cer文件的步骤更新了答案。
ndasusers,2015年


7

该帖子需要再次更新。我在CentOS 7机器上安装mailx时遇到麻烦。邮件会发送,但我仍然收到“认证错误:无法识别对等证书颁发者”。错误。

我在这里找到了解决方案,尽管不得不翻译。

这是一种快速的方法:

# Create a certificate directory
mkdir ~/.certs

# Create a new database in the certs dir (dont forget to enter your pass phrase!)
certutil -N -d ~/.certs 

# Create three files for the cert chain
touch ~/.certs/google ~/.certs/geotrust ~/.certs/equifax

# Copy the cert chain for smtp.google.com:465 over to my_certs file (don't forget the -showcerts option, CTRL + C to end this command)
openssl s_client -showcerts -connect smtp.gmail.com:465 > ~/.certs/my_certs

现在,复制每个证书,包括--BEGIN CERTIFICATE-和--END CERTIFICATE-,并将它们粘贴到您之前创建的相应文件中(谷歌,geotrust,equifax),然后保存这些文件。

# Open your my_certs file you made earlier and copy the google cert (usually the first one)
nano ~/.certs/my_certs

# Open your google file, paste the google cert that you just copied, and save and close
nano ~/.certs/google

# Open your my_certs file you made earlier and copy the geotrust cert (usually the second one)
nano ~/.certs/my_certs

# Open your geotrust file, paste the geotrust cert that you just copied, and save and close
nano ~/.certs/geotrust

# Open your my_certs file you made earlier and copy the equifax cert (usually the third one)
nano ~/.certs/my_certs

# Open your equifax file, paste the equifax cert that you just copied, and save and close
nano ~/.certs/equifax

现在我们必须将每个证书导入数据库。

# Import the google cert into the db
certutil -A -n "Google Internet Authority" -t "TC,," -d ~/.certs -i ~/.certs/google

# Import the geotrust cert into the db
certutil -A -n "GeoTrust Global CA" -t "TC,," -d ~/.certs -i ~/.certs/geotrust

# Import the equifax cert into the db
certutil -A -n "Equifax Secure Certificate Authority" -t "TCP,," -d ~/.certs -i ~/.certs/equifax

# Double check to make sure everything imported correctly into the db
certutil -L -d ~/.certs

输出示例:

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

Google Internet Authority                                    CT,,
GeoTrust Global CA                                           CT,,
Equifax Secure Certificate Authority                         CT,,

清理时间(可选)

# Remove all unnecessary files since the db has the certs :)
rm -rf ~/.certs/google ~/.certs/geotrust ~/.certs/equifax ~/.certs/my_certs

# Now run a test to make sure mailx is sending correctly now (don't forget to change yourname@example.com to the email address you'd like to send to)
echo "Your message" | mail -s "Message Subject" yourname@example.com

就是这样,您不应收到“认证错误:无法识别对等证书颁发者”。错误了!

笔记:

您可能已经注意到,我将目录从更改/certs~/.certs。mailx以root身份运行,因此我只是以root /身份进行了这些更改。“〜/”表示HOME目录,~/.certs表示“ /root/.certs/。”。我敢肯定,您知道这一点,但是,以防万一您永远不知道谁可能正在读这篇文章!

万一您需要它,这是我添加到底部的配置选项 /etc/mail.rc

# /etc/mail.rc options added to the bottom
set smtp-use-starttls
set smtp-auth=login
set smtp=smtp://smtp.gmail.com:587
set from="your.from.user@gmail.com(Web01 Server)"
set smtp-auth-user=your.smtp.user@gmail.com
set smtp-auth-password=your.pass
set ssl-verify=ignore
set nss-config-dir=/root/.certs

确保将your.from.user,your.smtp.user和your.pass更改为其各自的变量。


谢谢子,这就像魅力一样起作用,我不知道为什么@ndasusers无法工作。
Abhishek Madhani 2015年

当电子邮件服务器负载平衡并作为群集运行时,有人知道如何解决该问题吗?例如Office 365证书将间歇性地出现错误,因为连接末尾的服务器在连接之间变化。
布拉德(Brad)

这又过时了:-showcerts提供两个证书,而不是3个。第二个证书是GlobalSign证书。不过,此过程是唯一可行的过程,因此+1:use -showcerts,在其中找到所有证书(当前为2个),并将其分别导入数据库。
EML

...并运行opensslecho -n | openssl,它挂起等待输入
EML

@ EML +或openssl s_client </dev/null。是的,自2017年起,Google(包括gmail)已从GeoTrust / Equifax下的GIA2切换到GlobalSign下的GIA3。但是,无需存储链中的所有证书。而且,如果有任何犯罪者或冒名顶替者(例如爱管闲事的政府)冒充gmail,则此方法不仅会信任他们,而且会永久信任gmail-其他用户可能会被非法颁发的证书暂时欺骗,但是当该用户被吊销时,他们将不再信任它。您继续将所有电子邮件发送给作恶者的方法。
dave_thompson_085

0

我根据该线程中的答复创建了一个小脚本,该脚本将自动提取,解析和安装当前的gmail smtp证书。如果证书数量再次更改,它应该能够处理它。

这也是一个语法高亮的pastebin

#!/bin/bash

# This script pulls ssl certs for using gmail smtp. Adapted from the following config explaination:
# /server/498588/smtp-gmail-com-from-bash-gives-error-in-certificate-peers-certificate-issuer

certdirectory="/home/user/.certs"

# Functions

fail() {
    ec=$?
    [ "${ec}" == "0" ] && ec=1
    echo -e "FAILED[code=$ec]: $@"
    exit $ec
}

warn(){
echo -e "WARNING $@"
}

cleanup() {
  rm allgcert* || warn "Cleanup of files errored"
  rm gcert* || warn "Cleanup of files errored"
}

failclean() {
  cleanup
  fail "$@"
}

# Count number of certs currently being used (can change from time to time)
numcerts=$(echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | grep -c "i:")

# Create the certs directory if it does not exist
mkdir -p $certdirectory || fail "Unable to create certificates directory"

# Pull certs to a local file for parsing
echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > allgcert || failclean "Unable to pull certs from smtp.gmail.com"

# Parses certs output based on the number of certs, and outputs to individual files
if (($numcerts > 1)) ; then
  # Pulls the first cert out as it needs one extra line
  sed '1,27!d' allgcert > gcert1
  # For subsequent certs, it multiplies the cert number by the number of lines in the file where it should exist
  for i in $(seq 2 $numcerts) ; do
    sed "$((2 + (((($i - 1)) * 26))))"','"$((1 + (($i * 26))))"'!d' allgcert > gcert${i}
  done
fi

# Parses out certificate issuer names for installation
echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | grep i: | sed -e 's,.*=,,' > allgcertnames || failclean "Unable to output parsed names for certificates"

for i in $(seq 1 $numcerts) ; do
  certutil -A -n "$(sed -n ${i}p allgcertnames)" -t "TC,," -d $certdirectory -i gcert${i} || failclean "Unable to import certificates to database"
done

cleanup

如上所述,这是错误的操作,但如果要执行此操作,awk的一行就足够了:openssl s_client </dev/null -showcerts -connect ... | awk '/^ i:/{n=substr($0,7)} /-BEGIN/,/-END/{print>"t"} /-END/{close("t"); system("certutil -A -n \"" n "\" -t TC,, -i t -d certdir || echo failed; rm t")}'
dave_thompson_085

啊,在构建该脚本之前,我没有看到您的评论。谢谢!编辑:重新阅读您的单行代码后,我看不到我的脚本与该脚本之间的任何实际区别。我假设您基本上已经给了我脚本的一线版。有没有建议的“正确方法”来做到这一点而不会产生永久信任的问题?
pyr0ball
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.