无法访问此站点的错误,127.0.0.1 拒绝在 Rust 中连接 HTTP/3

问题描述 投票:0回答:1

我正在学习在 Rust 中使用 HTTP/3,但是当我在浏览器中打开 https://127.0.0.1:4433 时,我不断收到此错误。

错误无法访问此站点,127.0.0.1 拒绝连接

编译器没有错误。是因为证书的原因吗?问题是我也没有 SSL 证书,我当前使用的证书是使用 OpenSSL 自签名的。有谁拥有有效的 SSL 证书,请尝试运行我的代码以查看它是否有效,这样我就可以确定问题是否与证书有关,因为编译器中没有错误消息。我已在防火墙上激活 TCP 和 UDP 端口 4433。有谁知道为什么会发生这种情况?这是我的代码。

Cargo.toml:

[package]
name = "http3"
version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1.0"
bytes = "1"
futures = "0.3"
h3 = { version = "*", features = ["tracing"] }
h3-quinn = { version = "*", features = ["tracing"] }
h3-webtransport = { version = "*" }
http = "1"
quinn = { version = "0.11", default-features = false, features = [
    "runtime-tokio",
    "rustls",
    "ring",
] }
rcgen = { version = "0.13" }
rustls = { version = "0.23", default-features = false, features = [
    "logging",
    "ring",
    "std",
] }
rustls-native-certs = "0.7"
structopt = "0.3"
tokio = { version = "1.27", features = ["full"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3", default-features = false, features = [
    "fmt",
    "ansi",
    "env-filter",
    "time",
    "tracing-log",
] }
octets = "0.3.0"
tracing-tree = { version = "0.3" }
rustls-pemfile = "2.0"

主要.rs :

use std::{net::SocketAddr, path::PathBuf, sync::Arc};
use bytes::Bytes;
use http::{Request, Response, StatusCode};
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use structopt::StructOpt;
use tokio::{fs::File, io::AsyncReadExt};
use tracing::{error, info, trace_span};
use h3::{error::ErrorLevel, quic::BidiStream, server::RequestStream};
use h3_quinn::quinn::{self, crypto::rustls::QuicServerConfig};

#[derive(StructOpt, Debug)]
#[structopt(name = "server")]
struct Opt {
    #[structopt(
        name = "dir",
        short,
        long,
        help = "Root directory of the files to serve. \
                If omitted, server will respond OK."
    )]
    pub root: Option<PathBuf>,

    #[structopt(
        short,
        long,
        default_value = "127.0.0.1:4433",
        help = "What address:port to listen for new connections"
    )]
    pub listen: SocketAddr,

    #[structopt(flatten)]
    pub certs: Certs,
}

#[derive(StructOpt, Debug)]
pub struct Certs {
    #[structopt(
        long,
        short,
        default_value = "cert.pem",
        help = "Certificate for TLS in PEM format. If present, `--key` is mandatory."
    )]
    pub cert: PathBuf,

    #[structopt(
        long,
        short,
        default_value = "key.pem",
        help = "Private key for the certificate in PEM format."
    )]
    pub key: PathBuf,
}

static ALPN: &[u8] = b"h3";

fn load_pem_cert(path: PathBuf) -> Result<Vec<CertificateDer<'static>>, Box<dyn std::error::Error>> {
    let cert_file = std::fs::File::open(path)?;
    let mut reader = std::io::BufReader::new(cert_file);
    let certs = rustls_pemfile::certs(&mut reader)
        .collect::<Result<Vec<_>, _>>()?
        .into_iter()
        .map(CertificateDer::from)
        .collect();
    Ok(certs)
}

