.bind_rustls() 443 次 out/does 未在 public ip 上服务(使用 certbot 证书)

.bind_rustls() on 443 times out/does not serve on public ip (using a certbot certificate)

tl;博士:我的网站在使用 https 的以太本地主机上成功提供服务,或者使用 http 提供 domain/ip,但使用 https 不提供 domain/ip。代码在底部。

我在我的注册商中有 @ (gremy.co.uk) 和 wwwA 记录,当托管在 http 上时它会正确解析(例如 .bind("0.0.0.0:80"))

我已经使用 certbot certonly --standalonegremy.co.ukwww.gremy.co.uk 生成了证书,并将 rustls::ServerConfig 指向 fullchain.pemprivkey.pem 文件。

当运行 .bind("0.0.0.0:80") 我可以按预期成功访问我的网站。更改为 .bind_rustls("0.0.0.0:443", config)? 会使 https://gremy.co.uk 和指向它的 ip 超时(“服务器响应时间太长。”)。控制台不记录任何内容,未尝试连接。转到 localhost 时尝试连接,服务器记录 BadCertificate 错误(这很公平,因为我有 gremy.co.uk 而不是 localhost 的证书)

我能够 运行 mkcert 为本地主机生成一个自签名证书,并且按预期连接并且工作正常。

所以我似乎可以通过 https 在本地主机上为我的网站提供服务,但不能在我服务器的实际 public ip/domain 上提供服务。我的 actix-web 配置可能缺少某些东西吗?

代码:

use rustls::internal::pemfile::{certs, pkcs8_private_keys};
use actix_web::middleware::Logger;
use anyhow::Context;
use actix_web::{middleware::Logger, get, http, web, App, HttpRequest, HttpResponse, HttpServer, http::ContentEncoding, middleware::*};
use actix_cors::Cors;
use actix_files::{Files, NamedFile};

#[actix::main]
async fn main() -> anyhow::Result<()> {
    let mut config = rustls::ServerConfig::new(rustls::NoClientAuth::new());
    let cert_file = &mut std::io::BufReader::new(std::fs::File::open(&CONFIG.ssl.cert)?);
    let key_file = &mut std::io::BufReader::new(std::fs::File::open(&CONFIG.ssl.key)?);
    let cert_chain = certs(cert_file).ok().context("no certs")?;
    let mut keys = pkcs8_private_keys(key_file).ok().context("no private keys")?;
    config.set_single_cert(cert_chain, keys.remove(0))?;

    Ok(HttpServer::new(|| {
        App::new()
            .wrap(Logger::new("%s in %Ts, %b bytes \"%r\""))
            .wrap(NormalizePath::default())
            .wrap(Cors::permissive()) // seems to be necessary for chrome?
            .service(actix_files::Files::new("/public", "public"))
            .default_service(web::route().to(reply))
    })
        // .bind("0.0.0.0:80")? // just works
        .bind_rustls("0.0.0.0:443", config)? // just doesn't
        .run().await?)
}

fn reply() -> web::HttpResponse {
    static REPLY: Lazy<String> = Lazy::new(|| {
        let js = minifier::js::minify(&std::fs::read_to_string("public/wasm/client.js").expect("couldn't find the js payload"));

        minify::html::minify(&format!(
            include_str!("../response.html"),
            js = js,
            // or localhost/http as appropriate
            path = "https://gremy.co.uk/public/wasm/client_bg.wasm",
        ))
    });

    web::HttpResponse::Ok().body(&REPLY as &str)
}

有趣的是,如果您要托管服务器,您仍然需要转发默认端口,例如 443。

在路由器中转发 443 之后,为了以防万一,通过 windows 防火墙打开 443,我现在可以通过我的 public ip 在 https 上提供服务。