Skip to main content

tuwunel_router/serve/
tls.rs

1use std::{
2	net::{SocketAddr, TcpListener},
3	path::Path,
4};
5
6use axum::{Router, extract::connect_info::IntoMakeServiceWithConnectInfo};
7use axum_server::{Handle, from_tcp_rustls};
8use axum_server_dual_protocol::{
9	ServerExt, axum_server::tls_rustls::RustlsConfig, from_tcp_dual_protocol,
10};
11use futures::{FutureExt, future::BoxFuture};
12use tuwunel_core::{Result, debug, err, info};
13
14pub(super) async fn serve<'a>(
15	app: &Router,
16	handle: &Handle<SocketAddr>,
17	cert: &Path,
18	key: &Path,
19	dual_protocol: bool,
20	listeners: impl Iterator<Item = TcpListener>,
21) -> Result<Vec<BoxFuture<'a, Result<(), std::io::Error>>>> {
22	info!(
23		"Note: It is strongly recommended that you use a reverse proxy instead of running \
24		 tuwunel directly with TLS."
25	);
26
27	debug!(
28		"Using direct TLS. Certificate path {cert:?} and certificate private key path {key:?}"
29	);
30
31	let conf = RustlsConfig::from_pem_file(cert, key)
32		.await
33		.map_err(|e| err!(Config("tls", "Failed to load certificates or key: {e}")))?;
34
35	let app = app
36		.clone()
37		.into_make_service_with_connect_info::<SocketAddr>();
38
39	if dual_protocol {
40		serve_dual_protocol(&app, &conf, handle, listeners)
41	} else {
42		serve_tls(&app, &conf, handle, listeners)
43	}
44}
45
46fn serve_dual_protocol<'a>(
47	app: &IntoMakeServiceWithConnectInfo<Router, SocketAddr>,
48	conf: &RustlsConfig,
49	handle: &Handle<SocketAddr>,
50	listeners: impl Iterator<Item = TcpListener>,
51) -> Result<Vec<BoxFuture<'a, Result<(), std::io::Error>>>> {
52	listeners
53		.map(|listener| {
54			// Pinned against an upstream default flip: a plain request is answered,
55			// never redirected to the https scheme.
56			let acceptor = from_tcp_dual_protocol(listener, conf.clone())?
57				.set_upgrade(false)
58				.handle(handle.clone())
59				.serve(app.clone())
60				.boxed();
61
62			Ok(acceptor)
63		})
64		.collect()
65}
66
67fn serve_tls<'a>(
68	app: &IntoMakeServiceWithConnectInfo<Router, SocketAddr>,
69	conf: &RustlsConfig,
70	handle: &Handle<SocketAddr>,
71	listeners: impl Iterator<Item = TcpListener>,
72) -> Result<Vec<BoxFuture<'a, Result<(), std::io::Error>>>> {
73	listeners
74		.map(|listener| {
75			let acceptor = from_tcp_rustls(listener, conf.clone())?
76				.handle(handle.clone())
77				.serve(app.clone())
78				.boxed();
79
80			Ok(acceptor)
81		})
82		.collect()
83}