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
    • 最新
    • 标签
主页 / unix / 问题 / 451207
Accepted
l0b0
l0b0
Asked: 2018-06-22 15:20:02 +0800 CST2018-06-22 15:20:02 +0800 CST 2018-06-22 15:20:02 +0800 CST

如何在 cURL 命令行中信任自签名证书?

  • 772

我使用Let's Encrypt 推荐使用这个 Makefile为 foo.localhost 创建了一个自签名证书:

include ../.env

configuration = csr.cnf
certificate = self-signed.crt
key = self-signed.key

.PHONY: all
all: $(certificate)

$(certificate): $(configuration)
    openssl req -x509 -out $@ -keyout $(key) -newkey rsa:2048 -nodes -sha256 -subj '/CN=$(HOSTNAME)' -extensions EXT -config $(configuration)

$(configuration):
    printf "[dn]\nCN=$(HOSTNAME)\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:$(HOSTNAME)\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth" > $@

.PHONY: clean
clean:
    $(RM) $(configuration)

然后,我将其分配给 Web 服务器。我已验证服务器返回相关证书:

$ openssl s_client -showcerts -connect foo.localhost:8443 < /dev/null
CONNECTED(00000003)
depth=0 CN = foo.localhost
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = foo.localhost
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/CN=foo.localhost
   i:/CN=foo.localhost
-----BEGIN CERTIFICATE-----
[…]
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=foo.localhost
issuer=/CN=foo.localhost
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1330 bytes and written 269 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: […]
    Session-ID-ctx: 
    Master-Key: […]
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket:
    […]

    Start Time: 1529622990
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
    Extended master secret: no
---
DONE

如何在不修改 /etc 中的任何内容的情况下让 cURL 信任它? --cacert不起作用,大概是因为没有CA :

$ curl --cacert tls/foo.localhost.crt 'https://foo.localhost:8443/'
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

目标是在开发过程中启用 HTTPS:

  • 如果没有在所有开发环境中启用 DNS 验证的大量工作,我就无法拥有完全类似于生产的证书。因此我必须使用自签名证书。
  • 我显然仍然想让我的开发环境尽可能地类似于生产环境,所以我不能简单地忽略任何和所有证书问题。curl -k就像catch (Exception e) {}在这种情况下一样 - 完全不像浏览器与 Web 服务器通信。

换句话说,当我跑步时,curl [something] https://project.local/api/foo我想确信

  1. 如果 TLS 配置正确,除了具有自签名证书,该命令将成功并且
  2. 如果我的 TLS 配置有任何问题,除了拥有自签名证书,该命令将失败。

使用 HTTP 或--insecure不符合第二个标准。

curl https
  • 7 7 个回答
  • 155357 Views

