AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-293818

Parker's questions

Martin Hope
Parker
Asked: 2019-08-20 06:05:20 +0800 CST

如何针对多个证书路径验证证书吊销列表

  • 2

在最近的一个问题中,我概述了验证通配符 SSL 证书以从远程客户端连接到 PostgreSQL 的步骤(使用与我的 Web 服务器相同的通配符证书)。虽然我解决了这个问题,但我还没有弄清楚的一件挥之不去的事情是如何确认我的证书具有正确的 CRL。

我的证书有两个证书路径(来自 SSLLabs 测试的屏幕截图):

多个受信任的证书路径

但是,CA 仅将这些路径之一(路径 #2)的 CRL 包含在其颁发的证书中。我相信我已经确定了第二条路径的正确 CRL,但我不确定如何根据我的 SSL 证书检查它以确认它是正确的。我可以直观地确认 CN 匹配,但必须有一些 OpenSSL 命令来根据相应的证书验证 CRL。我得出的结论是,我不能为此使用 CRL 指纹,因为它们会随着 CRL 的每个版本而变化。

问题:

如何通过 OpenSSL(单独或捆绑)针对其特定的可信路径验证每个单独的 CRL?

这两个 CRL 能否以与捆绑证书相同的方式捆绑(即,通过简单地附加 PEM 文件)?

本质上,我正在寻找一种确定的方法来测试“是的,这个 CRL(捆绑包?)包含这个证书的正确 CRL”。使用证书和私钥,我可以测试模数,但这对于根证书/CRL 是否足够强大?

这是我正在使用的特定根证书和 CRL(与上图相同)。


路径 #1 根

路径 #1 的根证书(USERTrust RSA 证书颁发机构):

# openssl x509 -fingerprint -noout -in USERTrustRSACertificationAuthority.crt
SHA1 Fingerprint=2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E

这是我认为上述根证书的正确 CRL:

从 CA 下载 CRL:

# wget http://crl.usertrust.com/USERTrustRSACertificationAuthority.crl

将 DER 转换为 PEM:

# openssl crl -inform DER -in USERTrustRSACertificationAuthority.crl -outform PEM -out USERTrustRSACertificationAuthority.pem

获取 CRL 的指纹:

# openssl crl -fingerprint -noout -in USERTrustRSACertificationAuthority.pem
SHA1 Fingerprint=BA:32:A2:48:F9:72:C9:01:44:17:B0:EE:6D:7F:AB:29:50:6F:A2:D4

打印 CRL 的文本版本:

# openssl crl -in USERTrustRSACertificationAuthority.pem -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha384WithRSAEncryption
        Issuer: /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
        Last Update: Aug 18 13:58:25 2019 GMT
        Next Update: Aug 22 13:58:25 2019 GMT
        CRL extensions:
            X509v3 Authority Key Identifier:
                keyid:53:79:BF:5A:AA:2B:4A:CF:54:80:E1:D8:9B:C0:9D:F2:B2:03:66:CB

            X509v3 CRL Number:
                3628
Revoked Certificates:
    Serial Number: D8C857CAE4BE66F913759FDDA3D5DB2B
        Revocation Date: Mar 16 12:21:54 2018 GMT
    Serial Number: A6DC2ED38830CC033D23ABCEB72564BF
        Revocation Date: Mar 16 12:21:54 2018 GMT
    Serial Number: 3291B976375B708A08E5322427BBC434
        Revocation Date: Mar 16 12:21:54 2018 GMT
    Signature Algorithm: sha384WithRSAEncryption
         65:73:d1:c2:b2:21:83:6b:10:9c:0d:83:e7:07:32:7a:8b:25:
         bf:1c:84:03:7b:f5:8f:c1:3b:4e:3f:b3:0c:c9:61:1d:be:4c:
         92:5e:cd:fe:56:07:0b:ff:52:38:f1:1b:0e:ad:40:a7:d8:28:
         59:76:c2:e7:24:77:29:71:e5:53:4c:2f:c3:65:ce:b3:49:9c:
         45:d3:4a:0a:a5:75:00:1f:65:85:9c:16:e2:d7:38:6f:ea:bf:
         d3:58:ef:7e:cb:10:7a:c8:9b:bb:e4:69:e6:35:b4:31:88:19:
         29:dc:2b:87:95:4f:9e:17:0a:f5:16:b7:70:1f:2a:7c:d0:ed:
         fd:00:a7:11:0c:68:e0:4f:f7:a0:d8:13:34:43:7f:09:e8:21:
         2a:9f:34:cc:ab:10:49:ba:ff:21:b9:97:57:25:c9:28:21:66:
         1e:e0:23:45:35:20:c6:8f:a8:93:b5:40:7f:e5:c3:73:ce:2a:
         d1:52:0c:9f:36:53:f7:e6:9b:03:18:94:56:9e:7b:34:20:ba:
         98:b9:fa:85:d9:95:7a:46:8e:d1:f1:b5:56:be:4c:30:be:4e:
         2d:28:37:a3:60:5b:91:b8:c5:38:30:94:3a:7f:fa:0b:bb:f0:
         af:fd:e8:67:78:55:42:11:32:71:57:0e:b3:66:17:83:52:76:
         d7:00:4a:24:87:a0:82:8e:7f:0e:21:64:a8:48:65:82:74:11:
         15:fa:99:6d:c7:5b:cf:5f:09:0b:2b:5a:a4:71:51:af:99:04:
         1e:49:14:01:fe:70:0d:a0:ec:2a:4e:c4:f5:3a:d6:bc:80:7d:
         6c:9c:53:c4:25:32:c8:8a:6f:b7:5a:61:7f:4c:a1:b2:95:c9:
         57:67:8f:45:81:d2:3d:b9:9e:86:91:61:03:2a:51:16:50:3b:
         d4:21:83:89:98:0f:93:4d:00:82:78:67:62:70:8d:c0:e9:3b:
         77:4b:b7:4d:52:1f:f7:cd:04:5e:e4:02:c2:89:7b:64:79:69:
         da:f4:57:3d:36:0d:9e:b4:fc:fc:71:cb:6d:dc:0d:1e:cc:f9:
         d9:5a:5e:36:e3:5c:56:8a:a2:70:75:c2:b4:70:8b:9f:b0:86:
         04:42:a5:35:5b:47:a4:df:e0:94:3a:5a:32:e6:9c:1f:02:10:
         d4:14:88:de:d2:46:fc:bb:b6:1c:71:90:88:6f:07:cb:5c:be:
         5c:e1:52:42:d6:af:e6:3a:7c:c0:10:6c:94:5b:2f:1c:cd:5a:
         a0:c1:de:8d:79:4c:54:9d:a6:60:21:b1:39:0d:bc:98:c9:54:
         ac:54:55:9b:05:44:c4:af:94:f4:2d:b3:cb:8f:31:d4:bf:0d:
         ea:60:66:92:7b:fa:8c:a6
-----BEGIN X509 CRL-----
MIIDcjCCAVoCAQEwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMV
VGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENl
cnRpZmljYXRpb24gQXV0aG9yaXR5Fw0xOTA4MTgxMzU4MjVaFw0xOTA4MjIxMzU4
MjVaMGswIgIRANjIV8rkvmb5E3Wf3aPV2ysXDTE4MDMxNjEyMjE1NFowIgIRAKbc
LtOIMMwDPSOrzrclZL8XDTE4MDMxNjEyMjE1NFowIQIQMpG5djdbcIoI5TIkJ7vE
NBcNMTgwMzE2MTIyMTU0WqAwMC4wHwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd
8rIDZsswCwYDVR0UBAQCAg4sMA0GCSqGSIb3DQEBDAUAA4ICAQBlc9HCsiGDaxCc
DYPnBzJ6iyW/HIQDe/WPwTtOP7MMyWEdvkySXs3+VgcL/1I48RsOrUCn2ChZdsLn
JHcpceVTTC/DZc6zSZxF00oKpXUAH2WFnBbi1zhv6r/TWO9+yxB6yJu75GnmNbQx
iBkp3CuHlU+eFwr1FrdwHyp80O39AKcRDGjgT/eg2BM0Q38J6CEqnzTMqxBJuv8h
uZdXJckoIWYe4CNFNSDGj6iTtUB/5cNzzirRUgyfNlP35psDGJRWnns0ILqYufqF
2ZV6Ro7R8bVWvkwwvk4tKDejYFuRuMU4MJQ6f/oLu/Cv/ehneFVCETJxVw6zZheD
UnbXAEokh6CCjn8OIWSoSGWCdBEV+pltx1vPXwkLK1qkcVGvmQQeSRQB/nANoOwq
TsT1Ota8gH1snFPEJTLIim+3WmF/TKGylclXZ49FgdI9uZ6GkWEDKlEWUDvUIYOJ
mA+TTQCCeGdicI3A6Tt3S7dNUh/3zQRe5ALCiXtkeWna9Fc9Ng2etPz8cctt3A0e
zPnZWl4241xWiqJwdcK0cIufsIYEQqU1W0ek3+CUOloy5pwfAhDUFIje0kb8u7Yc
cZCIbwfLXL5c4VJC1q/mOnzAEGyUWy8czVqgwd6NeUxUnaZgIbE5DbyYyVSsVFWb
BUTEr5T0LbPLjzHUvw3qYGaSe/qMpg==
-----END X509 CRL-----

路径 #2 根

路径 #2 的根证书(AddTrust External CA Root):

# openssl x509 -fingerprint -noout -in AddTrustExternalCARoot.crt
SHA1 Fingerprint=02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68

从 CA 下载 CRL:

# wget http://crl.comodoca.com/AddTrustExternalCARoot.crl

将 DER 转换为 PEM:

# openssl crl -inform DER -in AddTrustExternalCARoot.crl -outform PEM -out AddTrustExternalCARoot.pem

获取 CRL 的指纹:

# openssl crl -fingerprint -noout -in AddTrustExternalCARoot.pem
SHA1 Fingerprint=3B:03:0D:23:1C:F5:1F:53:0A:CC:AA:7A:25:BF:EE:D5:3F:80:8A:BB

打印 CRL 的文本版本:

# openssl crl -in AddTrustExternalCARoot.pem -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
        Last Update: Aug 18 13:58:25 2019 GMT
        Next Update: Aug 22 13:58:25 2019 GMT
        CRL extensions:
            X509v3 Authority Key Identifier:
                keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A

            X509v3 CRL Number:
                5362
Revoked Certificates:
    Serial Number: 537B76564F297F14DC6943E922AD2C79
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 46EAF096054CC5E3FA65EA6E9F42C664
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 3ACDAB9C759886BCAF74E5DF81A9F4E8
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 79174AA9141736FE15A7CA9F2CFF4588
        Revocation Date: Apr 30 20:03:54 2018 GMT
    Serial Number: 74C18753F7EEB4EA238D8416B5AC7646
        Revocation Date: Oct  9 09:11:57 2018 GMT
    Signature Algorithm: sha1WithRSAEncryption
         a8:f8:d9:b4:e2:75:46:19:27:0f:88:68:69:fa:06:f9:6a:51:
         bd:17:6e:8f:35:7c:2d:27:28:84:b1:59:99:c5:59:12:60:bc:
         50:f6:32:47:5b:f7:72:b9:42:40:2a:00:e5:63:e0:af:45:04:
         99:72:6c:ee:30:e7:dd:53:f6:1c:7b:9e:01:b5:06:ea:86:5f:
         8a:66:65:12:37:75:55:8a:3b:91:dd:87:43:be:c4:ce:6c:29:
         80:33:38:f4:df:e6:ed:d3:c9:ea:5c:e6:ee:57:22:7e:ca:fe:
         58:bd:e9:1d:f6:1a:02:9c:a1:86:77:ed:c1:7b:ea:a1:c8:cf:
         0f:5f:5b:ad:92:38:fc:86:45:5f:fc:99:cb:19:25:62:b0:61:
         6b:a7:8b:70:71:38:5a:39:e6:7f:de:d1:84:db:1c:cc:f3:e2:
         88:c6:4f:89:7a:5b:04:3d:cf:71:51:60:41:6d:38:9a:3f:08:
         4b:35:00:63:87:97:70:1f:15:ff:e1:72:20:7b:59:1f:de:41:
         e4:81:6f:26:12:5e:c6:6f:cb:77:00:99:97:da:c2:68:fe:d5:
         07:3f:a5:e0:fa:33:6b:c9:f3:b8:7f:02:05:b4:23:9f:4b:5d:
         5c:2f:dd:81:7c:bf:5c:3f:87:f1:dd:03:03:f3:bc:3e:68:86:
         ae:a9:64:7d
-----BEGIN X509 CRL-----
MIICnTCCAYUCAQEwDQYJKoZIhvcNAQEFBQAwbzELMAkGA1UEBhMCU0UxFDASBgNV
BAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5hbCBUVFAg
TmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9vdBcNMTkw
ODE4MTM1ODI1WhcNMTkwODIyMTM1ODI1WjCBrzAhAhBTe3ZWTyl/FNxpQ+kirSx5
Fw0xNTEyMTQxNTU4MzBaMCECEEbq8JYFTMXj+mXqbp9CxmQXDTE1MTIxNDE1NTgz
MFowIQIQOs2rnHWYhryvdOXfgan06BcNMTUxMjE0MTU1ODMwWjAhAhB5F0qpFBc2
/hWnyp8s/0WIFw0xODA0MzAyMDAzNTRaMCECEHTBh1P37rTqI42EFrWsdkYXDTE4
MTAwOTA5MTE1N1qgMDAuMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8DveAky1Qa
MAsGA1UdFAQEAgIU8jANBgkqhkiG9w0BAQUFAAOCAQEAqPjZtOJ1RhknD4hoafoG
+WpRvRdujzV8LScohLFZmcVZEmC8UPYyR1v3crlCQCoA5WPgr0UEmXJs7jDn3VP2
HHueAbUG6oZfimZlEjd1VYo7kd2HQ77EzmwpgDM49N/m7dPJ6lzm7lcifsr+WL3p
HfYaApyhhnftwXvqocjPD19brZI4/IZFX/yZyxklYrBha6eLcHE4Wjnmf97RhNsc
zPPiiMZPiXpbBD3PcVFgQW04mj8ISzUAY4eXcB8V/+FyIHtZH95B5IFvJhJexm/L
dwCZl9rCaP7VBz+l4Poza8nzuH8CBbQjn0tdXC/dgXy/XD+H8d0DA/O8PmiGrqlk
fQ==
-----END X509 CRL-----

来自 CA 的 CRL(路径 #2 根,较旧的 CRL)

这是签署通配符证书的中间 CA 提供的 CRL:

# openssl crl -fingerprint -noout -in root.crl
SHA1 Fingerprint=E1:24:F4:35:3B:D0:B7:5B:AA:D9:AD:C7:33:F2:29:32:20:08:47:14

在这里,我注意到上面的 CRL 指纹是不同的,但是X509v3 授权密钥标识符是完全匹配的(这是上面 CRL 的旧版本)。

# openssl crl -in root.crl -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
        Last Update: May 28 00:12:38 2019 GMT
        Next Update: Jun  1 00:12:38 2019 GMT
        CRL extensions:
            X509v3 Authority Key Identifier:
                keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A

            X509v3 CRL Number:
                5275
Revoked Certificates:
    Serial Number: 537B76564F297F14DC6943E922AD2C79
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 46EAF096054CC5E3FA65EA6E9F42C664
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 3ACDAB9C759886BCAF74E5DF81A9F4E8
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 79174AA9141736FE15A7CA9F2CFF4588
        Revocation Date: Apr 30 20:03:54 2018 GMT
    Serial Number: 74C18753F7EEB4EA238D8416B5AC7646
        Revocation Date: Oct  9 09:11:57 2018 GMT
    Signature Algorithm: sha1WithRSAEncryption
         38:3a:7d:3e:ee:be:48:e7:93:c3:91:0a:c3:47:46:11:87:83:
         60:85:19:2f:77:17:bd:e9:0f:02:de:04:60:33:38:5a:38:99:
         16:6b:81:51:83:f4:dc:97:83:2f:f9:97:18:5e:6a:24:5e:77:
         a0:39:dc:e1:09:24:c8:9c:05:e3:68:a2:ca:aa:1f:e7:85:fb:
         84:a0:07:96:4d:f0:53:68:6f:85:bd:d6:07:6d:57:34:9a:01:
         6e:51:b5:53:69:da:db:e1:c6:0d:c6:d9:d6:85:96:2e:b0:bf:
         71:25:49:97:66:8b:61:4a:7d:fd:ce:f3:07:d2:b5:bf:71:c0:
         01:6b:79:b2:20:5f:58:41:34:03:1b:88:a5:d7:f7:9b:ab:ff:
         49:fa:07:0b:0a:90:d8:f8:93:28:70:7a:f9:48:ed:40:b3:ae:
         31:f5:af:51:ed:00:ff:2e:0e:b9:3e:ee:6c:20:21:a0:d8:98:
         46:bd:9d:00:bb:aa:3d:30:8c:b2:72:00:af:cd:79:05:2f:40:
         5a:ae:2a:27:26:77:c3:40:79:88:4c:7b:2e:2e:df:2e:d5:4f:
         c5:b2:14:e1:aa:9a:29:4f:b5:e5:01:04:df:b7:89:59:17:1c:
         06:7b:a1:a8:9a:84:0c:cf:8c:2f:e9:3a:ec:78:f5:c9:e2:da:
         5f:16:1a:38
-----BEGIN X509 CRL-----
MIICnTCCAYUCAQEwDQYJKoZIhvcNAQEFBQAwbzELMAkGA1UEBhMCU0UxFDASBgNV
BAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5hbCBUVFAg
TmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9vdBcNMTkw
NTI4MDAxMjM4WhcNMTkwNjAxMDAxMjM4WjCBrzAhAhBTe3ZWTyl/FNxpQ+kirSx5
Fw0xNTEyMTQxNTU4MzBaMCECEEbq8JYFTMXj+mXqbp9CxmQXDTE1MTIxNDE1NTgz
MFowIQIQOs2rnHWYhryvdOXfgan06BcNMTUxMjE0MTU1ODMwWjAhAhB5F0qpFBc2
/hWnyp8s/0WIFw0xODA0MzAyMDAzNTRaMCECEHTBh1P37rTqI42EFrWsdkYXDTE4
MTAwOTA5MTE1N1qgMDAuMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8DveAky1Qa
MAsGA1UdFAQEAgIUmzANBgkqhkiG9w0BAQUFAAOCAQEAODp9Pu6+SOeTw5EKw0dG
EYeDYIUZL3cXvekPAt4EYDM4WjiZFmuBUYP03JeDL/mXGF5qJF53oDnc4QkkyJwF
42iiyqof54X7hKAHlk3wU2hvhb3WB21XNJoBblG1U2na2+HGDcbZ1oWWLrC/cSVJ
l2aLYUp9/c7zB9K1v3HAAWt5siBfWEE0AxuIpdf3m6v/SfoHCwqQ2PiTKHB6+Ujt
QLOuMfWvUe0A/y4OuT7ubCAhoNiYRr2dALuqPTCMsnIAr815BS9AWq4qJyZ3w0B5
iEx7Li7fLtVPxbIU4aqaKU+15QEE37eJWRccBnuhqJqEDM+ML+k67Hj1yeLaXxYa
OA==
-----END X509 CRL-----
ssl
  • 1 个回答
  • 4958 Views
Martin Hope
Parker
Asked: 2019-08-15 08:55:51 +0800 CST

尝试使用 SSL 通配符服务器证书和无客户端证书连接到 PostgreSQL 9.6 时出错

  • 3

我在 Amazon Linux 上有一个 PostgreSQL 9.6.11 数据库,自 2012 年 1 月以来,该数据库已配置了 2048 位 SSL 通配符服务器证书和基于密码(无客户端证书)的远程连接。在最近的证书升级后(Comodo,现在是 Sectigo) ,我无法再通过 SSL 与该数据库建立远程 psql 或 JDBC 连接。

我的目标是能够通过 psql 和 JDBC 远程连接到这个 PostgreSQL 数据库。

从服务器密钥(自从我有远程访问工作以来它没有改变)开始,我试图涵盖整个系列的步骤,以验证我的密钥、证书、防火墙和数据库设置是否正确。

我一定错过了什么,因为我无法通过 psql 或 JDBC 远程连接。

我错过了什么可能导致这些远程连接失败?

故障排除步骤


作为用户postgres:

# cd /var/lib/pgsql96/data

postgresql.conf

我曾尝试限制密码集以尝试强制所有 SSL 连接使用 TLSv1.2。由于客户端行为没有区别,我注释掉了 ssl_ciphers 和 ssl_prefer_server_ciphers 以允许使用默认值。

ssl = on
#ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1'
#ssl_prefer_server_ciphers = on
ssl_cert_file = 'server.crt' # wildcard cert plus intermediate certs
ssl_key_file = 'server.key' # private key
#ssl_ca_file = 'root.crt' # commented out - do not require client certs
#ssl_crl_file = 'root.crl' # commented out - no client certificates

pg_hba.conf

该文件设置为仅允许本地主机的公共 IP 地址和我正在测试的远程主机。我不想要求客户端证书,只需要使用所需密码进行加密。

hostssl       all     all     11.222.11.222/32      password # localhost
hostssl       all     all     34.84.31.82/32        password # remote host

我通过ssltest检查了认证路径,发现有两个可用路径(路径 #1和路径 #2):

SSLTest 证书路径

从PostgreSQL 9.6 Secure TCP/IP Connections with SSL的文档中:

server.crt 中的第一个证书必须是服务器的证书,因为它必须与服务器的私钥匹配。“中间”证书颁发机构的证书也可以附加到文件中。这样做可以避免在客户端上存储中间证书的必要性,假设根证书和中间证书是使用 v3_ca 扩展创建的。这使得中间证书更容易过期。

无需将根证书添加到 server.crt。相反,客户端必须拥有服务器证书链的根证书。


组装和验证路径 #1 的证书链

# ls -l
-rw------- 1 postgres postgres 2313 Aug 15 00:26 1_wildcard_server.crt
-rw------- 1 postgres postgres 2167 Aug 15 00:27 2_intermediate_sectigo.crt
-rw------- 1 postgres postgres 2094 Aug 15 00:27 3_root_usertrust-selfsigned.crt

我检查了路径 #1 中每个证书的指纹以确认其身份:

# openssl x509 -in 1_wildcard_server.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=8C:69:06:8E:81:31:30:6E:DA:DD:C2:1C:38:83:73:67:97:3D:DB:37:78:B8:49:D7:7E:32:A8:3F:1F:8B:08:AB

# openssl x509 -in 2_intermediate_sectigo.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=7F:A4:FF:68:EC:04:A9:9D:75:28:D5:08:5F:94:90:7F:4D:1D:D1:C5:38:1B:AC:DC:83:2E:D5:C9:60:21:46:76

# openssl x509 -in 3_root_usertrust-selfsigned.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=E7:93:C9:B0:2F:D8:AA:13:E2:1C:31:22:8A:CC:B0:81:19:64:3B:74:9C:89:89:64:B1:74:6D:46:C3:D4:CB:D2

并且还检查了证书的文本版本,以确认中间证书和根证书具有 v3_ca 扩展名(通配符服务器证书没有此扩展名):

# openssl x509 -in 1_wildcard_server.crt -text
...
X509v3 Basic Constraints: critical
    CA:FALSE
...

# openssl x509 -in 2_intermediate_sectigo.crt -text
...
X509v3 Basic Constraints: critical
    CA:TRUE
...

# openssl x509 -in 3_root_usertrust-selfsigned.crt -text
...
X509v3 Basic Constraints: critical
    CA:TRUE
...

使用 OpenSSL 验证路径 #1 的证书链:

# openssl verify -verbose -CAfile 3_root_usertrust-selfsigned.crt -untrusted 2_intermediate_sectigo.crt 1_wildcard_server.crt
1_wildcard_server.crt: OK

为路径 #1 创建捆绑的服务器和中间证书:

# cat 1_wildcard_server.crt > server.crt
# cat 2_intermediate_sectigo.crt >> server.crt

为路径 #1 创建捆绑的中间证书和根证书(具有 v3_ca 扩展名的证书)(尽管仅在需要客户端证书时才需要):

# cat 2_intermediate_sectigo.crt > root.crt
# cat 3_root_usertrust-selfsigned.crt >> root.crt

组装和验证路径 #2 的证书链

# ls -l
-rw------- 1 postgres postgres 2313 Aug 15 00:26 1_wildcard_server.crt
-rw------- 1 postgres postgres 2167 Aug 15 00:27 2_intermediate_sectigo.crt
-rw------- 1 postgres postgres 1956 Aug 15 00:35 3_intermediate_usertrust.crt
-rw------- 1 postgres postgres 1521 Aug 15 00:27 4_root_addtrustroot-selfsigned.crt

我检查了路径 #2 中每个证书的指纹以确认它们的身份:

# openssl x509 -in 1_wildcard_server.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=8C:69:06:8E:81:31:30:6E:DA:DD:C2:1C:38:83:73:67:97:3D:DB:37:78:B8:49:D7:7E:32:A8:3F:1F:8B:08:AB

# openssl x509 -in 2_intermediate_sectigo.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=7F:A4:FF:68:EC:04:A9:9D:75:28:D5:08:5F:94:90:7F:4D:1D:D1:C5:38:1B:AC:DC:83:2E:D5:C9:60:21:46:76

# openssl x509 -in 3_intermediate_usertrust.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=1A:51:74:98:0A:29:4A:52:8A:11:07:26:D5:85:56:50:26:6C:48:D9:88:3B:EA:69:2B:67:B6:D7:26:DA:98:C5

# openssl x509 -in 4_root_addtrustroot-selfsigned.crt -noout -sha256 -fingerprint
SHA256 Fingerprint=68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2

并且还检查了证书的文本版本,以确认中间证书和根证书具有 v3_ca 扩展名(通配符服务器证书没有此扩展名):

# openssl x509 -in 1_wildcard_server.crt -text
...
X509v3 Basic Constraints: critical
    CA:FALSE
...

# openssl x509 -in 2_intermediate_sectigo.crt -text
...
X509v3 Basic Constraints: critical
    CA:TRUE
...

# openssl x509 -in 3_intermediate_usertrust.crt -text
...
X509v3 Basic Constraints: critical
    CA:TRUE
...

# openssl x509 -in 4_root_addtrustroot-selfsigned.crt -text
...
X509v3 Basic Constraints: critical
    CA:TRUE
...

使用 OpenSSL 验证路径 #2 的证书链(来自本文):

# openssl verify -verbose -CAfile 4_root_addtrustroot-selfsigned.crt -untrusted 3_intermediate_usertrust.crt 2_intermediate_sectigo.crt
2_intermediate_sectigo.crt: OK

为路径 #2 创建捆绑的服务器和中间证书:

# cat 1_wildcard_server.crt > server.crt
# cat 2_intermediate_sectigo.crt >> server.crt
# cat 3_intermediate_usertrust.crt >> server.crt

为路径 #2 创建捆绑的中间证书和根证书(具有 v3_ca 扩展名的证书)(尽管仅在需要客户端证书时才需要):

# cat 2_intermediate_sectigo.crt > root.crt
# cat 3_intermediate_usertrust.crt >> root.crt
# cat 4_root_addtrustroot-selfsigned.crt >> root.crt

已验证的密钥和证书权限(如在此问题中)。

# ls -l *.key *.crt *.crl-bash-4.2$ ls -l *.key *.crt *.crl
-rw-r----- 1 postgres postgres  963 Aug 14 21:12 root.crl
-rw-r--r-- 1 postgres postgres 1521 Aug 15 01:27 root.crt
-rw-r--r-- 1 postgres postgres 6436 Aug 15 01:27 server.crt
-rw------- 1 postgres postgres 1679 May 28 19:33 server.key

按照 Comodo的说明确认服务器密钥正常。

# openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017
# openssl rsa -check -noout -in server.key
RSA key ok

确认证书和私钥模数相同。

# openssl rsa -modulus -noout -in server.key
Modulus=[REDACTED]

# openssl x509 -modulus -noout -in server.crt
Modulus=[REDACTED]

测试了 CRL 并验证了颁发者:

# openssl crl -in root.crl -text
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
        Last Update: May 28 00:12:38 2019 GMT
        Next Update: Jun  1 00:12:38 2019 GMT
        CRL extensions:
            X509v3 Authority Key Identifier:
                keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A
            X509v3 CRL Number:
                5275
Revoked Certificates:
    Serial Number: 537B76564F297F14DC6943E922AD2C79
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 46EAF096054CC5E3FA65EA6E9F42C664
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 3ACDAB9C759886BCAF74E5DF81A9F4E8
        Revocation Date: Dec 14 15:58:30 2015 GMT
    Serial Number: 79174AA9141736FE15A7CA9F2CFF4588
        Revocation Date: Apr 30 20:03:54 2018 GMT
    Serial Number: 74C18753F7EEB4EA238D8416B5AC7646
        Revocation Date: Oct  9 09:11:57 2018 GMT
    Signature Algorithm: sha1WithRSAEncryption
         38:3a:7d:3e:ee:be:48:e7:93:c3:91:0a:c3:47:46:11:87:83:
[TRIMMED]
         5f:16:1a:38
-----BEGIN X509 CRL-----
MIICnTCCAYUCAQEwDQYJKoZIhvcNAQEFBQAwbzELMAkGA1UEBhMCU0UxFDASBgNV
[TRIMMED]
iEx7Li7fLtVPxbIU4aqaKU+15QEE37eJWRccBnuhqJqEDM+ML+k67Hj1yeLaXxYa
OA==
-----END X509 CRL-----

启动 PostgreSQL 服务。

# service postgresql96 start
Starting postgresql96 service:                             [  OK  ]

验证日志文件中没有错误。

# cat ../pgstartup.log
LOG:  redirecting log output to logging collector process
HINT:  Future log output will appear in directory "pg_log".

# cat pg_log/postgresql-Wed.log
LOG:  database system was shut down at 2019-08-14 15:01:03 UTC
LOG:  MultiXact member wraparound protections are now enabled
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started

使用sslmode require和verify-full(使用 FQDN)从localhost通过 SSL 成功连接到数据库。

# psql "postgresql://mydbuser@localhost:5432/mydb?ssl=true&sslmode=require"
psql (9.6.11)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
mydb=> \q

# psql "postgresql://mydbuser@[REDACTED].org:5432/mydb?ssl=true&sslmode=verify-full"
Password: ********
psql (9.6.11)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
mydb=> \q

结合本法、本法、本法、本法,通过Java远程检索并直观验证SSL证书链。这确认端口 5432 在防火墙上为此主机打开,并且证书和链可通过 JDBC 检索。

Supported Protocols: 5
 SSLv2Hello
 SSLv3
 TLSv1
 TLSv1.1
 TLSv1.2
Enabled Protocols: 3
 TLSv1
 TLSv1.1
 TLSv1.2
Enabled Cipher suites: 43
 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
 TLS_RSA_WITH_AES_256_CBC_SHA256
 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
 TLS_RSA_WITH_AES_256_CBC_SHA
 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
 TLS_RSA_WITH_AES_128_CBC_SHA256
 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
 TLS_RSA_WITH_AES_128_CBC_SHA
 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
 TLS_RSA_WITH_AES_256_GCM_SHA384
 TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
 TLS_RSA_WITH_AES_128_GCM_SHA256
 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
 TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Cert 1 (active):
    Thumbprint SHA1   : B5:2D:43:A8:0F:C6:C3:39:1F:2D:BB:9C:30:A5:4B:8D:DF:5F:9B:F8
    Fingerprint SHA256: 8c69068e8131306edaddc21c38837367973ddb3778b849d77e32a83f1f8b08ab
    Subject: CN=*.[REDACTED].org,OU=PositiveSSL Wildcard,OU=Domain Control Validated
    Issuer: CN=Sectigo RSA Domain Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
Cert 2 (active):
    Thumbprint SHA1   : 33:E4:E8:08:07:20:4C:2B:61:82:A3:A1:4B:59:1A:CD:25:B5:F0:DB
    Fingerprint SHA256: 7fa4ff68ec04a99d7528d5085f94907f4d1dd1c5381bacdc832ed5c960214676
    Subject: CN=Sectigo RSA Domain Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
    Issuer: CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US
Cert 3 (active):
    Thumbprint SHA1   : 33:E4:E8:08:07:20:4C:2B:61:82:A3:A1:4B:59:1A:CD:25:B5:F0:DB
    Fingerprint SHA256: 7fa4ff68ec04a99d7528d5085f94907f4d1dd1c5381bacdc832ed5c960214676
    Subject: CN=Sectigo RSA Domain Validation Secure Server CA,O=Sectigo Limited,L=Salford,ST=Greater Manchester,C=GB
    Issuer: CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US
Cert 4 (active):
    Thumbprint SHA1   : EA:B0:40:68:9A:0D:80:5B:5D:6F:D6:54:FC:16:8C:FF:00:B7:8B:E3
    Fingerprint SHA256: 1a5174980a294a528a110726d5855650266c48d9883bea692b67b6d726da98c5
    Subject: CN=USERTrust RSA Certification Authority,O=The USERTRUST Network,L=Jersey City,ST=New Jersey,C=US
    Issuer: CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE

我确认上述根证书(AddTrust External CA Root)都在此处推荐的默认 Java 密钥库中(并且还确认默认情况下它们也在 Windows 密钥库中):

C:\Windows\System32>"C:\Program Files\Java\jdk1.8.0_212\jre\bin\keytool.exe" -keystore "C:\Program Files\Java\jdk1.8.0_212\jre\lib\security\cacerts" -storepass
changeit -list
Keystore type: jks
Keystore provider: SUN

Your keystore contains 95 entries
....
usertrustrsaca [jdk], Aug 25, 2016, trustedCertEntry,
Certificate fingerprint (SHA1): 2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E
....
addtrustexternalca [jdk], Aug 25, 2016, trustedCertEntry,
Certificate fingerprint (SHA1): 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68
....

尝试从远程主机通过 openssl 连接到 PostgreSQL(如在这个问题中)。

# openssl version
OpenSSL 1.1.0h  27 Mar 2018
# openssl s_client -connect [REDACTED].org:5432 -state -msg -showcerts -debug
CONNECTED(00000003)
SSL_connect:before/connect initialization
write to 0x2070760 [0x20fe520] (289 bytes => 289 (0x121))
0000 - 16 03 01 01 1c 01 00 01-18 03 03 0c 53 44 0c a3   ............SD..
[TRIMMED]
0110 - 03 01 03 02 03 03 02 01-02 02 02 03 00 0f 00 01   ................
0120 - 01                                                .
>>> TLS 1.2  [length 0005]
    16 03 01 01 1c
>>> TLS 1.2 Handshake [length 011c], ClientHello
    01 00 01 18 03 03 0c 53 44 0c a3 e2 21 36 f2 b0
[TRIMMED]
    01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03
    03 02 01 02 02 02 03 00 0f 00 01 01
SSL_connect:SSLv2/v3 write client hello A
read from 0x2070760 [0x2103a80] (7 bytes => 0 (0x0))
139650021263184:error:140790E5:SSL routines:ssl23_write:ssl handshake failure:s23_lib.c:177:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 289 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1565797370
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

# tail pg_log/postgresql-Wed.log
LOG:  invalid length of startup packet

尝试通过 Windows psql 客户端 (9.6.5) 远程连接。

C:\Program Files\PostgreSQL\9.6\bin>psql "postgresql://mydbuser@[REDACTED].org:5432/mydb?ssl=true&sslmode=require"
psql: SSL error: certificate verify failed

出于某种原因,psql 客户端正在发送一个 TLSv1 警报,“未知 ca”:

# tail pg_log/postgresql-Wed.log
LOG:  could not accept SSL connection: tlsv1 [alert][15] unknown ca

此外,如果我指定根证书:

C:\Program Files\PostgreSQL\9.6\bin>psql "postgresql://mydbuser@[REDACTED].org:5432/mydb?ssl=true&sslmode=require&sslrootcert=root.crt"
psql: SSL error: certificate verify failed

或者如果我将该参数留空:

C:\Program Files\PostgreSQL\9.6\bin>psql "postgresql://mydbuser@[REDACTED].org:5432/mydb?ssl=true&sslmode=require&sslrootcert="
psql: SSL error: certificate verify failed

但是,如果我为该参数指定一个不存在的文件,我能够成功连接(使用 sslmode=require):

C:\Program Files\PostgreSQL\9.6\bin>psql "postgresql://mydbuser@[REDACTED].org:5432/mydb?ssl=true&sslmode=require&sslrootcert=x"
Password:
psql (9.6.5, server 9.6.11)
WARNING: Console code page (437) differs from Windows code page (1252)
         8-bit characters might not work correctly. See psql reference
         page "Notes for Windows users" for details.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
n4l_live=> \q

从规范:

未知的_ca

  A valid certificate chain or partial chain was received, but the
  certificate was not accepted because the CA certificate could not
  be located or couldn't be matched with a known, trusted CA.  This
  message is always fatal.

尝试通过 Java 客户端与postgresql-42.2.5.jar 连接。

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
  at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
  at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
  at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
  at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
  at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
  at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
  at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
  at org.postgresql.ssl.MakeSSL.convert(MakeSSL.java:40)
  ... 36 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
  at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
  at sun.security.validator.Validator.validate(Validator.java:262)
  at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330)
  at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:237)
  at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
  at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)
  ... 44 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
  at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
  at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
  at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
  ... 50 more

