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
    • 最新
    • 标签
主页 / coding / 问题 / 79194535
Accepted
David Martínez Gil
David Martínez Gil
Asked: 2024-11-16 12:43:59 +0800 CST2024-11-16 12:43:59 +0800 CST 2024-11-16 12:43:59 +0800 CST

如何使用 Rust 在两个对等点之间建立 TLS 连接

  • 772

我正在开发一个文件传输系统,该系统具有使用 Rust 的 p2p 连接库。它仅使用 tcp 即可工作,但现在我想使用 TLS 对其进行改进,但我不明白 2 件事。两个对等方如何共享证书颁发机构 CA,以便他们可以验证连接是否值得信赖。在我描述的对等连接中,只有 2 个对等方尝试传输一些文件。由于他们没有域 IP,因此无法工作。如果有人能在这方面给我一些帮助,我会很迷茫,请提供一些如何处理的指导,谢谢。

ssl
  • 1 1 个回答
  • 55 Views

1 个回答

  • Voted
  1. Best Answer
    Finn Bear
    2024-11-16T14:30:23+08:002024-11-16T14:30:23+08:00

    native-tls

    同步函数的文档说明connect:

    如果 SNI 和主机名验证都被禁用,则该域将被忽略。

    考虑到这一点,切换到asyncAPI 并生成自签名证书,我们得到以下工作代码:

    [package]
    name = "tls"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    rcgen = "0.13.1"
    tokio = { version = "1.41.1", features = ["full"] }
    tokio-native-tls = "0.3.1"
    
    use tokio::io::{AsyncReadExt, AsyncWriteExt};
    use tokio::net::{TcpListener, TcpStream};
    use tokio_native_tls::native_tls::Identity;
    use tokio_native_tls::{native_tls, TlsAcceptor, TlsConnector};
    
    #[tokio::main]
    async fn main() {
        let cert = rcgen::generate_simple_self_signed([]).unwrap();
        let listener = TcpListener::bind("127.0.0.1:8001").await.unwrap();
    
        let trusted = native_tls::Certificate::from_pem(cert.cert.pem().as_bytes()).unwrap();
        tokio::spawn(async move {
            let connector = TlsConnector::from(
                native_tls::TlsConnector::builder()
                    .disable_built_in_roots(true)
                    .add_root_certificate(trusted)
                    .danger_accept_invalid_hostnames(true)
                    .use_sni(false)
                    .build()
                    .unwrap(),
            );
            let tcp = TcpStream::connect("0.0.0.0:8001").await.unwrap();
            let mut tls = connector.connect("N/A", tcp).await.unwrap();
            tls.write_all(b"hello!").await.unwrap();
            tls.shutdown().await.unwrap();
        });
    
        let acceptor = TlsAcceptor::from(
            native_tls::TlsAcceptor::new(
                Identity::from_pkcs8(
                    cert.cert.pem().as_bytes(),
                    cert.key_pair.serialize_pem().as_bytes(),
                )
                .unwrap(),
            )
            .unwrap(),
        );
    
        let (tcp, _) = listener.accept().await.unwrap();
        let mut tls = acceptor.accept(tcp).await.unwrap();
        let mut buf = String::new();
        tls.read_to_string(&mut buf).await.unwrap();
        println!("read: {buf}");
    }
    

    rustls

    以下是使用 的类似代码rustls。不同之处包括:

    • 您可以并且应该传递服务器 IP,而不是“N/A”作为服务器名称。
    • 默认证书验证器要求 IP 位于主题名称之中。
    [package]
    name = "tls"
    version = "0.1.0"
    edition = "2021"
    
    [dependencies]
    rcgen = "0.13.1"
    tokio = { version = "1.41.1", features = ["full"] }
    tokio-rustls = "0.26.0"
    
    use std::net::Ipv4Addr;
    use std::sync::Arc;
    use tokio::io::{AsyncReadExt, AsyncWriteExt};
    use tokio::net::{TcpListener, TcpStream};
    use tokio_rustls::rustls::pki_types::pem::PemObject;
    use tokio_rustls::rustls::pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer, ServerName};
    use tokio_rustls::rustls::{ClientConfig, RootCertStore};
    use tokio_rustls::{rustls, TlsAcceptor, TlsConnector};
    
    #[tokio::main]
    async fn main() {
        let cert = rcgen::generate_simple_self_signed(["127.0.0.1".to_owned()]).unwrap();
        let listener = TcpListener::bind("127.0.0.1:8001").await.unwrap();
    
        let mut trusted = RootCertStore::empty();
        trusted.add(cert.cert.der().clone()).unwrap();
        tokio::spawn(async move {
            let connector: TlsConnector = TlsConnector::from(Arc::new(
                ClientConfig::builder()
                    .with_root_certificates(trusted)
                    .with_no_client_auth(),
            ));
            let tcp = TcpStream::connect("127.0.0.1:8001").await.unwrap();
            let mut tls = connector
                .connect(
                    ServerName::IpAddress(Ipv4Addr::new(127, 0, 0, 1).into()),
                    tcp,
                )
                .await
                .unwrap();
            tls.write_all(b"hello!").await.unwrap();
            tls.shutdown().await.unwrap();
        });
    
        let acceptor = TlsAcceptor::from(Arc::new(
            rustls::ServerConfig::builder()
                .with_no_client_auth()
                .with_single_cert(
                    vec![cert.cert.der().clone()],
                    PrivateKeyDer::Pkcs8(
                        PrivatePkcs8KeyDer::from_pem_slice(cert.key_pair.serialize_pem().as_bytes())
                            .unwrap(),
                    ),
                )
                .unwrap(),
        ));
    
        let (tcp, _) = listener.accept().await.unwrap();
        let mut tls = acceptor.accept(tcp).await.unwrap();
        let mut buf = String::new();
        tls.read_to_string(&mut buf).await.unwrap();
        println!("read: {buf}");
    }
    

    如果您想使用 CA 签名的证书,则可以将 CA 证书添加为受信任的根。

    • 2

相关问题

  • traefik acme http challenge 得出“没有默认证书,回退到内部生成的证书”

  • 有没有办法以 32 字节数据包的形式安全地传输数据(TLS 版本)?

  • SSLStream 客户端证书用途

  • HTTPS/TLS/SSL 如何防止会话劫持?[复制]

  • 下面的 tls 握手,有什么问题吗?

Sidebar

Stats

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

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行?

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    何时应使用 std::inplace_vector 而不是 std::vector?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Martin Hope
    Aleksandr Dubinsky 为什么 InetAddress 上的 switch 模式匹配会失败,并出现“未涵盖所有可能的输入值”? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge 为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini 具有指定基础类型但没有枚举器的“枚举类”的用途是什么? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer 何时应使用 std::inplace_vector 而不是 std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB 为什么 GCC 生成有条件执行 SIMD 实现的代码? 2024-02-17 06:17:14 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

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

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve