aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2021-12-08 22:58:19 +0100
committerAlex Auvolat <alex@adnab.me>2021-12-08 22:58:19 +0100
commitca8c5aad2378dd9f8ec525b3b0779f5c53cfe9eb (patch)
treeba5ac35eeacd9ee85363c231030313e7204ecc63
parent55f57df82e8486065bd563c21e1ea858c9f8969d (diff)
downloadtricot-ca8c5aad2378dd9f8ec525b3b0779f5c53cfe9eb.tar.gz
tricot-ca8c5aad2378dd9f8ec525b3b0779f5c53cfe9eb.zip
Handle HTTPS targets
-rw-r--r--Cargo.lock28
-rw-r--r--Cargo.toml2
-rw-r--r--src/https.rs23
-rw-r--r--src/proxy_config.rs8
-rw-r--r--src/reverse_proxy.rs23
5 files changed, 74 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 38e8c70..9f5b314 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -672,6 +672,21 @@ dependencies = [
]
[[package]]
+name = "hyper-rustls"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
+dependencies = [
+ "http 0.2.5",
+ "hyper 0.14.15",
+ "log",
+ "rustls 0.20.2",
+ "rustls-native-certs",
+ "tokio 1.14.0",
+ "tokio-rustls",
+]
+
+[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1295,6 +1310,18 @@ dependencies = [
]
[[package]]
+name = "rustls-native-certs"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943"
+dependencies = [
+ "openssl-probe",
+ "rustls-pemfile",
+ "schannel",
+ "security-framework",
+]
+
+[[package]]
name = "rustls-pemfile"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1913,6 +1940,7 @@ dependencies = [
"http 0.2.5",
"hyper 0.14.15",
"hyper-reverse-proxy",
+ "hyper-rustls",
"lazy_static",
"log",
"pretty_env_logger",
diff --git a/Cargo.toml b/Cargo.toml
index 5dca10f..aa1b4fb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,7 +25,7 @@ chrono = { version = "0.4", features = [ "serde" ] }
hyper = { version = "0.14", features = [ "full" ] }
futures-util = "0.3"
tokio-rustls = "0.23"
-#hyper-rustls = "0.23"
+hyper-rustls = "0.23"
http = "0.2"
hyper-reverse-proxy = "0.4"
unicase = "2"
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)
+}