fn load_pem_key(path: PathBuf) -> Result<PrivateKeyDer<'static>, Box<dyn std::error::Error>> {
    let key_file = std::fs::File::open(path.clone())?;
    let mut reader = std::io::BufReader::new(key_file);
    let pkcs8_keys = rustls_pemfile::pkcs8_private_keys(&mut reader)
        .collect::<Result<Vec<_>, _>>()?;
    if let Some(key) = pkcs8_keys.into_iter().next() {
        return Ok(PrivateKeyDer::from(key));
    }
    let key_file = std::fs::File::open(path)?;
    let mut reader = std::io::BufReader::new(key_file);
    let rsa_keys = rustls_pemfile::rsa_private_keys(&mut reader)
        .collect::<Result<Vec<_>, _>>()?;
    if let Some(key) = rsa_keys.into_iter().next() {
        return Ok(PrivateKeyDer::from(key));
    }
    Err("No valid private key found in PEM file".into())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    tracing_subscriber::fmt()
        .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
        .with_span_events(tracing_subscriber::fmt::format::FmtSpan::FULL)
        .with_writer(std::io::stderr)
        .with_max_level(tracing::Level::INFO)
        .init();

    let opt = Opt::from_args();
    let root = if let Some(root) = opt.root {
        if !root.is_dir() {
            return Err(format!("{}: is not a readable directory", root.display()).into());
        } else {
            info!("serving {}", root.display());
            Arc::new(Some(root))
        }
    } else {
        Arc::new(None)
    };

    let Certs { cert, key } = opt.certs;
    let certs = load_pem_cert(cert)?;
    let key = load_pem_key(key)?;

    let mut tls_config = rustls::ServerConfig::builder()
        .with_no_client_auth()
        .with_single_cert(certs, key)?;

    tls_config.max_early_data_size = u32::MAX;
    tls_config.alpn_protocols = vec![ALPN.into()];

    let mut server_config =
        quinn::ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(tls_config)?));
    let transport_config = Arc::get_mut(&mut server_config.transport).unwrap();
    transport_config.keep_alive_interval(Some(std::time::Duration::from_secs(5)));

    let endpoint = quinn::Endpoint::server(server_config, opt.listen)?;
    info!("listening on {}", opt.listen);

    while let Some(new_conn) = endpoint.accept().await {
        trace_span!("New connection being attempted");
        let root = root.clone();

        tokio::spawn(async move {
            match new_conn.await {
                Ok(conn) => {
                    info!("new connection established from {:?}", conn.remote_address());
                    let mut h3_conn = h3::server::Connection::new(h3_quinn::Connection::new(conn))
                        .await
                        .unwrap();
                    loop {
                        match h3_conn.accept().await {
                            Ok(Some((req, stream))) => {
                                info!("new request: {:#?}", req);
                                let root = root.clone();
                                tokio::spawn(async {
                                    if let Err(e) = handle_request(req, stream, root).await {
                                        error!("handling request failed: {}", e);
                                    }
                                });
                            }
                            Ok(None) => break,
                            Err(err) => {
                                error!("error on accept {}", err);
                                match err.get_error_level() {
                                    ErrorLevel::ConnectionError => break,
                                    ErrorLevel::StreamError => continue,
                                }
                            }
                        }
                    }
                }
                Err(err) => {
                    error!("accepting connection failed: {:?}", err);
                }
            }
        });
    }

    endpoint.wait_idle().await;
    Ok(())
}

async fn handle_request<T>(
    req: Request<()>,
    mut stream: RequestStream<T, Bytes>,
    serve_root: Arc<Option<PathBuf>>,
) -> Result<(), Box<dyn std::error::Error>>
where
    T: BidiStream<Bytes>,
{
    let mut contents = Vec::new();

    println!("hello dari http 3");

    match req.uri().path() {
        "/" => {
            contents.extend_from_slice(b"Welcome to the root page!");
        }
        "/api/hello" => {
            let json_response = b"{\"message\": \"Hello from API!\"}";
            contents.extend_from_slice(json_response);
            stream.send_response(
                Response::builder()
                    .status(StatusCode::OK)
                    .header("content-type", "application/json")
                    .body(())
                    .unwrap(),
            ).await?;
        }
        path if path.starts_with("/static/") => {
            if let Some(root) = serve_root.as_ref() {
                let file_path = root.join(&path[8..]);
                let mut file = File::open(&file_path).await?;
                file.read_to_end(&mut contents).await?;
            } else {
                contents.extend_from_slice(b"No static file root set.");
            }
        }
        _ => {
            contents.extend_from_slice(b"404 Not Found");
            stream.send_response(
                Response::builder()
                    .status(StatusCode::NOT_FOUND)
                    .header("content-type", "text/plain")
                    .body(())
                    .unwrap(),
            ).await?;
        }
    }

    let contents = Bytes::from(contents);
    stream.send_data(contents).await?;
    stream.finish().await?;
    Ok(())
}

rust udp quic http3
1个回答
0
投票

您面临的问题至少之一是缺乏 HTTP/3 服务发现。 TLS ALPN 不够,因为导航到

https://127.0.0.1:4433
的浏览器将首先建立 TCP 连接。您应该考虑在 TCP 端口 4433 上托管 TCP、HTTP/1.1 和/或 HTTP/2 服务器,为每个响应添加
Alt-Svc: h3=":4433"; ma=3600
标头。除此之外,TCP 服务器应该返回相同的响应。

您可以在这里阅读更多内容:https://my.f5.com/manage/s/article/K16240003

如果您只需要以编程方式连接到您的服务器,则可以绕过上述需要;只是不要指望浏览器能够连接。

© www.soinside.com 2019 - 2024. All rights reserved.