为什么 HAProxy 无法加载 letsencrypt 生成的证书?

Why is HAProxy unable to load certificates generated by letsencrypt?

HAProxy 无法加载由 letsencrypt 生成的 .pem 文件,这是为什么?

我看到的错误是:

parsing [/haproxy.cfg:37] : 'bind :443' : unable to load SSL private key from PEM file '/certs/cert0.pem'.

PEM 文件的内容是:

-----BEGIN CERTIFICATE-----
MIIFCjCCA/KgAwIBAgISATGh2D5ZMcKNqpIqViwd5EZOMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTAeFw0xNTEyMTcwOTIyMDBaFw0x
NjAzMTYwOTIyMDBaMB4xHDAaBgNVBAMTE3N0YWdpbmcubXV6aGFjay5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrV1XqamfHm6tbDYAbnbjRxBw8
pxM/wPdO9RLUk5EmPnYy0XmPrbge93M5hh4qzMA7IGRxRa4xXjmj2nl4y6oLmRzF
nqHRBznh0D3u27dOmxk9vgWEGFO423T4W4DW5T6ukw+i2V5zxdtiu9tP7s8qsN7P
IxKQ8tPx8NB0PYXTg+DWhPQMZkX3Q63YEJrl6pR1kQ+shOg1WRw08/gfl8YCH0bj
AtbSPwwSNzNVylgA2IZX6mTrBYnbXJ5N63Ee/p1e+vw9fqxha4B4qPpNoByvgR27
cIGFjEoBzeS76awPzBnZLWNaVqM3E0YL9riQnAAgYPrqBIofV65GELBjwVRFAgMB
AAGjggIUMIICEDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFC5MVU7RKuD07ZwP6kGT
49qPO2tFMB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMHAGCCsGAQUF
BwEBBGQwYjAvBggrBgEFBQcwAYYjaHR0cDovL29jc3AuaW50LXgxLmxldHNlbmNy
eXB0Lm9yZy8wLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14MS5sZXRzZW5j
cnlwdC5vcmcvMB4GA1UdEQQXMBWCE3N0YWdpbmcubXV6aGFjay5jb20wgf4GA1Ud
IASB9jCB8zAIBgZngQwBAgEwgeYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUFBwIB
FhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4MgZtU
aGlzIENlcnRpZmljYXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJlbHlp
bmcgUGFydGllcyBhbmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENlcnRp
ZmljYXRlIFBvbGljeSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9y
ZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAmcF6jtx6QWAOQtRLhnuDyViJ
9ISP2mw8Ueq5p3L/oBMebCAjS1qv7bCcHP5RyeaqsGrHclpv090JY44rCppj5oOh
OFzzsNqZ5dwLp8vNbPls1Y7ohThVxk5PfMGpfkDwpuZGxUkizB7qQtknjBr6lX2B
XX2/IknJnABU2ssh2q77aqeVkHYVWXYG8iNMETUcIys1/Mb7X/FdL1DGRhkS1kN0
geL/+e7pmusHijkSoOP7IXFgTfcnw1DiIPctXmH2/ETcQ5deWVTgOpCTBk0M1+d2
oFFNaePdQXk4iRYlJNrswoZCSgdqqUybvEcJDKvL+ogi6GwZpJCIn/Rc2PWhGQ==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEqDCCA5CgAwIBAgIRAJgT9HUT5XULQ+dDHpceRL0wDQYJKoZIhvcNAQELBQAw
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjMzMzZaFw0yMDEwMTkyMjMzMzZa
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJzTDPBa5S5Ht3JdN4OzaGMw6tc1Jhkl4b2+NfFwki+3uEtB
BaupnjUIWOyxKsRohwuj43Xk5vOnYnG6eYFgH9eRmp/z0HhncchpDpWRz/7mmelg
PEjMfspNdxIknUcbWuu57B43ABycrHunBerOSuu9QeU2mLnL/W08lmjfIypCkAyG
dGfIf6WauFJhFBM/ZemCh8vb+g5W9oaJ84U/l4avsNwa72sNlRZ9xCugZbKZBDZ1
gGusSvMbkEl4L6KWTyogJSkExnTA0DHNjzE4lRa6qDO4Q/GxH8Mwf6J5MRM9LTb4
4/zyM2q5OTHFr8SNDR1kFjOq+oQpttQLwNh9w5MCAwEAAaOCAZIwggGOMBIGA1Ud
EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy
BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j
b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv
ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ
MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH
AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw
MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM
LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUqEpqYwR93brm0Tm3
pkVl7/Oo7KEwDQYJKoZIhvcNAQELBQADggEBANHIIkus7+MJiZZQsY14cCoBG1hd
v0J20/FyWo5ppnfjL78S2k4s2GLRJ7iD9ZDKErndvbNFGcsW+9kKK/TnY21hp4Dd
ITv8S9ZYQ7oaoqs7HwhEMY9sibED4aXw09xrJZTC9zK1uIfW6t5dHQjuOWv+HHoW
ZnupyxpsEUlEaFb+/SCI4KCSBdAsYxAcsHYI5xxEI4LutHp6s3OT2FuO90WfdsIk
6q78OMSdn875bNjdBYAqxUp2/LEIHfDBkLoQz0hFJmwAbYahqKaLn73PAAm1X2kj
f1w8DdnkabOLGeOVcj9LQ+s67vBykx4anTjURkbqZslUEUsn2k5xeua2zUk=
-----END CERTIFICATE-----

问题是我使用的是 letsencrypt 生成的 fullchain.pem 文件。相反,应该将它与 'privkey.pem'(也由 letsencrypt 生成)连接到一个 .pem 文件中。

我只能通过在连接时使用 cert.pem 而不是 fullchain.pem 来解决这个问题。

cat cert.pem key.pem > haproxy_cert.pem

取自https://www.haproxy.com/blog/haproxy-ssl-termination/:

frontend www.mysite.com
bind 10.0.0.3:80
bind 10.0.0.3:443 ssl crt /etc/ssl/certs/mysite.pem
default_backend web_servers

The ssl parameter enables SSL termination for this listener. The crt parameter identifies the location of the PEM-formatted SSL certificate.

This certificate should contain both the public certificate and private key.

老实说,根据我使用 TLS/SSL 端到端部署 HA Proxy 且至少有 2 个节点作为后端服务器的经验,这种说法有些正确。事实上,HA Proxy 需要 fullchain.pem(而不是 cert.pem)+ privkey.pem 作为单个文件。不使用 fullchain.pem 会导致 Systemd 上出现 unable to load cert 之类的消息。

简而言之,你应该做:

$ cat fullchain.pem privkey.pem > /etc/haproxy/mydomain_certs/mydomain.pem

而不是:

$ cat cert.pem privkey.pem > /etc/haproxy/mydomain_certs/mydomain.pem

这个 artile 有一个有价值的例子。

补充一下我遇到的问题。生成的 cat 命令连接了文件,文件之间没有换行符。我手动插入了一个新行(使用 vim)并且成功了。

另外,在我的案例中,我从注册商处获得了三个文件:crt、ca-bundle 和 p7b。我只想补充一点,我只需要私钥文件和 crt 文件(所以没有使用 ca-bundle 和 p7b)。