Pular para o conteúdo
Guides 8 min de leitura 927 visualizações

Usando proxies em Rust

Este artigo detalha como integrar e usar proxies HTTP/S nas suas aplicações Rust com crates populares como reqwest e hyper, com a GProxy.

Usando proxies em Rust

Usar proxies em Rust com reqwest significa configurar um ClientBuilder com as opções de proxy, enquanto o hyper, por ser uma biblioteca HTTP de mais baixo nível, exige estabelecer a conexão manualmente através do servidor proxy.

Servidores proxy atuam como intermediários das requisições de rede, oferecendo benefícios como anonimato, acesso a conteúdo com restrição geográfica, balanceamento de carga e filtragem de tráfego. Os clientes HTTP assíncronos do Rust, reqwest e hyper, adotam abordagens diferentes para integrar proxies. O reqwest oferece suporte nativo de alto nível, já o hyper exige controle mais granular sobre o processo de conexão.

Usando proxies com reqwest

O reqwest é um cliente HTTP popular e fácil de usar para Rust, construído sobre o hyper. Ele simplifica tarefas HTTP comuns, incluindo a configuração de proxy. O ClientBuilder do reqwest traz métodos para configurar vários tipos de proxy.

Configuração do proxy

Para usar um proxy com reqwest, crie uma instância de reqwest::Client com reqwest::ClientBuilder e seu método proxy(). O método proxy() recebe um objeto reqwest::Proxy, que pode ser construído para diferentes esquemas de proxy:

  • Proxy HTTP: configurado com Proxy::http(url), para requisições HTTP simples.
  • Proxy HTTPS (método CONNECT): configurado com Proxy::https(url), para requisições HTTPS. O reqwest usa o método CONNECT para tunelar a conexão TLS pelo proxy.
  • Proxy SOCKS5: configurado com Proxy::socks5(url), para servidores proxy SOCKS5.
  • Proxy unificado: Proxy::all(url) configura um único proxy tanto para requisições HTTP quanto HTTPS.

Autenticação de proxy

Muitos servidores proxy exigem autenticação. O reqwest::Proxy suporta autenticação básica através do método basic_auth().

Suporte a variáveis de ambiente

Por padrão, o ClientBuilder do reqwest verifica automaticamente as variáveis de ambiente HTTP_PROXY, HTTPS_PROXY e NO_PROXY. Se elas estiverem definidas, o reqwest vai usá-las, a menos que sejam explicitamente sobrescritas por ClientBuilder::no_proxy() ou pela configuração de um proxy específico.

Exemplo: uso de proxy com reqwest

Este exemplo mostra como configurar o reqwest para usar proxies HTTP, HTTPS e SOCKS5, incluindo autenticação básica.

use reqwest::{Client, Error, Proxy};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Error> {
    // 1. Proxy HTTP
    let http_proxy_url = "http://user:[email protected]:8080";
    let http_client = Client::builder()
        .proxy(Proxy::http(http_proxy_url)?)
        .timeout(Duration::from_secs(10))
        .build()?;

    println!("HTTP Proxy request...");
    let http_res = http_client.get("http://httpbin.org/ip").send().await?;
    println!("HTTP Proxy Response: {:?}", http_res.text().await?);

    // 2. Proxy HTTPS (método CONNECT)
    // Nota: para HTTPS, a própria URL do proxy pode ser HTTP, mas ela tunela o tráfego HTTPS.
    let https_proxy_url = "http://user:[email protected]:8080";
    let https_client = Client::builder()
        .proxy(Proxy::https(https_proxy_url)?)
        .timeout(Duration::from_secs(10))
        .build()?;

    println!("\nHTTPS Proxy request...");
    let https_res = https_client.get("https://httpbin.org/ip").send().await?;
    println!("HTTPS Proxy Response: {:?}", https_res.text().await?);

    // 3. Proxy SOCKS5
    let socks5_proxy_url = "socks5://user:[email protected]:1080";
    let socks5_client = Client::builder()
        .proxy(Proxy::socks5(socks5_proxy_url)?)
        .timeout(Duration::from_secs(10))
        .build()?;

    println!("\nSOCKS5 Proxy request...");
    let socks5_res = socks5_client.get("http://httpbin.org/ip").send().await?;
    println!("SOCKS5 Proxy Response: {:?}", socks5_res.text().await?);

    // 4. Proxy unificado (vale para requisições HTTP e HTTPS)
    let all_proxy_url = "http://user:[email protected]:8080";
    let all_client = Client::builder()
        .proxy(Proxy::all(all_proxy_url)?)
        .timeout(Duration::from_secs(10))
        .build()?;

    println!("\nUnified Proxy (HTTP) request...");
    let all_http_res = all_client.get("http://httpbin.org/ip").send().await?;
    println!("Unified Proxy (HTTP) Response: {:?}", all_http_res.text().await?);

    println!("\nUnified Proxy (HTTPS) request...");
    let all_https_res = all_client.get("https://httpbin.org/ip").send().await?;
    println!("Unified Proxy (HTTPS) Response: {:?}", all_https_res.text().await?);

    Ok(())
}

Nota: substitua your-http-proxy.com:8080, your-https-proxy.com:8080 e your-socks5-proxy.com:1080 pelos endereços e portas reais dos servidores proxy, incluindo user:password para proxies com autenticação.

Usando proxies com hyper

O hyper é uma biblioteca HTTP de baixo nível e alto desempenho que serve de base para muitos outros crates HTTP do Rust, inclusive o reqwest. Diferente do reqwest, o hyper não oferece métodos nativos e diretos de configuração de proxy para o seu cliente. Em vez disso, usar proxy com hyper exige gerenciar manualmente a conexão TCP subjacente ou integrar crates específicos de proxy.

Gerenciamento manual da conexão

Para usar um proxy com hyper, você precisa primeiro estabelecer a conexão com o servidor proxy e depois instruir o hyper a usar essa conexão já estabelecida ou um connector personalizado que trate a lógica de proxy.

Proxy HTTP para requisições HTTP

Para requisições HTTP em texto claro através de um proxy HTTP, o cliente estabelece uma conexão TCP com o servidor proxy. Em seguida, envia a requisição HTTP diretamente ao proxy, indicando a URL completa do alvo na linha de requisição (por exemplo, GET http://target.com/path HTTP/1.1). O header Host ainda deve apontar para o servidor alvo.

Proxy HTTP para requisições HTTPS (método CONNECT)

Para requisições HTTPS, o cliente primeiro envia uma requisição HTTP CONNECT ao proxy, instruindo-o a abrir um túnel TCP até o host e a porta de destino. Assim que o proxy responde com 200 OK, o cliente faz o handshake TLS diretamente com o servidor alvo através do túnel estabelecido.

Proxy SOCKS5

Proxies SOCKS5 operam em um nível mais baixo que os proxies HTTP e suportam diversos protocolos, incluindo TCP e UDP. Integrar SOCKS5 ao hyper normalmente envolve usar uma biblioteca cliente SOCKS5 dedicada (por exemplo, tokio-socks) para estabelecer a conexão proxificada, que então é passada ao connection builder do hyper.

Exemplo: uso de proxy com hyper (proxy HTTP para HTTP)

Este exemplo mostra como fazer uma requisição HTTP básica através de um proxy HTTP usando hyper, construindo a requisição manualmente e gerenciando o stream TCP. Ele ilustra o mecanismo subjacente; para soluções robustas, considere encapsular essa lógica ou usar um connector dedicado.

use hyper::{Body, Client, Request, Uri};
use hyper::client::conn::Builder;
use tokio::net::TcpStream;
use std::str::FromStr;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let proxy_addr = "127.0.0.1:8080"; // Substitua pelo endereço do seu proxy HTTP
    let target_url = "http://httpbin.org/ip";

    println!("Connecting to proxy: {}", proxy_addr);
    let stream = TcpStream::connect(proxy_addr).await?;

    // Para proxy HTTP, conectamos ao proxy e enviamos a URI completa na requisição.
    // Não é preciso método CONNECT para alvos HTTP simples.
    let (mut sender, conn) = Builder::new()
        .http1_only(true) // Garante HTTP/1.1 para compatibilidade com proxy HTTP
        .handshake(stream)
        .await?;

    tokio::spawn(async move {
        if let Err(e) = conn.await {
            eprintln!("Connection error: {:?}", e);
        }
    });

    let req = Request::builder()
        .uri(Uri::from_str(target_url)?) // URI absoluta para encaminhamento pelo proxy HTTP
        .header("Host", "httpbin.org") // Header Host do servidor alvo
        .body(Body::empty())?;

    println!("Sending request through proxy to: {}", target_url);
    let res = sender.send(req).await?;

    println!("Response Status: {}", res.status());
    let body_bytes = hyper::body::to_bytes(res.into_body()).await?;
    println!("Response Body: {}", String::from_utf8_lossy(&body_bytes));

    Ok(())
}

Nota: este exemplo pressupõe um proxy HTTP básico que não exige autenticação e encaminha requisições HTTP diretamente. Para HTTPS ou proxies com autenticação, a lógica fica bem mais complexa, envolvendo requisições CONNECT ou bibliotecas específicas de negociação de proxy.

Usando connectors externos com hyper

Para cenários de proxy mais complexos com hyper, especialmente SOCKS5 ou proxies HTTP/HTTPS com autenticação, é comum implementar um hyper::client::connect::Connection personalizado ou usar um crate que já ofereça essa implementação. Para SOCKS5, por exemplo, o usual é usar um crate como tokio-socks para estabelecer um TcpStream proxificado via SOCKS5 e então chamar hyper::client::conn::Builder::handshake com esse stream.

reqwest vs. hyper para uso de proxy

Característica reqwest hyper
Configuração de proxy Métodos nativos de alto nível (ClientBuilder::proxy()) Implementação manual de hyper::client::connect::Connection ou integração com bibliotecas externas
Facilidade de uso Alto nível, simples para os tipos de proxy comuns Baixo nível, complexo para proxies, exige mais código repetitivo
Tipos de proxy suportados HTTP, HTTPS (CONNECT), SOCKS5 Exige tratamento manual de cada tipo; costuma usar crates externos para SOCKS5 ou autenticação complexa
Autenticação Nativa (Proxy::basic_auth()) Injeção manual de header (Proxy-Authorization) ou recursos de uma biblioteca de proxy específica
Nível de controle Moderado, abstrai os detalhes da conexão Alto, controle granular sobre conexões e detalhes do protocolo HTTP
Dependências Mais simples para proxy, o reqwest cuida da complexidade interna Pode exigir crates adicionais (tokio-socks, connectors personalizados) para lógica de proxy robusta
Caso de uso típico A maioria das aplicações que precisam de requisições HTTP com suporte a proxy, priorizando velocidade e simplicidade de desenvolvimento Construção de clientes HTTP, servidores ou componentes de rede altamente otimizados, onde o controle fino sobre as conexões é essencial

Boas práticas e considerações

Tratamento de erros

Conexões de proxy podem falhar por vários motivos (problemas de rede, proxy fora do ar, falha de autenticação). Implemente tratamento de erros robusto para as operações relacionadas a proxy, especialmente ao gerenciar conexões manualmente com hyper. O reqwest retorna reqwest::Error, que pode ser inspecionado em busca de problemas específicos de proxy.

Tipos de proxy e compatibilidade de protocolo

  • Proxies HTTP: principalmente para tráfego HTTP. Podem tunelar tráfego HTTPS pelo método CONNECT.
  • Proxies SOCKS5: agnósticos de protocolo, suportam TCP e UDP. Costumam ser preferidos para tráfego não-HTTP ou quando se busca maior grau de anonimato.
  • Garanta que o tipo de proxy configurado corresponda às capacidades do servidor proxy e ao tipo de tráfego que você pretende enviar.

Autenticação

Sempre forneça credenciais corretas para proxies com autenticação. Autenticação mal configurada é uma fonte comum de erros de conexão de proxy. No reqwest, use Proxy::basic_auth(). No hyper ou em connectors personalizados, envie o header Proxy-Authorization com as credenciais adequadas (por exemplo, username:password codificado em Base64).

Impacto no desempenho

Usar um proxy adiciona um salto extra no caminho de rede, o que pode aumentar a latência. A sobrecarga de desempenho depende da localização do servidor proxy, da sua carga e das condições de rede entre o seu cliente, o proxy e o servidor alvo.

Considerações de segurança

  • Confiança: use apenas servidores proxy confiáveis. Proxies maliciosos podem inspecionar, modificar ou registrar o seu tráfego.
  • Proxy de HTTPS: ao usar um proxy HTTPS com o método CONNECT, o proxy abre um túnel e o seu cliente faz o handshake TLS diretamente com o servidor alvo. Isso significa que o proxy não consegue descriptografar o conteúdo do seu tráfego HTTPS (a não ser que seja um proxy "man-in-the-middle" com um certificado raiz próprio instalado no seu cliente). O reqwest trata isso de forma segura por padrão.
  • Headers de proxy: proxies costumam adicionar headers como X-Forwarded-For. Fique atento a isso se o anonimato for uma preocupação central.

Interação com variáveis de ambiente

O reqwest respeita automaticamente as variáveis de ambiente HTTP_PROXY, HTTPS_PROXY e NO_PROXY. Se precisar sobrescrever esse comportamento, use ClientBuilder::no_proxy() ou configure os proxies explicitamente. Ao usar o hyper diretamente, você mesmo precisa ler e aplicar essas variáveis de ambiente, se desejar.

Atualizado: 03.03.2026
Voltar à categoria

Leia também

Experimente nossos proxies

20,000+ proxies em 100+ países do mundo

support_agent
GProxy Support
Usually replies within minutes
Hi there!
Send us a message and we'll reply as soon as possible.