我正在一个文件传输系统中工作,该系统具有使用 Rust 的 p2p 连接库。它仅使用 tcp 即可工作,但现在我想使用 TLS 改进它,但我不明白两件事。首先是两个对等方如何共享证书颁发机构 CA,以便他们可以验证连接是否值得信赖。其次,我尝试使用 tokio_native_tls 来包装 native_tls 库并添加异步。我正在遵循 native_tls 文档中的示例。然而,他们使用带有域的连接器,并使用谷歌作为域。这是他们提供的示例。
use native_tls::TlsConnector;
use std::io::{Read, Write};
use std::net::TcpStream;
let connector = TlsConnector::new().unwrap();
let stream = TcpStream::connect("google.com:443").unwrap();
let mut stream = connector.connect("google.com", stream).unwrap();
stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
let mut res = vec![];
stream.read_to_end(&mut res).unwrap();
println!("{}", String::from_utf8_lossy(&res));
在我描述的对等连接中,只有 2 个对等点尝试传输一些文件。由于他们没有纯域名 IP,因此无法正常工作。如果有人能给我一些帮助,请提供一些如何处理的指南,那就太好了,谢谢。
同步 connect
函数的
docs说:
如果同时禁用 SNI 和主机名验证,则域将被忽略。
考虑到这一点,切换到
async
API,并生成自签名证书,我们得到以下工作代码:
[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();
});
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}");
}
如果您想使用 CA 签名的证书,则应信任 CA 证书。