slinger_mitm/
proxy.rs

1//! MITM Proxy configuration and main proxy implementation
2
3use crate::ca::CertificateManager;
4use crate::error::Result;
5use crate::interceptor::InterceptorHandler;
6use crate::server::ProxyServer;
7use slinger::Proxy;
8use std::path::PathBuf;
9use std::sync::Arc;
10use tokio::sync::RwLock;
11
12/// Configuration for MITM proxy
13#[derive(Clone)]
14pub struct MitmConfig {
15  /// Path to store CA certificates
16  pub ca_storage_path: PathBuf,
17  /// Enable HTTPS interception
18  pub enable_https_interception: bool,
19  /// Maximum concurrent connections
20  pub max_connections: usize,
21  /// Connection timeout in seconds
22  pub connection_timeout: u64,
23  /// Optional upstream proxy (supports HTTP, HTTPS, SOCKS5, SOCKS5h)
24  /// Example: "<socks5h://127.0.0.1:1080>" or "<http://proxy.example.com:8080>"
25  pub upstream_proxy: Option<Proxy>,
26}
27
28impl Default for MitmConfig {
29  fn default() -> Self {
30    Self {
31      ca_storage_path: PathBuf::from(".slinger-mitm"),
32      enable_https_interception: true,
33      max_connections: 1000,
34      connection_timeout: 30,
35      upstream_proxy: None,
36    }
37  }
38}
39
40/// MITM Proxy main struct
41pub struct MitmProxy {
42  config: MitmConfig,
43  cert_manager: Arc<CertificateManager>,
44  interceptor_handler: Arc<RwLock<InterceptorHandler>>,
45}
46
47impl MitmProxy {
48  /// Create a new MITM proxy with the given configuration
49  pub async fn new(config: MitmConfig) -> Result<Self> {
50    let cert_manager = Arc::new(CertificateManager::new(&config.ca_storage_path).await?);
51    let interceptor_handler = Arc::new(RwLock::new(InterceptorHandler::new()));
52
53    Ok(Self {
54      config,
55      cert_manager,
56      interceptor_handler,
57    })
58  }
59
60  /// Create a new MITM proxy with default configuration
61  pub async fn default() -> Result<Self> {
62    Self::new(MitmConfig::default()).await
63  }
64
65  /// Get the CA certificate in PEM format
66  ///
67  /// This certificate should be installed in the client's trust store
68  pub fn ca_cert_pem(&self) -> Result<String> {
69    self.cert_manager.ca_cert_pem()
70  }
71
72  /// Get the CA certificate path
73  pub fn ca_cert_path(&self) -> PathBuf {
74    self.cert_manager.ca_cert_path()
75  }
76
77  /// Get a reference to the interceptor handler
78  pub fn interceptor_handler(&self) -> Arc<RwLock<InterceptorHandler>> {
79    self.interceptor_handler.clone()
80  }
81
82  /// Start the MITM proxy server on the given address
83  pub async fn start(&self, addr: &str) -> Result<()> {
84    let server = ProxyServer::new(
85      self.config.clone(),
86      self.cert_manager.clone(),
87      self.interceptor_handler.clone(),
88    )?;
89    server.run(addr).await
90  }
91}
92
93#[cfg(test)]
94mod tests {
95  use super::*;
96
97  #[tokio::test]
98  async fn test_mitm_proxy_creation() {
99    let config = MitmConfig {
100      ca_storage_path: PathBuf::from("/tmp/test-mitm-ca"),
101      ..Default::default()
102    };
103
104    let proxy = MitmProxy::new(config).await;
105    assert!(proxy.is_ok());
106
107    if let Ok(p) = proxy {
108      let ca_pem = p.ca_cert_pem();
109      assert!(ca_pem.is_ok());
110    }
111  }
112}