good_mitm_core/
lib.rs

1use error::Error;
2use handler::{CustomContextData, HttpHandler, MitmFilter};
3use http_client::gen_client;
4use hyper_proxy::Proxy as UpstreamProxy;
5use mitm::MitmProxy;
6use std::{future::Future, marker::PhantomData, net::SocketAddr, sync::Arc};
7use tokio::net::TcpListener;
8use typed_builder::TypedBuilder;
9
10pub use ca::CertificateAuthority;
11pub use hyper;
12pub use rcgen;
13pub use tokio_rustls;
14
15mod ca;
16mod error;
17pub mod handler;
18mod http_client;
19pub mod mitm;
20
21#[derive(TypedBuilder)]
22pub struct Proxy<F, H, D>
23where
24    F: Future<Output = ()>,
25    H: HttpHandler<D>,
26    D: CustomContextData,
27{
28    /// The address to listen on.
29    pub listen_addr: SocketAddr,
30    /// A future that once resolved will cause the proxy server to shut down.
31    pub shutdown_signal: F,
32    /// The certificate authority to use.
33    pub ca: CertificateAuthority,
34    pub upstream_proxy: Option<UpstreamProxy>,
35
36    pub mitm_filters: Vec<String>,
37    pub handler: H,
38
39    #[builder(default)]
40    _custom_contex_data: PhantomData<D>,
41}
42
43impl<F, H, D> Proxy<F, H, D>
44where
45    F: Future<Output = ()>,
46    H: HttpHandler<D>,
47    D: CustomContextData,
48{
49    pub async fn start_proxy(self) -> Result<(), Error> {
50        let client = gen_client(self.upstream_proxy)?;
51        let ca = Arc::new(self.ca);
52        let http_handler = Arc::new(self.handler);
53        let mitm_filter = Arc::new(MitmFilter::new(self.mitm_filters));
54
55        let tcp_listener = TcpListener::bind(self.listen_addr).await?;
56        loop {
57            let client = client.clone();
58            let ca = Arc::clone(&ca);
59            let http_handler = Arc::clone(&http_handler);
60            let mitm_filter = Arc::clone(&mitm_filter);
61
62            if let Ok((tcp_stream, _)) = tcp_listener.accept().await {
63                tokio::spawn(async move {
64                    let mitm_proxy = MitmProxy {
65                        ca: ca.clone(),
66                        client: client.clone(),
67                        http_handler: Arc::clone(&http_handler),
68                        mitm_filter: Arc::clone(&mitm_filter),
69                        custom_contex_data: Default::default(),
70                    };
71
72                    let mut tls_content_type = [0; 1];
73                    if tcp_stream.peek(&mut tls_content_type).await.is_ok() {
74                        if tls_content_type[0] <= 0x40 {
75                            // ASCII < 'A', assuming tls
76                            mitm_proxy.serve_tls(tcp_stream).await;
77                        } else {
78                            // assuming http
79                            _ = mitm_proxy.serve_stream(tcp_stream).await;
80                        }
81                    }
82                });
83            }
84        }
85    }
86}