我尝试做一个Rust Actix TLS Web服务器。
项目布局
.
├── .env
├── Cargo.lock
├── Cargo.toml
├── certs
│ ├── cert.pem
│ └── key.pem
└── src
├── api_error.rs
├── handlers.rs
└── main.rs
.env
RUST_LOG=debug
PORT=443
CERTIFICATE_PATH=certs/cert.pem
PRIVATE_KEY_PATH=certs/key.pem
Cargo.toml
[package]
name = "https-test"
version = "0.1.0"
edition = "2021"
[dependencies]
actix-web = { version = "4.3.1", features = ["openssl"] }
openssl = { version = "0.10.54", features = ["v110"], optional = true }
anyhow = "1.0.72"
log = "0.4.19"
env_logger = "0.10.0"
dotenvy = "0.15.7"
main.rs
mod api_error;
mod handlers;
use anyhow::{anyhow, Result};
use log::info;
#[actix_web::main]
async fn main() -> Result<()> {
dotenvy::dotenv()?;
env_logger::init();
info!("Starting server");
let port = std::env::var("PORT")?.parse::<u16>()?;
let server = actix_web::HttpServer::new(|| {
actix_web::App::new()
.wrap(actix_web::middleware::Logger::default())
.service(actix_web::web::scope("/api/v1").configure(handlers::config_app))
});
let server = server.bind_openssl(("0.0.0.0", port), {
info!("Using TLS");
let mut builder = openssl::ssl::SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls())
.unwrap();
let private_key_path = std::env::var("PRIVATE_KEY_PATH")?;
let certificate_path = std::env::var("CERTIFICATE_PATH")?;
builder
.set_private_key_file(private_key_path, openssl::ssl::SslFiletype::PEM)
.unwrap();
builder
.set_certificate_chain_file(certificate_path)
.unwrap();
builder
})?;
server.run().await.map_err(|e| anyhow!(e))
}
handlers.rs
use crate::api_error::ApiError;
pub fn config_app(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(actix_web::web::resource("/").route(actix_web::web::get().to(index)));
}
async fn index() -> Result<actix_web::HttpResponse, ApiError> {
log::debug!("Hitting `index`");
Ok(actix_web::HttpResponse::Ok().body("Hello world !"))
}
注意:证书是使用我生成的CA自签名的。我把根CA放在我系统的可信CA中,这样我就不会每次在浏览器中看到“不可信证书”错误。
当运行服务器时,我得到预期的日志:
$ cargo run --release
[INFO https-test] Starting server
[INFO actix_server::builder] starting 10 workers
[INFO actix_server::server] Actix runtime found; starting in Actix runtime
然后在浏览器上,我转到https://localhost/
,我的浏览器无法连接到服务器,在我得到的日志中:
[ERROR actix_http::h1::dispatcher] stream error: request parse error: invalid Header provided
[ERROR actix_http::h1::dispatcher] stream error: request parse error: invalid Header provided
[ERROR actix_http::h1::dispatcher] stream error: request parse error: invalid Header provided
[ERROR actix_http::h1::dispatcher] stream error: request parse error: invalid Header provided
[ERROR actix_http::h1::dispatcher] stream error: request parse error: invalid Header provided
[ERROR actix_http::h1::dispatcher] stream error: request parse error: invalid Header provided
1条答案
按热度按时间mqkwyuun1#
这个问题似乎与HTTP/1.1解析器检测到请求中的无效标头有关。这可能是由于各种原因造成的,例如:
1.不正确的客户端行为(尽管浏览器不太可能发送格式错误的头)
1.来自某些代理或防火墙的干扰
让我们探索一些故障排除步骤:
检查SSL/TLS配置
确保您的SSL/TLS证书已正确加载,并且路径正确。仔细检查是否可以使用
openssl
CLI检查它们:配置环境变量
确保
CERTIFICATE_PATH
和PRIVATE_KEY_PATH
环境变量正确加载并指向正确的路径。检查原始HTTP流量
您可以使用像
tcpdump
或Wireshark这样的工具来捕获客户端和服务器之间的原始数据包。这可以提供关于头文件错误的进一步线索:尝试使用其他客户端
请不要使用浏览器,而是尝试使用
curl
来查看错误是否仍然存在。确保使用-k
标志来接受自签名证书。增加日志详细度
修改您的
.env
文件或直接将RUST_LOG
设置为trace
以获取更详细的日志。这可以提供线索,了解请求的哪一部分导致了错误。无SSL/TLS测试
尝试在没有SSL/TLS的情况下运行服务器,看看问题是否与SSL/TLS或其他东西有关。如果它在没有SSL的情况下工作正常,则可能是您的SSL配置有问题。
让我知道哪一步给你更多的信息,或者如果你有进一步的问题。