softprops / hyperlocal

🔌 ✨rustlang hyper bindings for local unix domain sockets
MIT License
227 stars 46 forks source link

Incorrect Host header is set #30

Open kornelski opened 4 years ago

kornelski commented 4 years ago

Requests made via hyperlocal have a Host header with a hostname of the "fake" socket URL, rather than the original hostname of the URL being wrapped, e.g.

Host: 2f7661722f666f6c646572732f31332f633839683062316e376e64326c7432733433675f64765f3830303030676e2f542f2e746d706265417941472f746573742e736f636b:0

instead of

Host: example.com
onalante-msft commented 2 years ago

If by "wrapped" you mean something like socat UNIX-LISTEN:... TCP:example.com:80, there is no way for hyperlocal to know what the underlying host should be if you are using a client directly connected to the wrapping socket. You could manually set the "Host" header if you really needed this method.

You could alternatively use hyperlocal::UnixConnector together with hyper-proxy to tunnel requests through your wrapping socket. This would still require coordination of the socket forwarding and request URIs when using socat or the like, but it would automatically set the host on the request, at least.

use hyper::{Body, Client};
use hyperlocal::{UnixConnector, Uri};
use hyper_proxy::{Proxy, ProxyConnector, Intercept};

#[tokio::main(flavor = "current_thread")]
async fn main() {
    let tunnel = {
        // $ socat UNIX-LISTEN:foo.sock,fork TCP:google.com:80
        let uri = Uri::new("foo.sock", "/").into();
        let proxy = Proxy::new(Intercept::All, uri);
        ProxyConnector::from_proxy(UnixConnector, proxy).unwrap()
    };

    let client: Client<_, Body> = Client::builder().build(tunnel);

    let res = client.get("http://google.com".parse().unwrap()).await.unwrap();

    println!("{}", std::str::from_utf8(&hyper::body::to_bytes(res.into_body()).await.unwrap()).unwrap());
}