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