跨平台P2P Rust文件传输库的TLS加密实现及握手故障排查求助
跨平台P2P Rust文件传输库的TLS加密实现及握手故障排查求助
大家好,我正在开发一个Rust语言的文件传输类库,目标是实现设备间的文件互传,目前已经基于TCP完成了基础功能,但现在想给客户端和服务端的连接加上TLS加密,却卡在了TLS握手失败的问题上——服务端能正常启动,但客户端发起连接时握手总是失败,我一直没定位到根源。
我已经尝试的排查方案
- 用OpenSSL生成了自签名证书
- 基于
rustls配置加载这些证书 - 确认客户端和服务端都能正确读取并加载证书
- 简化TLS配置来缩小排查范围,但握手失败的问题依然存在
我的核心目标
- 给客户端与服务端的连接加上TLS加密保护
- 支持P2P连接模式
- 确保证书的配置与验证流程完全合规
- 实现跨平台兼容,能在不同操作系统的设备间正常建立连接
当前使用的技术栈
我目前用的是rustls和tokio_rustls,如果换用其他更适配场景的库也完全没问题。
客户端与服务端核心代码
客户端连接代码
pub struct Client { client_storage_path: String, server_address: IpAddr, timeout: Option<Duration>, connection: Arc<Mutex<Option<TlsStream<TcpStream>>>>, } impl Client { pub fn new(client_storage_path: &str, server_address: IpAddr) -> Self { Self { client_storage_path: client_storage_path.to_owned(), server_address, timeout: None, connection: Arc::new(Mutex::new(None)) } } /// Sets a timeout duration for the client. pub fn set_timeout(&mut self, timeout: Duration) { self.timeout = Some(timeout); } /// Connects to the server. pub async fn connect(&mut self) -> Result<(), anyhow::Error> { let crypto_provider = tokio_rustls::rustls::crypto::aws_lc_rs::default_provider(); if let Err(err) = crypto_provider.install_default() { eprintln!("Failed to install default CryptoProvider: {:?}", err) } let cert = rcgen::generate_simple_self_signed(vec![self.server_address.to_string()]).unwrap(); println!("Server Certificate:\n{}", cert.key_pair.serialize_pem()); let mut trusted = RootCertStore::empty(); trusted.add(cert.cert.der().clone()).unwrap(); let connector: TlsConnector = TlsConnector::from(Arc::new( ClientConfig::builder() .with_root_certificates(trusted) .with_no_client_auth(), )); let addr = SocketAddr::new(self.server_address, 8080); let tcp = TcpStream::connect(addr).await?; let tls = connector .connect(ServerName::IpAddress(self.server_address.into()), tcp) .await.expect("Could not connect with tls"); let mut connection = self.connection.lock().await; *connection = Some(tokio_rustls::TlsStream::Client(tls)); Ok(()) } }
服务端启动代码
#[derive(Clone)] pub struct Server { /// Indicates if the server is currently running. pub is_server_running: Arc<Mutex<bool>>, /// The IP address on which the server listens. pub ip: IpAddr, /// The port on which the server listens. pub port: u16, /// The path to the directory where files are stored. pub path: String, /// Buffer size for file transfer operations. pub buffer_size: u64, /// Notification signal for stopping the server. pub stop_signal: Arc<Notify>, } impl Server { /// Creates a new instance of the `Server`. /// /// # Parameters /// /// - `ip`: IP address on which the server will listen. /// - `port`: Port on which the server will listen. /// - `path`: Directory path for file storage and retrieval. /// - `buffer_size`: Size of the buffer used for file transfers. pub fn new(ip: IpAddr, port: u16, path: &str, buffer_size: u64, stop_signal: Arc<Notify>) -> Self { let is_server_running = Arc::new(Mutex::new(false)); Self { is_server_running, ip, port, path: path.to_owned(), buffer_size, stop_signal, } } /// Starts the server, accepting and handling incoming connections. pub async fn start_server(&mut self) -> Result<(), Box<dyn std::error::Error>> { let crypto_provider = rustls::crypto::ring::default_provider(); if let Err(err) = crypto_provider.install_default() { eprintln!("Failed to install default CryptoProvider: {:?}", err) } let listener = TcpListener::bind(SocketAddr::new(self.ip.to_owned(), self.port)).await?; let cert = rcgen::generate_simple_self_signed(vec![self.ip.to_string()]) .map_err(|e| format!("Certificate generation failed: {:?}", e))?; println!("Server Certificate:\n{}", cert.key_pair.serialize_pem()); println!("Server running on {}", self.ip); // accept connection 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(), )); loop { tokio::select! { // Wait for an incoming connection result = listener.accept() => { match result { Ok((socket, addr)) => { let tls = acceptor.accept(socket).await.unwrap(); println!("New connection from: {}", addr); let stop_signal_clone = Arc::clone(&self.stop_signal); let self_clone = self.clone(); tokio::spawn(async { if let Err(e) = self_clone.handle_request(tokio_rustls::TlsStream::Server(tls), stop_signal_clone).await { eprintln!("Error handling connection: {:?}", e); } }); } Err(e) => { eprintln!("Failed to accept connection: {:?}", e); } } }, _ = self.stop_signal.notified() => { println!("Stopping server..."); break; }, } } Ok(()) } }
备注:内容来源于stack exchange,提问作者David Martínez Gil
相关产品推荐
相关产品推荐

