forked from Deuxfleurs/tricot
Support totally ignoring backend HTTPS certificate stuff
This commit is contained in:
parent
ca8c5aad23
commit
207f467b87
6 changed files with 117 additions and 12 deletions
|
@ -19,7 +19,7 @@ serde_json = "1.0.53"
|
|||
tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "time", "macros", "sync", "signal", "fs"] }
|
||||
bytes = "1"
|
||||
acme-micro = "0.12"
|
||||
rustls = "0.20"
|
||||
rustls = { version = "0.20", features = [ "dangerous_configuration" ] }
|
||||
rustls-pemfile = "0.2"
|
||||
chrono = { version = "0.4", features = [ "serde" ] }
|
||||
hyper = { version = "0.14", features = [ "full" ] }
|
||||
|
|
|
@ -18,6 +18,6 @@ COPY ./src ./src
|
|||
RUN cargo build --release
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
RUN apt-get update && apt-get install -y libssl1.1 iptables
|
||||
RUN apt-get update && apt-get install -y libssl1.1 iptables ca-certificates
|
||||
COPY --from=builder /srv/target/release/tricot /usr/local/sbin/tricot
|
||||
CMD ["/usr/local/sbin/tricot"]
|
||||
|
|
|
@ -56,8 +56,8 @@ impl CertStore {
|
|||
}
|
||||
}
|
||||
|
||||
debug!("Ensuring we have certs for domains: {:#?}", domains);
|
||||
for dom in domains.iter() {
|
||||
info!("Ensuring we have certs for domains: {:?}", domains);
|
||||
if let Err(e) = self.get_cert(dom).await {
|
||||
warn!("Error get_cert {}: {}", dom, e);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use futures::TryFutureExt;
|
|||
use std::net::SocketAddr;
|
||||
use structopt::StructOpt;
|
||||
|
||||
mod tls_util;
|
||||
mod cert;
|
||||
mod cert_store;
|
||||
mod consul;
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
//! Copied from https://github.com/felipenoris/hyper-reverse-proxy
|
||||
//! See there for original Copyright notice
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::convert::TryInto;
|
||||
use std::time::SystemTime;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use log::*;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use http::header::HeaderName;
|
||||
use hyper::header::{HeaderMap, HeaderValue};
|
||||
use hyper::{Body, Client, Request, Response, Uri};
|
||||
use rustls::{Certificate, ServerName};
|
||||
use rustls::client::{ServerCertVerifier, ServerCertVerified};
|
||||
use lazy_static::lazy_static;
|
||||
use std::net::IpAddr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::tls_util::HttpsConnectorFixedDnsname;
|
||||
|
||||
fn is_hop_header(name: &str) -> bool {
|
||||
use unicase::Ascii;
|
||||
|
@ -149,12 +156,12 @@ pub async fn call_https(
|
|||
|
||||
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 tls_config = rustls::client::ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_custom_certificate_verifier(Arc::new(DontVerifyServerCert))
|
||||
.with_no_client_auth();
|
||||
let connector = HttpsConnectorFixedDnsname::new(tls_config, "dummy");
|
||||
let client: Client<_, hyper::Body> = Client::builder().build(connector);
|
||||
let response = client.request(proxied_request).await?;
|
||||
|
||||
trace!("Inner response (HTTPS): {:?}", response);
|
||||
|
@ -162,3 +169,21 @@ pub async fn call_https(
|
|||
let proxied_response = create_proxied_response(response);
|
||||
Ok(proxied_response)
|
||||
}
|
||||
|
||||
struct DontVerifyServerCert;
|
||||
|
||||
impl ServerCertVerifier for DontVerifyServerCert {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
_end_entity: &Certificate,
|
||||
_intermediates: &[Certificate],
|
||||
_server_name: &ServerName,
|
||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
||||
_ocsp_response: &[u8],
|
||||
_now: SystemTime
|
||||
) -> Result<ServerCertVerified, rustls::Error> {
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
79
src/tls_util.rs
Normal file
79
src/tls_util.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
use core::future::Future;
|
||||
use core::task::{Context, Poll};
|
||||
use std::convert::TryFrom;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::io;
|
||||
|
||||
use futures_util::future::*;
|
||||
use rustls::ServerName;
|
||||
use hyper::client::connect::Connection;
|
||||
use hyper::client::HttpConnector;
|
||||
use hyper::service::Service;
|
||||
use hyper::Uri;
|
||||
use hyper_rustls::MaybeHttpsStream;
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
use tokio_rustls::TlsConnector;
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HttpsConnectorFixedDnsname<T> {
|
||||
http: T,
|
||||
tls_config: Arc<rustls::ClientConfig>,
|
||||
fixed_dnsname: &'static str,
|
||||
}
|
||||
type BoxError = Box<dyn std::error::Error + Send + Sync>;
|
||||
impl HttpsConnectorFixedDnsname<HttpConnector> {
|
||||
pub fn new(mut tls_config: rustls::ClientConfig, fixed_dnsname: &'static str) -> Self {
|
||||
let mut http = HttpConnector::new();
|
||||
http.enforce_http(false);
|
||||
tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
||||
Self {
|
||||
http,
|
||||
tls_config: Arc::new(tls_config),
|
||||
fixed_dnsname,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> Service<Uri> for HttpsConnectorFixedDnsname<T>
|
||||
where
|
||||
T: Service<Uri>,
|
||||
T::Response: Connection + AsyncRead + AsyncWrite + Send + Unpin + 'static,
|
||||
T::Future: Send + 'static,
|
||||
T::Error: Into<BoxError>,
|
||||
{
|
||||
type Response = MaybeHttpsStream<T::Response>;
|
||||
type Error = BoxError;
|
||||
#[allow(clippy::type_complexity)]
|
||||
type Future =
|
||||
Pin<Box<dyn Future<Output = Result<MaybeHttpsStream<T::Response>, BoxError>> + Send>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
match self.http.poll_ready(cx) {
|
||||
Poll::Ready(Ok(())) => Poll::Ready(Ok(())),
|
||||
Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
|
||||
fn call(&mut self, dst: Uri) -> Self::Future {
|
||||
let is_https = dst.scheme_str() == Some("https");
|
||||
assert!(is_https);
|
||||
|
||||
let cfg = self.tls_config.clone();
|
||||
let connecting_future = self.http.call(dst);
|
||||
let dnsname =
|
||||
ServerName::try_from(self.fixed_dnsname).expect("Invalid fixed dnsname");
|
||||
let f = async move {
|
||||
let tcp = connecting_future.await.map_err(Into::into)?;
|
||||
let connector = TlsConnector::from(cfg);
|
||||
let tls = connector
|
||||
.connect(dnsname, tcp)
|
||||
.await
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
Ok(MaybeHttpsStream::Https(tls))
|
||||
};
|
||||
f.boxed()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in a new issue