出于某种原因,Java 客户端正在生成 SSLv3警报,“证书未知”,即使它不是启用的协议之一:

# tail pg_log/postgresql-Wed.log
LOG:  could not accept SSL connection: sslv3 alert certificate unknown

从规范:

证书_未知

  Some other (unspecified) issue arose in processing the
  certificate, rendering it unacceptable.

PostgreSQL JDBC 驱动程序文档表明Java 客户端(默认情况下)将尝试使用verify-full服务器证书,这可能是此处产生的错误与使用 psql 客户端不同的原因:

最简单的是 ssl=true,将其传递给驱动程序将导致驱动程序验证 SSL 证书并验证主机名(与 相同verify-full)。请注意,这与默认为非验证 SSL 连接的 libpq 不同。

上述失败(以及使用 指定不存在的根证书时的成功sslmode=require)似乎表明验证证书的 CA 存在一些问题。

注意:我使用此答案中提供的脚本生成新证书并再次执行上述测试,结果相同。

ssl
  • 2 个回答
  • 11876 Views
Martin Hope
Parker
Asked: 2019-06-25 08:40:45 +0800 CST

上传大文件时偶尔出现 mod_jk 客户端错误

  • 0

注意:此问题末尾有一个 TL;DR。

我有一个夜间备份脚本,它已经可靠地工作了 6 年,两个月前,它开始无法上传到我的存档服务器(只有大约四分之一的尝试成功)。一旦备份文件的大小超过大约 440MB(成功上传需要 20-40 秒才能完成),这种情况就开始发生。其他较小的文件 (>200MB) 每次都成功上传。故障的开始与有问题的服务器的任何配置更改或更新不一致。

以下是我正在上传的文件的详细信息:

-rw-r--r-- 1 backup backup 486948951 Jun 12 13:20 snapshot-20190612.zip

这些文件通过 curl 上传到我的服务器PUT(请参见下面的命令)。源服务器是弗吉尼亚州的 Amazon Linux 实例,目标服务器是俄亥俄州的 Amazon Linux 实例(均位于美国东部地区)。

处理上传的 Web 服务是Apache HTTPD 2.4.39 + mod24_ssl/OpenSSL 1.0.2k -> mod_jk 1.2.42 -> Apache Tomcat 8.5.40 -> Artifactory 5.3.2实例。


我在其中一个错误发生之前和之后捕获了jk_status页面(之前/之后在动画 GIF 中以突出显示差异)。该错误被mod_jk解释为客户端错误。

错误前后的 jk_status


我的 mod/jk workers.properties文件:

worker.list=main_ajp13_worker
# Set properties for main_ajp13_worker (ajp13)
worker.main_ajp13_worker.type=ajp13
worker.main_ajp13_worker.host=localhost
worker.main_ajp13_worker.port=8009

以下是上传失败后的控制台输出(已清除授权详细信息),然后是成功上传:

-bash-4.2$ curl -v -k -u backup:PASSWORD -H X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3 -H X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10 -T snapshot-20190612.zip https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
*   Trying 123.222.100.132...
* TCP_NODELAY set
* Connected to repo.mydomain.org (123.222.100.132) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.mydomain.org
*  start date: May 28 00:00:00 2019 GMT
*  expire date: May 27 23:59:59 2021 GMT
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
* Server auth using Basic with user 'backup'
> PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1
> Host: repo.mydomain.org
> Authorization: Basic DELETED_TOKEN
> User-Agent: curl/7.61.1
> Accept: */*
> X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3
> X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10
> Content-Length: 486948951
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104
* Closing connection 0
curl: (56) OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104

-bash-4.2$ curl -v -u backup:PASSWORD -H X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3 -H X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10 -T snapshot-20190612.zip https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
*   Trying 123.222.100.132...
* TCP_NODELAY set
* Connected to repo.mydomain.org (123.222.100.132) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.mydomain.org
*  start date: May 28 00:00:00 2019 GMT
*  expire date: May 27 23:59:59 2021 GMT
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
* Server auth using Basic with user 'backup'
> PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1
> Host: repo.mydomain.org
> Authorization: Basic DELETED_TOKEN
> User-Agent: curl/7.61.1
> Accept: */*
> X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3
> X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10
> Content-Length: 486948951
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104
* Closing connection 0
curl: (56) OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104

