Project Goal:
Build a user-space forward proxy in Rust that can accept HTTP and HTTPS (via CONNECT) requests, forward them to the destination server, and optionally block requests based on a configurable blacklist. The blacklist now supports both domain-level and path-level blocking (e.g., block example.com/subfolder but allow example.com).
- HTTP Proxy: Handles standard HTTP methods (
GET,POST, etc.). Parses requests, forwards them, and relays responses. - HTTPS Proxy (CONNECT method): Handles
CONNECTrequests to establish a raw TCP tunnel between the client and the destination. - Blacklisting: Blocks connections to specific domains, IP addresses, or specific paths under a domain.
- Logging: Provides detailed logs for debugging and operational insight.
- Initializes the
tokioruntime and logging. - Parses command-line arguments (proxy listen address/port, path to blacklist file).
- Loads the initial blacklist.
- Creates and starts the
ProxyServer.
ProxyServerstruct: Holds configuration (listen address, port, reference toBlacklistManager).run()method:- Binds a
tokio::net::TcpListenerto the configured address/port. - Accepts incoming client connections in an async loop.
- Spawns a new
tokio::taskfor each connection, callinghandle_client.
- Binds a
handle_client(mut client_stream: TcpStream, blacklist_manager: Arc<BlacklistManager>)async function:- Reads and parses the HTTP request from the client.
- Extracts the HTTP method, URI, headers, and path.
- Blacklist Check:
- Extracts the target host and path from the request.
- Calls
blacklist_manager.is_blocked(target_host, path). - If blocked: Logs the block, returns a "403 Forbidden" HTTP response (for HTTP) or closes the connection (for HTTPS
CONNECT), and returns.
- Establishes Upstream Connection:
- If not blocked, connects to the target server using
tokio::net::TcpStream::connect().
- If not blocked, connects to the target server using
- Forwarding Logic:
CONNECTMethod (HTTPS Tunnel):- Sends "HTTP/1.1 200 Connection Established\r\n\r\n" to the client.
- Uses
tokio::io::copy()to shuttle bytes betweenclient_streamandupstream_streamin both directions, creating a raw TCP tunnel.
- Other HTTP Methods:
- Forwards the original client request bytes to the
upstream_stream. - Reads the response from
upstream_stream. - Forwards the response bytes back to
client_stream. - Handles connection closing after one request/response cycle for simplicity.
- Forwards the original client request bytes to the
-
BlacklistManagerstruct:- Holds two data structures:
blocked_domains: HashSet<String>for domain/IP blocking.blocked_paths: HashSet<(String, String)>for domain+path blocking.
- Thread-safe via
RwLock.
- Holds two data structures:
-
new(path: &str)method: Loads rules from a specified file. -
is_blocked(host: &str, path: &str)method:
Checks if the given host (domain or IP string) or host+path matches any rule in the blacklist.- Supports:
- Domain/IP blocking (e.g.,
example.com) - Path-based blocking (e.g.,
example.com/subfolder) - Subdomain matching (e.g., blocking
example.comalso blockssub.example.com)
- Domain/IP blocking (e.g.,
- Supports:
-
Blacklist File Format:
-
Each line is either a domain/IP or a domain+path (e.g.,
example.com/subfolder). -
Lines starting with
#are comments. -
Examples:
# Block all of example.com example.com # Block only /subfolder on example.com example.com/subfolder # Block an IP 192.168.1.100
-
tokio: Asynchronous runtime for non-blocking I/O and task spawning.httparse: Efficient, low-level parsing of HTTP requests from raw bytes.log&env_logger: Logging.clap: Command-line argument parsing.anyhow/thiserror: Ergonomic error handling.url: URL parsing and manipulation.trust-dns-resolver: (Optional) For IP-based blacklist checks.tokio-rustls: (Optional) For advanced HTTPS handling (not required for basic CONNECT tunneling).
- Custom
ProxyErrorenum covers:- I/O errors
- HTTP request parse errors
- Bad HTTP requests
- Upstream connection errors
- Blacklist errors
- Invalid URIs
- All fallible functions return
Result<T, ProxyError>. - Errors are logged with context.
-
Cargo.tomlSetup:
Add dependencies:tokio,httparse,log,env_logger,clap,anyhow,url. -
Blacklist File:
Create a blacklist file (e.g.,blacklist.txt) with entries as described above. -
Run the Proxy:
cargo run -- --listen 127.0.0.1:8080 --blacklist blacklist.txt
-
Configure Your Browser or HTTP Client:
Set the proxy to127.0.0.1:8080. -
Test Blacklisting:
- Requests to blacklisted domains or paths will be blocked with a 403 (HTTP) or closed tunnel (HTTPS).
- All other requests will be forwarded.
- To block all of
example.com:example.com - To block only
example.com/subfolderbut allow the rest ofexample.com:example.com/subfolder - To block an IP:
192.168.1.100
- Add support for wildcards or regex in blacklist rules.
- Implement dynamic blacklist updates (add/remove rules at runtime).
- Add metrics or a web UI for monitoring.
This proxy does not decrypt HTTPS traffic (no MITM). It only tunnels encrypted bytes for HTTPS via the CONNECT method.
MIT or Apache-2.0 (choose your preferred license).