#Hyper Reverse Proxy

4 messages · Page 1 of 1 (latest)

frank willow
#

I'm having trouble terminating the TLS when I'm trying to rotue HTTPS incomming requests to an HTTP server, here is the code:

#
impl ProxyHandler {
    pub fn new(balancer: Arc<dyn LoadBalancer>) -> Self {
        let connector = HttpConnector::new();

        Self {
            client: Client::builder(TokioExecutor::new()).build(connector),
            load_balancer: balancer,
        }
    }

    pub async fn handle(&self, req: Request<Body>) -> Response<Body> {
        ... // next message
    }

    async fn forward_request(&self, mut req: Request<Body>, uri: Uri) -> Result<Response<Body>, StatusCode> {
        *req.uri_mut() = uri;
        Ok(self.client
            .request(req)
            .await
            .map_err(|e| {
                log::error!("Error forwarding request: {:?}", e);
                StatusCode::BAD_REQUEST
            })?
            .into_response())
    }
}

#
pub async fn handle(&self, req: Request<Body>) -> Response<Body> {
        let timeout_duration = std::time::Duration::from_secs(5);

        let selected_lb = self.load_balancer.next().await;


        match selected_lb {
            Some(lb ) => {
                let uri = self.build_backend_uri(&req, &lb.server);

                match timeout(timeout_duration, self.forward_request(req, uri)).await {
                    Ok(Ok(mut response)) => {
                        log::trace!("Response recieved: {:?}", response);
                        response.extensions_mut().insert(lb);

                        response
                    },
                    Ok(Err(e)) => {
                        Response::builder()
                            .status(e)
                            .body(Body::from("Bad request"))
                            .unwrap()
                    },
                    Err(_) => {
                        log::warn!("Request to backend timed out");

                        Response::builder()
                        .status(504)
                        .body(Body::from("Gateway Timeout"))
                        .unwrap()
                    }
                }
            },
            None => {
                Response::builder()
                    .status(503)
                    .body(Body::from("Service Unavailable"))
                    .unwrap()
            }
        }
    }
#

Here is my https server:

pub async fn start_https_server(mut app: Router, tcp_listener: TcpListener) -> Result<(), Box<dyn std::error::Error>> {
    let rustls_config =  rustls_server_config(
      PathBuf::from("certs/key.pem"),
        PathBuf::from("certs/cert.pem"),  
    )?;

    let tls_acceptor = TlsAcceptor::from(rustls_config);

    Pin::new(&mut app);
    loop {
        let tower_service: Router = app.clone();
        let tls_acceptor = tls_acceptor.clone();
        
        let (cnx, addr) = tcp_listener.accept().await.unwrap();
    
        tokio::spawn(async move {
            let Ok(stream) = tls_acceptor.accept(cnx).await else {
                log::error!("Error during tls handshake connection from {}", addr);
                return;
            };

            let stream = TokioIo::new(stream);

            let hyper_service = hyper::service::service_fn(move |request: Request<Incoming>| {
                tower_service.clone().oneshot(request)
            });

            let ret = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new())
                .serve_connection_with_upgrades(stream, hyper_service)
                .await;

            if let Err(err) = ret {
                log::warn!("eError serving connection from {}: {}", addr, err);
            }
        });
    }
}