通过第二次(或者通常是第三次或第四次)尝试上传,它最终会成功:

-bash-4.2$ curl -v -u backup:PASSWORD -H X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3 -H X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10 -T snapshot-20190612.zip https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
*   Trying 123.222.100.132...
* TCP_NODELAY set
* Connected to repo.mydomain.org (123.222.100.132) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.mydomain.org
*  start date: May 28 00:00:00 2019 GMT
*  expire date: May 27 23:59:59 2021 GMT
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
* Server auth using Basic with user 'backup'
> PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1
> Host: repo.mydomain.org
> Authorization: Basic DELETED_TOKEN
> User-Agent: curl/7.61.1
> Accept: */*
> X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3
> X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10
> Content-Length: 486948951
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 201 201
< Date: Wed, 12 Jun 2019 13:22:46 GMT
< Server: Apache
< Strict-Transport-Security: max-age=15768000
< X-Artifactory-Id: 9e49bf90cd4b7700:7ba45cf1:16b1db56e4d:-8000
< Location: https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
< Transfer-Encoding: chunked
< Content-Type: application/vnd.org.jfrog.artifactory.storage.itemcreated+json;charset=ISO-8859-1
<
{
  "repo" : "resource-snapshot",
  "path" : "/snapshot/20190612/snapshot-20190612.zip",
  "created" : "2019-06-12T13:23:05.805Z",
  "createdBy" : "backup",
  "downloadUri" : "https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip",
  "mimeType" : "application/zip",
  "size" : "486948951",
  "checksums" : {
    "sha1" : "6b9525bf9bb572ec7f70d0d474cb6533e0091bd3",
    "md5" : "6da0c444ad1b53dc1cf06784e204cb10"
  },
  "originalChecksums" : {
    "sha1" : "6b9525bf9bb572ec7f70d0d474cb6533e0091bd3",
    "md5" : "6da0c444ad1b53dc1cf06784e204cb10"
  },
  "uri" : "https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip"
* Connection #0 to host repo.mydomain.org left intact
}

服务器日志不是特别有用。以下是上传失败时的相关日志:

/var/log/httpd/ssl_request_log

[24/Jun/2019:12:17:45 +0000] 52.1.100.190 TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 "PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1" -

/var/log/httpd/repo.mydomain.org-ssl_access_log

140.1.100.101 - - [24/Jun/2019:12:17:45 +0000] "PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1" 400 -

catalina.out

没有日志条目。

/var/log/httpd/mod_jk.log

这些是 mod/jk 日志级别设置为info时的日志:

[Mon Jun 24 12:18:05 2019] [15679:140534117611584] [info] ajp_read_into_msg_buff::jk_ajp_common.c (1553): (main_ajp13_worker) receiving data from client failed. Connection aborted or network problems
[Mon Jun 24 12:18:05 2019] [15679:140534117611584] [info] ajp_process_callback::jk_ajp_common.c (2105): (main_ajp13_worker) Reading from client aborted or client network problems
[Mon Jun 24 12:18:05 2019] [15679:140534117611584] [info] ajp_service::jk_ajp_common.c (2778): (main_ajp13_worker) sending request to tomcat failed (unrecoverable), because of client read error (attempt=1)
[Mon Jun 24 12:18:05 2019] [15679:140534117611584] [info] jk_handler::mod_jk.c (2988): Aborting connection for worker=main_ajp13_worker

这是调试级别的 240 万个 mod_jk 日志条目的相关部分,从 HTTP 100 Continue 开始并显示文件上传的最开始(您可以看到 zip 文件的幻数,50 4B 03 04 ):

[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0160    32 65 32 00 A0 08 00 09 34 39 36 32 37 38 36 30  - 2e2.....49627860
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0170    33 00 00 06 45 78 70 65 63 74 00 00 0C 31 30 30  - 3...Expect...100
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0180    2D 63 6F 6E 74 69 6E 75 65 00 0A 00 0F 41 4A 50  - -continue....AJP
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0190    5F 52 45 4D 4F 54 45 5F 50 4F 52 54 00 00 05 33  - _REMOTE_PORT...3
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 01a0    32 39 37 30 00 0A 00 0E 41 4A 50 5F 4C 4F 43 41  - 2970....AJP_LOCA
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 01b0    4C 5F 41 44 44 52 00 00 0C 31 37 32 2E 33 31 2E  - L_ADDR...172.31.
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 01c0    31 33 2E 39 36 00 0A 00 10 4A 4B 5F 4C 42 5F 41  - 13.96....JK_LB_A
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 01d0    43 54 49 56 41 54 49 4F 4E 00 00 03 41 43 54 00  - CTIVATION...ACT.
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 01e0    0A 00 0F 53 53 4C 5F 43 4C 49 45 4E 54 5F 43 45  - ...SSL_CLIENT_CE
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 01f0    52 54 00 00 0F 53 53 4C 5F 43 4C 49 45 4E 54 5F  - RT...SSL_CLIENT_
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0200    43 45 52 54 00 FF 00 00 00 00 00 00 00 00 00 00  - CERT............
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_send_request::jk_ajp_common.c (1782): (main_ajp13_worker) request body to send 496278603 - request body to resend 0
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_send_request::jk_ajp_common.c (1886): (main_ajp13_worker) sending 8186 bytes of request body
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): sending to ajp13 pos=4 len=8192 max=8192
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0000    12 34 1F FC 1F FA 50 4B 03 04 14 00 00 00 08 00  - .4....PK........
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0010    84 61 D8 4E 73 67 93 AF 7C 0A 00 00 E0 B0 00 00  - .a.Nsg..|.......
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0020    0A 00 1C 00 62 61 63 6B 75 70 2E 6C 6F 67 55 54  - ....backup.logUT
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0030    09 00 03 18 BE 10 5D 90 BD 10 5D 75 78 0B 00 01  - ......]...]ux...
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0040    04 1A 00 00 00 04 1A 00 00 00 ED 5C 4D 6F DC C8  - ...........\Mo..
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0050    11 BD E7 57 34 74 4A 80 D8 80 77 17 8B 45 80 1C  - ...W4tJ...w..E..

.... [lots of encoded data trimmed out here, the next part shows re-filling the 8k buffer] ....

[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_get_message::jk_ajp_common.c (1462): received from ajp13 pos=0 len=3 max=8192E D7 E9 E6 DD BB  - 8...U?.er.>.....
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_get_message::jk_ajp_common.c (1462): 00000   06 1F FA 00 00 00 00 00 00 00 00 00 00 00 00 00  - .................
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): sending to ajp13 pos=4 len=8192 max=8192 2E 40 41 4C 94  - ..$z~YW.?1G.@AL.
[Mon Jun 24 14:37:08 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 0000    12 34 1F FC 1F FA C9 62 3E 48 C5 70 E9 05 E1 8D  - .4.....b>H.p....

.... [lots of encoded data trimmed out here, the next part shows where re-filling the 8k buffer fails] ....

[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 03e0    2D E5 36 F3 8C 12 8C 51 69 66 21 AE A5 58 BE 6E  - -.6....Qif!..X.n
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_connection_tcp_send_message::jk_ajp_common.c (1267): 03f0    57 F3 F4 EC CB E9 49 9B 59 44 AB FE 66 6E 67 DC  - W.....I.YD..fng.
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_connection_tcp_get_message::jk_ajp_common.c (1462): received from ajp13 pos=0 len=3 max=8192
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_connection_tcp_get_message::jk_ajp_common.c (1462): 0000   06 1F FA 00 00 00 00 00 00 00 00 00 00 00 00 00  - ................
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [info] ajp_read_into_msg_buff::jk_ajp_common.c (1553): (main_ajp13_worker) receiving data from client failed. Connection aborted or network problems
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [info] ajp_process_callback::jk_ajp_common.c (2105): (main_ajp13_worker) Reading from client aborted or client network problems
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [info] ajp_service::jk_ajp_common.c (2778): (main_ajp13_worker) sending request to tomcat failed (unrecoverable), because of client read error (attempt=1)
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_reset_endpoint::jk_ajp_common.c (851): (main_ajp13_worker) resetting endpoint with socket 24 (socket shutdown)
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_abort_endpoint::jk_ajp_common.c (821): (main_ajp13_worker) aborting endpoint with socket 24
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] jk_shutdown_socket::jk_connect.c (932): About to shutdown socket 24 [127.0.0.1:38678 -> 127.0.0.1:8009]
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] jk_shutdown_socket::jk_connect.c (1005): shutting down the read side of socket 24 [127.0.0.1:38678 -> 127.0.0.1:8009]
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] jk_shutdown_socket::jk_connect.c (1016): Shutdown socket 24 [127.0.0.1:38678 -> 127.0.0.1:8009] and read 265 lingering bytes in 0 sec.
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [debug] ajp_done::jk_ajp_common.c (3287): recycling connection pool for worker main_ajp13_worker and socket -1
[Mon Jun 24 14:37:28 2019] [17826:139891516274752] [info] jk_handler::mod_jk.c (2988): Aborting connection for worker=main_ajp13_worker
[Mon Jun 24 14:38:24 2019] [17825:139891516274752] [debug] wc_shutdown::jk_worker.c (390): Shutting down worker main_ajp13_worker
[Mon Jun 24 14:38:24 2019] [17825:139891516274752] [debug] jk_shm_close::jk_shm.c (745): Closed shared memory /var/log/httpd/mod_jk.shm.17823 childs=9
[Mon Jun 24 14:38:24 2019] [17877:139891516274752] [debug] wc_shutdown::jk_worker.c (390): Shutting down worker main_ajp13_worker

查看AJPv3 文档,我们看到了 8k 块的解释:

容器从请求中请求更多数据(如果主体太大而无法放入发送的第一个数据包或请求被分块时)。服务器将发回一个正文数据包,其中包含的数据量是 request_length、最大发送正文大小 (8186 (8 Kbytes - 6)) 和实际剩余要从请求正文发送的字节数中的最小值。如果 body 中没有更多数据(即 servlet 容器试图读取超过 body 的末尾),服务器将发回一个“空”数据包,这是一个有效负载长度为 0 的 body 数据包。( 0x12,0x34,0x00,0x00)

在上述日志中,我统计了重新填充 8k 缓冲区的次数(36,856 次),发现在错误发生之前传输了 301,703,216 字节(287 MB,或 62%)的文件。在反复尝试时,这个百分比变化很大,但通常超过 300MB,有时会成功完成所有 440MB。


我对以上日志的解读

SSL 握手成功,错误发生在 HTTP 100 Continue 之后,所以我怀疑该文件在mod_jk.log中的以下消息之前已部分发送:

  • 从客户端接收数据失败。连接中止或网络问题
  • 由于客户端读取错误(尝试=1),向 tomcat 发送请求失败(不可恢复)

由于catalina.out没有错误,并且 mod_jk 抱怨客户端读取错误,我相信这排除了 Tomcat 本身(以及 Web 应用程序Artifactory)。

我在谷歌搜索中看到的大多数关于上述 mod_jk 消息的评论都表明它们是暂时的网络错误,但我不相信,因为这些是同一区域中 EC2 实例之间的文件传输。我也将此解释为与连接超时没有任何关系,因为(我认为)会产生“连接在 n 毫秒后超时”消息。


更改 mod_jk 和 Tomcat 配置

我尝试过的其他事情(这些变化是累积的,结果没有明显的变化):

  • 将 mod_jk 升级到最新版本 (1.2.46)
  • 将工作包大小从 8,196(默认)增加到 16,384
  • 工作数据包大小从 16,384 增加到 32,768
  • 将 JkShmSize 从 1kB(默认)增加到 1GB(哎呀,值以 kB 为单位)
  • 将 JkShmSize 从 1GB 减少到 1MB
  • 将工作人员 JkShmSize 返回到默认值
  • 将工作包大小返回为默认值
  • 将工作重试次数从 2(默认)增加到 5
  • 将 reply_timeout 从永远(默认)减少到 1000 毫秒(这实际上在成功上传期间导致底层服务出现一些问题)
  • 返回的工人重试默认值
  • 将 reply_timeout 返回到默认值
  • 将 socket_keepalive 从 false(默认)更改为 true
  • 将 socket_keepalive 恢复为默认值
  • 将连接器协议从 org.apache.coyote.http11.Http11NioProtocol 更改为 org.apache.coyote.http11.Http11Nio2Protocol
  • 将 Tomcat 连接超时从 20 秒 (20000) 增加到 60 秒 (60000)
  • 将 Tomcat connectionUploadTimeout 设置为 60 秒 (60000)
  • 将 Tomcat disableUploadTimeout 设置为 false
  • 将 connectionUploadTimeout 和 disableUploadTimeout 返回为默认值
  • 通过 -H "Transfer-Encoding:chunked" 强制分块传输
  • 将worker属性设置为:retries=2,socket_timeout=100,reply_timeout=30000
  • 将工作人员属性恢复为默认值。
  • 在 JkOptions 中添加了 +DisableReuse。
  • 将 JkOptions 恢复为默认值。
  • 为 repo 和 repo-access 虚拟主机创建了单独的工作人员。
  • 删除了非 SSL 虚拟主机条目,只留下两个 SSL 虚拟主机。

注意:分离工作人员至少隔离了工作人员消息,所以我现在知道错误完全发生在 repo web 服务上,而不是 repo-access web 服务上:

[Sat Jun 29 16:16:55 2019] [6174:139690136819776] [info] ajp_read_into_msg_buff::jk_ajp_common.c (1550): (repo) receiving data from client failed. Connection aborted or network problems
[Sat Jun 29 16:16:55 2019] [6174:139690136819776] [info] ajp_process_callback::jk_ajp_common.c (2102): (repo) Reading from client aborted or client network problems
[Sat Jun 29 16:16:55 2019] [6174:139690136819776] [info] ajp_service::jk_ajp_common.c (2775): (repo) sending request to tomcat failed (unrecoverable), because of client read error (attempt=1)
[Sat Jun 29 16:16:55 2019] [6174:139690136819776] [info] jk_handler::mod_jk.c (2984): Aborting connection for worker=repo

更改 HTTP(S) 客户端

我能够使用 wget 而不是 curl 重现该问题,这意味着这不是客户端软件的一些深奥问题:

-bash-4.2$ wget -v --tries=1 --user=backup --password=PASSWORD --header=X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3 --header=X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10 --method=PUT --body-file=snapshot-20190612.zip https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip

--2019-06-24 19:59:16--  https://repo.mydomain.org/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
Resolving repo.mydomain.org (repo.mydomain.org)... 123.222.100.132
Connecting to repo.mydomain.org (repo.mydomain.org)|123.222.100.132|:443... connected.
HTTP request sent, awaiting response... 401 401
Authentication selected: Basic realm="Artifactory Realm"
Reusing existing connection to repo.mydomain.org:443.
Giving up.

在本地主机上测试

我已经在存档服务器(https://localhost:443/)上测试了从本地主机上传,这需要将-k标志添加到 curl 以跳过证书主机名验证,并且每次上传都成功(11秒)。但是,添加--limit-rate 20M会导致每次上传都失败(它适用于--limit-rate 25M)。


绕过 Apache HTTPD、mod_jk 和 SSL 有效

如果我绕过 Apache HTTPD、mod_jk 和 SSL 并直接通过端口 8080,上传总是会成功:

[ec2-user@repo ~]$ curl -v -k --limit-rate 1024K -u backup:PASSWORD -H X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3 -H X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10 -T snapshot-20190612.zip http://localhost:8080/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Server auth using Basic with user 'backup'
> PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1
> Host: localhost:8080
> Authorization: Basic DELETED_TOKEN
> User-Agent: curl/7.61.1
> Accept: */*
> X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3
> X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10
> Content-Length: 496278603
> Expect: 100-continue
>
< HTTP/1.1 100
* We are completely uploaded and fine
< HTTP/1.1 201
< Server: Artifactory/5.3.2
...