7 个回答

  • Voted
  1. V13
    2018-10-17T15:55:31+08:002018-10-17T15:55:31+08:00

    尝试-k:

    curl -k https://yourhost/
    

    它应该“接受”自签名证书

    • 41
  2. Robert Brisita
    2018-09-12T11:19:32+08:002018-09-12T11:19:32+08:00

    遵循这些步骤应该可以解决您的问题:

    1. 下载并保存自签名证书:echo quit | openssl s_client -showcerts -servername "${API_HOST}" -connect "${API_HOST}":443 > cacert.pem
    2. 告诉curl客户:curl --cacert cacert.pem --location --silent https://${API_HOST}

    也可以使用 wget 并忽略以下证书:wget --no-check-certificate https://${API_HOST}

    • 17
  3. Best Answer
    TrentP
    2020-04-25T12:12:26+08:002020-04-25T12:12:26+08:00

    我有这个问题,完全相同的问题和错误消息,但我使用 GNUTLS 的 certtool 来生成我的证书而不是 openssl。

    我的问题是我没有将我的自签名证书设为 CA。它仅配置为充当 Web 服务器证书。这就是我想要用它做的所有事情,我不打算将它用作 CA 来签署其他证书。

    但是当你想将一个证书作为其他证书的颁发者添加到信任链中时,该证书必须是 CA,否则会被 openssl 拒绝!

    有了certtool -i < mycert.crt,人们需要看到这一点:

        Extensions:
                Basic Constraints (critical):
                        Certificate Authority (CA): TRUE
    

    尝试添加-addext basicConstraints=critical,CA:TRUE,pathlen:1到您的 openssl 命令或修改您的 cnf 文件以达到相同的效果。

    或者,使用 certtool,一次性生成证书要容易得多:

    certtool -p --outfile localhost.key
    certtool -s --load-privkey localhost.key --outfile localhost.crt
    

    然后回答提示以提供证书的 CN 等。当被问及它是否适用于证书颁发机构时,说是的!

    • 9
  4. l0b0
    2021-10-19T18:46:55+08:002021-10-19T18:46:55+08:00

    trustme,由urllib3使用,看起来是个不错的选择。根据他们的自述文件:

    $ # ----- Creating certs -----
    $ python -m trustme
    Generated a certificate for 'localhost', '127.0.0.1', '::1'
    Configure your server to use the following files:
      cert=/tmp/server.pem
      key=/tmp/server.key
    Configure your client to use the following files:
      cert=/tmp/client.pem
    $ # ----- Using certs -----
    $ gunicorn --keyfile server.key --certfile server.pem app:app
    $ curl --cacert client.pem https://localhost:8000/
    Hello, world!
    
    • 3
  5. user232326
    2018-09-13T22:35:52+08:002018-09-13T22:35:52+08:00

    拥有包含自签名证书的信任链是无效的。如果是这样的话,任何人都可以提供(组成)有效的信任链。如果自签名证书出现在信任链中,则必须忽略它。自签名证书只能在本地目录(由计算机所有者控制)中有效。提供给任何服务器的证书必须链接到自签名证书。

    没有大部分小细节的一般指南。

    • 您的openssl s_client命令输出显示两个错误:

      verify error:num=20:unable to get local issuer certificate
      verify error:num=21:unable to verify the first certificate
      

      这意味着您机器中的默认证书存储缺少一个验证您使用的网站给出的链的证书。您需要一个带有自签名证书的目录和一个链接到该 Web 服务器的证书。

    脚步:

    1. 您可以构建一个新目录(在任何地方),使用c_rehash脚本处理它并告诉 openssl 使用它来验证带有选项的证书-CApath Directory。-CApath进行更改,直到您在使用该选项时消除这两个错误。

    2. 为 Web 服务器生成链式证书。

    3. 然后,告诉 curl 证书目录:

      curl --capath <dir>
      

      以及所需的所有其他选项。

    这将清除这两个错误。

    • 2
  6. Fagner Fonseca
    2022-02-05T08:42:55+08:002022-02-05T08:42:55+08:00

    using 提供的解决方案trustme完美运行,但如果有人有兴趣为学习目的创建证书,这些步骤对我有用:

    1. 创建根 CA:

      openssl req -x509 -sha256 -days 1825 -newkey rsa:2048 -keyout rootCA.key -out rootCA.crt
      
    2. 创建服务器私钥:

      openssl genrsa -out localhost.key 2048
      
    3. 创建证书签名请求:

      openssl req -key localhost.key -new -out localhost.csr
      
    4. 创建localhost.ext具有以下内容的文件:

      authorityKeyIdentifier=keyid,issuer
      basicConstraints=CA:FALSE
      subjectAltName = @alt_names
      [alt_names]
      DNS.1 = localhost
      

      此文件具有证书的 DNS 配置。这很重要,因为如果 URL 中的名称与证书中的 DNS 不匹配,TLS 检查将不会通过。

    5. 使用之前创建的根 CA 签署服务器证书:

      openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in localhost.csr -out localhost.crt -days 365 -CAcreateserial -extfile localhost.ext
      
    6. 将crt文件转换为以下pem格式:

      openssl x509 -in localhost.crt -out localhost.pem
      openssl x509 -in rootCA.crt -out rootCA.pem
      

    现在您应该可以在服务器中使用 thelocalhost.pem和 the了。localhost.key客户端应该使用rootCA.pem连接到服务器。

    就我而言,我必须使用jks文件。该pem文件可以转换jks为如下:

    //first convert it to pkcs12
    openssl pkcs12 -export -in localhost.pem -inkey localhost.key -out serverCertificate.p12 -name "serverCertificate"
    
    //then convert it from pkcs12 to jks
    keytool -importkeystore -srckeystore serverCertificate.p12 -srcstoretype pkcs12 -destkeystore localhost.jks
    

    可以使用以下命令查看密钥库中的条目:

    keytool -keystore localhost.jks -list
    

    localhost.jks应该在服务器中使用,并且可以使用以下方法测试连接:

    curl --cacert rootCA.pem https://localhost:<port>
    

    参考:

    1. https://www.baeldung.com/openssl-self-signed-cert
    2. https://www.digicert.com/kb/ssl-support/openssl-quick-reference-guide.htm
    3. https://www.baeldung.com/convert-pem-to-jks
    • 2
  7. user2679859
    2020-05-05T12:58:09+08:002020-05-05T12:58:09+08:00

    如果您从服务器保存 self-signed.crt,您可以通过“--cacert self-signed.crt”将其传递给 curl,curl 将使用给定的 CA Cert 验证您的服务器的证书。

    • 0

相关问题

  • 如果文件已在本地存在,请勿使用 curl 下载文件

  • 如何卷曲并解压缩到某个目录?[复制]

  • 从终端检查 URL 重定向

  • 从文件中获取 URL 地址并检查 HTTP 代码

  • 如何在终端中下载链接重定向并且似乎仅在 GUI 中工作的文件?

Sidebar

Stats

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

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

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

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve