#hyper #reverse-proxy #http #tokio #header #tls #https

spectacles-proxy

一个简单的反向代理,与Hyper和Tokio一起使用

1个不稳定版本

0.4.0 2019年4月13日

#55 in #reverse-proxy


用于 spectacles

Apache-2.0

11KB
117

hyper-reverse-proxy

License CI docs version

一个简单的反向代理,与Hyper一起使用。

实现确保在两个方向上正确删除端到端头部,并在X-Forwarded-For头部中添加客户端IP地址到逗号分隔的转发地址列表。

实现基于Go的httputil.ReverseProxy

示例

将这些依赖项添加到您的Cargo.toml文件中。

[dependencies]
hyper-reverse-proxy = "?"
hyper = { version = "?", features = ["full"] }
tokio = { version = "?", features = ["full"] }
lazy_static = "?"
hyper-trust-dns = { version = "?", features = [
  "rustls-http2",
  "dnssec-ring",
  "dns-over-https-rustls",
  "rustls-webpki",
  "https-only"
] }

以下示例将在127.0.0.1:13900上设置反向代理,并将这些调用代理

  • "/target/first"将被代理到http://127.0.0.1:13901

  • "/target/second"将被代理到http://127.0.0.1:13902

  • 所有其他URL将由debug_request函数处理,该函数将显示请求信息。

use hyper::server::conn::AddrStream;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server, StatusCode};
use hyper_reverse_proxy::ReverseProxy;
use hyper_trust_dns::{RustlsHttpsConnector, TrustDnsResolver};
use std::net::IpAddr;
use std::{convert::Infallible, net::SocketAddr};

lazy_static::lazy_static! {
    static ref  PROXY_CLIENT: ReverseProxy<RustlsHttpsConnector> = {
        ReverseProxy::new(
            hyper::Client::builder().build::<_, hyper::Body>(TrustDnsResolver::default().into_rustls_webpki_https_connector()),
        )
    };
}

fn debug_request(req: &Request<Body>) -> Result<Response<Body>, Infallible> {
    let body_str = format!("{:?}", req);
    Ok(Response::new(Body::from(body_str)))
}

async fn handle(client_ip: IpAddr, req: Request<Body>) -> Result<Response<Body>, Infallible> {
    if req.uri().path().starts_with("/target/first") {
        match PROXY_CLIENT.call(client_ip, "http://127.0.0.1:13901", req)
            .await
        {
            Ok(response) => {
                Ok(response)
            },
            Err(_error) => {
                Ok(Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(Body::empty())
                .unwrap())},
        }
    } else if req.uri().path().starts_with("/target/second") {
        match PROXY_CLIENT.call(client_ip, "http://127.0.0.1:13902", req)
            .await
        {
            Ok(response) => Ok(response),
            Err(_error) => Ok(Response::builder()
                .status(StatusCode::INTERNAL_SERVER_ERROR)
                .body(Body::empty())
                .unwrap()),
        }
    } else {
        debug_request(&req)
    }
}

#[tokio::main]
async fn main() {
    let bind_addr = "127.0.0.1:8000";
    let addr: SocketAddr = bind_addr.parse().expect("Could not parse ip:port.");

    let make_svc = make_service_fn(|conn: &AddrStream| {
        let remote_addr = conn.remote_addr().ip();
        async move { Ok::<_, Infallible>(service_fn(move |req| handle(remote_addr, req))) }
    });

    let server = Server::bind(&addr).serve(make_svc);

    println!("Running server on {:?}", addr);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

关于安全性的话

处理发出的请求可能是一个安全噩梦。这个crate不控制发出的请求客户端,因为它需要提供给代理调用。以下章节可能会给您一个关于如何使用hyper-trust-dns crate来保护您的客户端的概述。

您可以在示例中看到它们的使用。

HTTPS

您应该使用安全传输,以便知道您在跟谁说话,并且可以信任连接。默认情况下,hyper-trust-dns启用了功能标志https-only,如果提供的是不是https的传输方案,则会引发恐慌。这是一个健康的默认值,因为它不仅需要您信任来源,还需要其他人信任在未加密连接上看到的内容。

注意:如果您正在运行主机,其中证书存储中添加了证书,请确保定期审计它们,以确保您的客户端不会将旧证书或恶意证书视为有效。

TLS 1.2

默认情况下,禁用了 tls 1.2,以启用 tls 1.3,因为许多 tls 1.2 的部分可能被视为攻击友好。由于并非所有服务都支持它,可以通过 rustls-tls-12 功能启用 tls 1.2

注意:请确保定期审计您连接到的服务

DNSSEC

从安全角度来看,默认情况下,DNS查询和条目不是“可信”的。 DNSSEC 为验证添加了一个新的加密层。要启用它,请使用 dnssec-ring 功能。

HTTP/2

默认情况下,只启用了 rustlss 的 http1 功能以用于 DNS 查询。虽然 http/3 可能就在眼前。可以通过 rustls-http2 功能启用 http/2 支持。

DoT & DoH

DoT 和 DoH 为您提供与 DNS 之间的安全传输。

默认情况下,它们都不启用。如果您想启用它们,可以使用 dohdot 功能。

建议

  • 如果您需要监控与访问端口相关的网络活动,请使用具有 dns-over-rustls 功能标志的 DoT。
  • 如果您在野外并且没有根据端口监控的需求,请使用具有 dns-over-https-rustls 功能标志的 DoH,因为它将与其他 https 流量混合。

强烈建议使用其中之一。

目前仅包括 DNS 查询作为 esniech 仍在 ietf 中为草案的原因。

依赖关系

~7–17MB
~220K SLoC