Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example to use trust-dns-resolver as DNS backend #81

Open
hermantolim opened this issue Aug 25, 2019 · 5 comments
Open

Example to use trust-dns-resolver as DNS backend #81

hermantolim opened this issue Aug 25, 2019 · 5 comments

Comments

@hermantolim
Copy link

is ther an example to use the HttpsConnector with trust-dns-resolver?

@cpu
Copy link
Member

cpu commented Mar 31, 2023

There isnt'! Would you be interested in providing one?

@CalderWhite
Copy link

Hey, I'm currently working on this. The only thing blocking me is going from having a use mio::net::TcpStream and rustls::ClientConnection to creating an HttpsConnector.

@CalderWhite
Copy link

For anyone who is interested, I think using tokio-rustls in conjunction with hyper is the way to go.

Here's a quick program to get you started:

use std::{
    net::{Ipv4Addr, SocketAddr, SocketAddrV4},
    sync::Arc,
    time::Instant,
};

use http_body_util::{BodyExt, Empty};
use hyper::{body::Bytes, Request};
use tokio::{
    io::{self, AsyncWriteExt},
    net::TcpStream,
};
use tokio_rustls::rustls::{ClientConfig, OwnedTrustAnchor, RootCertStore, ServerName};
use tokio_rustls::TlsConnector;

async fn async_request(ip: Ipv4Addr, domain: &str, url: &str) {
    let mut root_cert_store = RootCertStore::empty();
    root_cert_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
        OwnedTrustAnchor::from_subject_spki_name_constraints(
            ta.subject,
            ta.spki,
            ta.name_constraints,
        )
    }));
    let config = ClientConfig::builder()
        .with_safe_defaults()
        .with_root_certificates(root_cert_store)
        .with_no_client_auth();
    let connector = TlsConnector::from(Arc::new(config));
    let dnsname = ServerName::try_from(domain).unwrap();

    let addr = SocketAddr::V4(SocketAddrV4::new(ip, 443));
    let stream = TcpStream::connect(&addr).await.expect("Could not connect");
    let mut stream = connector
        .connect(dnsname, stream)
        .await
        .expect("Could not connect connector?");

    let (mut request_sender, connection) = hyper::client::conn::http1::handshake(stream)
        .await
        .expect("Could not perform http1 handshake");

    // spawn a task to poll the connection and drive the HTTP state
    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("Error in connection: {}", e);
        }
    });

    let parsed_url = url.parse::<hyper::Uri>().expect("Could not parse url");
    let request = Request::builder()
        // We need to manually add the host header because SendRequest does not
        .header("Host", "example.com")
        .method("GET")
        .uri(parsed_url)
        .body(Empty::<Bytes>::new())
        .expect("Could not build HTTP request");
    let mut response = request_sender
        .send_request(request)
        .await
        .expect("Could not send request");
    while let Some(next) = response.frame().await {
        let frame = next.expect("Could not unwrap next frame");
        if let Some(chunk) = frame.data_ref() {
            io::stdout()
                .write_all(&chunk)
                .await
                .expect("Could not write to stdout");
        }
    }
}

All you need to do is call async_request like so:

async_request(
    Ipv4Addr::new(93, 184, 216, 34),
    "example.com.",
    "https://example.com/",
)
.await;

@djc
Copy link
Member

djc commented May 29, 2023

I don't see how that example is using trust-dns-resolver for DNS resolution.

@CalderWhite
Copy link

I didn't actually integrate it with the Https resolver. This thread just comes up on google when you look for ways to use rustls without performing resolutions, so I provided an example I landed on. This example takes in an ip address so that no resolutions are necessary. I haven't actually checked if it does not perform resolutions or not.

To complete the example you could add the trustDNS resolver to provide the IP.

Not a full example, just leaving it in case people come upon the same path as me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants