diff options
author | Alex Auvolat <alex@adnab.me> | 2021-12-08 22:58:19 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2021-12-08 22:58:19 +0100 |
commit | ca8c5aad2378dd9f8ec525b3b0779f5c53cfe9eb (patch) | |
tree | ba5ac35eeacd9ee85363c231030313e7204ecc63 /src | |
parent | 55f57df82e8486065bd563c21e1ea858c9f8969d (diff) | |
download | tricot-ca8c5aad2378dd9f8ec525b3b0779f5c53cfe9eb.tar.gz tricot-ca8c5aad2378dd9f8ec525b3b0779f5c53cfe9eb.zip |
Handle HTTPS targets
Diffstat (limited to 'src')
-rw-r--r-- | src/https.rs | 23 | ||||
-rw-r--r-- | src/proxy_config.rs | 8 | ||||
-rw-r--r-- | src/reverse_proxy.rs | 23 |
3 files changed, 45 insertions, 9 deletions
diff --git a/src/https.rs b/src/https.rs index e1db42e..b0d452b 100644 --- a/src/https.rs +++ b/src/https.rs @@ -79,6 +79,9 @@ async fn handle( req: Request<Body>, proxy_config: Arc<ProxyConfig>, ) -> Result<Response<Body>, anyhow::Error> { + let method = req.method().clone(); + let uri = req.uri().to_string(); + let host = if let Some(auth) = req.uri().authority() { auth.as_str() } else { @@ -89,7 +92,7 @@ async fn handle( }; let path = req.uri().path(); - let ent = proxy_config + let best_match = proxy_config .entries .iter() .filter(|ent| { @@ -111,17 +114,20 @@ async fn handle( ) }); - if let Some(proxy_to) = ent { - proxy_to.calls.fetch_add(1, Ordering::SeqCst); - let to_addr = format!("http://{}", proxy_to.target_addr); - let method = req.method().clone(); + if let Some(proxy_to) = best_match { + proxy_to.calls.fetch_add(1, Ordering::SeqCst); - let uri = req.uri().to_string(); debug!("{}{} -> {}", host, path, proxy_to); trace!("Request: {:?}", req); - let mut response = reverse_proxy::call(remote_addr.ip(), &to_addr, req).await?; + let mut response = if proxy_to.https_target { + let to_addr = format!("https://{}", proxy_to.target_addr); + reverse_proxy::call_https(remote_addr.ip(), &to_addr, req).await? + } else { + let to_addr = format!("http://{}", proxy_to.target_addr); + reverse_proxy::call(remote_addr.ip(), &to_addr, req).await? + }; for (header, value) in proxy_to.add_headers.iter() { response.headers_mut().insert( @@ -134,7 +140,8 @@ async fn handle( Ok(response) } else { - info!("Proxying {} {} -> NOT FOUND", host, path); + debug!("{}{} -> NOT FOUND", host, path); + info!("{} 404 {}", method, uri); Ok(Response::builder() .status(StatusCode::NOT_FOUND) diff --git a/src/proxy_config.rs b/src/proxy_config.rs index 8a64f53..2c55eb5 100644 --- a/src/proxy_config.rs +++ b/src/proxy_config.rs @@ -41,6 +41,7 @@ impl HostDescription { #[derive(Debug)] pub struct ProxyEntry { pub target_addr: SocketAddr, + pub https_target: bool, pub host: HostDescription, pub path_prefix: Option<String>, @@ -55,6 +56,9 @@ pub struct ProxyEntry { impl std::fmt::Display for ProxyEntry { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.https_target { + write!(f, "https://")?; + } write!(f, "{} ", self.target_addr)?; match &self.host { HostDescription::Hostname(h) => write!(f, "{}", h)?, @@ -94,7 +98,8 @@ fn parse_tricot_tag( add_headers: &[(String, String)], ) -> Option<ProxyEntry> { let splits = tag.split(' ').collect::<Vec<_>>(); - if (splits.len() != 2 && splits.len() != 3) || splits[0] != "tricot" { + if (splits.len() != 2 && splits.len() != 3) + || (splits[0] != "tricot" && splits[0] != "tricot-https") { return None; } @@ -121,6 +126,7 @@ fn parse_tricot_tag( Some(ProxyEntry { target_addr, + https_target: (splits[0] == "tricot-https"), host, path_prefix, priority, diff --git a/src/reverse_proxy.rs b/src/reverse_proxy.rs index 401f4b1..9d7780c 100644 --- a/src/reverse_proxy.rs +++ b/src/reverse_proxy.rs @@ -139,3 +139,26 @@ pub async fn call( let proxied_response = create_proxied_response(response); Ok(proxied_response) } + +pub async fn call_https( + client_ip: IpAddr, + forward_uri: &str, + request: Request<Body>, +) -> Result<Response<Body>> { + let proxied_request = create_proxied_request(client_ip, &forward_uri, request)?; + + trace!("Proxied request (HTTPS): {:?}", proxied_request); + + let https = hyper_rustls::HttpsConnectorBuilder::new() + .with_native_roots() + .https_only() + .enable_http1() + .build(); + let client: Client<_, hyper::Body> = Client::builder().build(https); + let response = client.request(proxied_request).await?; + + trace!("Inner response (HTTPS): {:?}", response); + + let proxied_response = create_proxied_response(response); + Ok(proxied_response) +} |