From 3491b80142aa45a56709531fe85fdc51a8d045c2 Mon Sep 17 00:00:00 2001 From: Jun Kurihara Date: Tue, 28 Jun 2022 11:51:38 -0400 Subject: [PATCH] add feature to specify default backend --- bench/rpxy.toml | 1 + config-example.toml | 7 +++++++ src/backend.rs | 5 +++++ src/config/parse.rs | 16 ++++++++++++++-- src/config/toml.rs | 1 + src/main.rs | 15 ++++++++++++--- src/proxy/proxy_handler.rs | 5 ++++- src/proxy/proxy_main.rs | 8 ++++---- src/proxy/proxy_tls.rs | 4 ++-- 9 files changed, 50 insertions(+), 12 deletions(-) diff --git a/bench/rpxy.toml b/bench/rpxy.toml index 1c075ab..682863e 100644 --- a/bench/rpxy.toml +++ b/bench/rpxy.toml @@ -5,6 +5,7 @@ listen_ipv6 = false max_concurrent_streams = 128 max_clients = 512 +default_app = 'localhost' # passing through 127.0.0.1 [apps] diff --git a/config-example.toml b/config-example.toml index 2465d1f..6871cdd 100644 --- a/config-example.toml +++ b/config-example.toml @@ -15,6 +15,13 @@ max_clients = 512 listen_ipv6 = false +# App that serves all plaintext http request by referring to HOSTS or request header +# execpt for configured application. +# Note that this is only for http. +# Note that nothing is served for requests via https since secure channel cannot be +# established for unconfigured server_name, and they are always rejected by checking SNI. +default_app = 'another_localhost' + ################################### # Backend settings # ################################### diff --git a/src/backend.rs b/src/backend.rs index e67f80e..a09c937 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -12,6 +12,11 @@ use std::{ }; use tokio_rustls::rustls::{Certificate, PrivateKey, ServerConfig}; +pub struct Backends { + pub apps: HashMap, // TODO: hyper::uriで抜いたhostで引っ掛ける。Stringでいいのか? + pub default_app: Option, // for plaintext http +} + pub struct Backend { pub app_name: String, pub server_name: String, diff --git a/src/config/parse.rs b/src/config/parse.rs index ee89024..54c0155 100644 --- a/src/config/parse.rs +++ b/src/config/parse.rs @@ -7,7 +7,7 @@ use std::{collections::HashMap, sync::Mutex}; // #[cfg(feature = "tls")] use std::path::PathBuf; -pub fn parse_opts(globals: &mut Globals, backends: &mut HashMap) -> Result<()> { +pub fn parse_opts(globals: &mut Globals, backends: &mut Backends) -> Result<()> { let _ = include_str!("../../Cargo.toml"); let options = clap::command!().arg( Arg::new("config_file") @@ -110,7 +110,7 @@ pub fn parse_opts(globals: &mut Globals, backends: &mut HashMap ensure!(app.reverse_proxy.is_some(), "Missing reverse_proxy"); let reverse_proxy = get_reverse_proxy(app.reverse_proxy.as_ref().unwrap())?; - backends.insert( + backends.apps.insert( server_name.to_owned(), Backend { app_name: app_name.to_owned(), @@ -125,6 +125,18 @@ pub fn parse_opts(globals: &mut Globals, backends: &mut HashMap ); info!("Registering application: {} ({})", app_name, server_name); } + + // default backend application for plaintext http requests + if let Some(d) = config.default_app { + if backends.apps.contains_key(&d) { + info!( + "Serving plaintext http for requests to unconfigured server_name: {}.", + d + ); + } + backends.default_app = Some(d); + } + Ok(()) } diff --git a/src/config/toml.rs b/src/config/toml.rs index e57916e..230c025 100644 --- a/src/config/toml.rs +++ b/src/config/toml.rs @@ -10,6 +10,7 @@ pub struct ConfigToml { pub max_concurrent_streams: Option, pub max_clients: Option, pub apps: Option, + pub default_app: Option, } #[derive(Deserialize, Debug, Default)] diff --git a/src/main.rs b/src/main.rs index 74287b2..fa9640f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,13 @@ mod log; mod proxy; use crate::{ - backend::Backend, config::parse_opts, constants::*, error::*, globals::*, log::*, proxy::Proxy, + backend::{Backend, Backends}, + config::parse_opts, + constants::*, + error::*, + globals::*, + log::*, + proxy::Proxy, }; use futures::future::select_all; use hyper::Client; @@ -55,7 +61,10 @@ fn main() { runtime_handle: runtime.handle().clone(), }; - let mut backends: HashMap = HashMap::new(); + let mut backends = Backends { + default_app: None, + apps: HashMap::::new(), + }; let _ = parse_opts(&mut globals, &mut backends).expect("Invalid configuration"); @@ -67,7 +76,7 @@ fn main() { } // entrypoint creates and spawns tasks of proxy services -async fn entrypoint(globals: Arc, backends: Arc>) -> Result<()> { +async fn entrypoint(globals: Arc, backends: Arc) -> Result<()> { let connector = TrustDnsResolver::default().into_rustls_webpki_https_connector(); let forwarder = Arc::new(Client::builder().build::<_, hyper::Body>(connector)); diff --git a/src/proxy/proxy_handler.rs b/src/proxy/proxy_handler.rs index 26ce6a4..c73e003 100644 --- a/src/proxy/proxy_handler.rs +++ b/src/proxy/proxy_handler.rs @@ -39,8 +39,11 @@ where } else { return http_error(StatusCode::SERVICE_UNAVAILABLE); }; - let backend = if let Some(be) = self.backends.get(server_name.as_str()) { + let backend = if let Some(be) = self.backends.apps.get(server_name.as_str()) { be + } else if let Some(default_be) = &self.backends.default_app { + debug!("Serving by default app: {}", default_be); + self.backends.apps.get(default_be).unwrap() } else { return http_error(StatusCode::SERVICE_UNAVAILABLE); }; diff --git a/src/proxy/proxy_main.rs b/src/proxy/proxy_main.rs index cdf0bfb..b46e88c 100644 --- a/src/proxy/proxy_main.rs +++ b/src/proxy/proxy_main.rs @@ -1,9 +1,9 @@ // use super::proxy_handler::handle_request; -use crate::{backend::Backend, error::*, globals::Globals, log::*}; +use crate::{backend::Backends, error::*, globals::Globals, log::*}; use hyper::{ client::connect::Connect, server::conn::Http, service::service_fn, Body, Client, Request, }; -use std::{collections::HashMap, net::SocketAddr, sync::Arc}; +use std::{net::SocketAddr, sync::Arc}; use tokio::{ io::{AsyncRead, AsyncWrite}, net::TcpListener, @@ -38,8 +38,8 @@ where T: Connect + Clone + Sync + Send + 'static, { pub listening_on: SocketAddr, - pub tls_enabled: bool, // TCP待受がTLSかどうか - pub backends: Arc>, // TODO: hyper::uriで抜いたhostで引っ掛ける。Stringでいいのか? + pub tls_enabled: bool, // TCP待受がTLSかどうか + pub backends: Arc, pub forwarder: Arc>, pub globals: Arc, } diff --git a/src/proxy/proxy_tls.rs b/src/proxy/proxy_tls.rs index 6e539d9..b8f939f 100644 --- a/src/proxy/proxy_tls.rs +++ b/src/proxy/proxy_tls.rs @@ -17,7 +17,7 @@ where let cert_service = async { info!("Start cert watch service for {}", self.listening_on); loop { - for (server_name, backend) in self.backends.iter() { + for (server_name, backend) in self.backends.apps.iter() { if backend.tls_cert_key_path.is_some() && backend.tls_cert_path.is_some() { if let Err(_e) = backend.update_server_config().await { warn!("Failed to update certs for {}", server_name); @@ -53,7 +53,7 @@ where info!("No SNI in ClientHello"); continue; }; - let backend_serve = if let Some(backend_serve) = self.backends.get(svn){ + let backend_serve = if let Some(backend_serve) = self.backends.apps.get(svn){ backend_serve } else { info!("No configuration for the server name {} given in client_hello", svn);