仅绕过SSL失败

通过没有 SSL 的 Apache HTTPD + mod_jk,我仍然能够复制问题。这意味着该问题与 SSL 无关。

[ec2-user@repo ~]$ curl -v -k --limit-rate 1024K -u backup:PASSWORD -H X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3 -H X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10 -T snapshot-20190612.zip http://localhost/resource-snapshot/snapshot/20190612/snapshot-20190612.zip
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
* Server auth using Basic with user 'backup'
> PUT /resource-snapshot/snapshot/20190612/snapshot-20190612.zip HTTP/1.1
> Host: localhost:8080
> Authorization: Basic DELETED_TOKEN
> User-Agent: curl/7.61.1
> Accept: */*
> X-Checksum-Sha1:6b9525bf9bb572ec7f70d0d474cb6533e0091bd3
> X-Checksum-Md5:6da0c444ad1b53dc1cf06784e204cb10
> Content-Length: 496278603
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* Recv failure: Connection reset by peer
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer

绕过 HTTPD 和 mod_jk

我尝试通过端口 8443(仍然使用 SSL)直接上传到 Tomcat 来绕过 Apache HTTPD 和 mod_jk。这些请求每次都成功。这使我相信问题出在 Apache HTTPD 和/或 mod_jk 上,而不是由“瞬态网络错误”或防火墙引起的。


TL;博士

上传失败仅在通过 HTTPD + mod_jk 时发生,而不是在直接与 Tomcat 通信时发生。SSL 已被排除为问题的潜在根源。这不是网络问题,因为从 localhost 上传时该错误是可重现的。该问题似乎仅与传输文件所需的时间有关,与文件大小无关。


我的问题

我应该为 HTTPD 和/或mod_jk、workers.properties甚至Tomcat寻找任何配置选项来消除这些问题吗?

或者,有没有办法告诉mod_jk尝试以容错方式处理这些失败的缓冲区重新填充,以便上传可以成功完成?

apache-2.4
  • 1 个回答
  • 1251 Views
Martin Hope
Parker
Asked: 2015-07-08 18:41:54 +0800 CST

大量 JetDirect 固件更新 - 它们解决了哪些问题?

  • 2

惠普最近发布了大量针对 JetDirect 设备的固件更新。没有提供变更日志。奇怪的是,许多过时的(例如,802.11b)设备都在列表中,最后一次为其中一些设备提供固件更新是在 2004 年。这些设备的范围从 10/100 以太网到 802.11b/g 打印服务器、EIO、 MIO 和 LIO。这批更新是否解决了一些安全漏洞(例如,SSLv3、POODLE 或其他记录在案的 CVE)或引入了新功能(例如,TL​​S 或 WPA2)?

更新 根据接受的答案中提供的页面中的信息,这些固件更新中引入了几个安全更新和新功能。在 280m 的更新中,这些是我最感兴趣的更新,因为它们出现了几个 SSL 漏洞并添加了 WPA 兼容性:

  • 自动 IP 寻址
  • 以太网本地管理寻址 (LAA)
  • SSL证书的导入/导出
  • CERT 漏洞说明VU#412115已修复
  • FTP 和 DHCP 改进,SPX 和 TCP 改进。
  • 802.11b 的 Wi-Fi 认证和 680n (J6058A)、380x (J6061A)、280m (J6044A) 802.11b 无线打印服务器的 WPA。
hp
  • 1 个回答
  • 543 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve