mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-30 16:59:52 +00:00
Fix/fix domain server (#319)
* fix: server_domain and improve code for tls * add log * add tracing * test * improve config and tls * Update rustfs/src/console.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -32,13 +32,7 @@ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -node
|
|||||||
### TLS File
|
### TLS File
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
rustfs_public.crt #api cert.pem
|
||||||
|
|
||||||
rustfs_tls_cert.pem api cert.pem
|
rustfs_private.key #api key.pem
|
||||||
|
|
||||||
rustfs_tls_key.pem api key.pem
|
|
||||||
|
|
||||||
rustfs_console_tls_cert.pem console cert.pem
|
|
||||||
|
|
||||||
rustfs_console_tls_key.pem console key.pem
|
|
||||||
|
|
||||||
```
|
```
|
||||||
+12
-12
@@ -29,11 +29,11 @@ pub const DEFAULT_OBS_CONFIG: &str = "config/obs.toml";
|
|||||||
|
|
||||||
/// Default TLS key for rustfs
|
/// Default TLS key for rustfs
|
||||||
/// This is the default key for TLS.
|
/// This is the default key for TLS.
|
||||||
pub(crate) const RUSTFS_TLS_KEY: &str = "rustfs_tls_key.pem";
|
pub(crate) const RUSTFS_TLS_KEY: &str = "rustfs_private.key";
|
||||||
|
|
||||||
/// Default TLS cert for rustfs
|
/// Default TLS cert for rustfs
|
||||||
/// This is the default cert for TLS.
|
/// This is the default cert for TLS.
|
||||||
pub(crate) const RUSTFS_TLS_CERT: &str = "rustfs_tls_cert.pem";
|
pub(crate) const RUSTFS_TLS_CERT: &str = "rustfs_public.crt";
|
||||||
|
|
||||||
#[allow(clippy::const_is_empty)]
|
#[allow(clippy::const_is_empty)]
|
||||||
const SHORT_VERSION: &str = {
|
const SHORT_VERSION: &str = {
|
||||||
@@ -47,16 +47,16 @@ const SHORT_VERSION: &str = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const LONG_VERSION: &str = concat!(
|
const LONG_VERSION: &str = concat!(
|
||||||
concat!(SHORT_VERSION, "\n"),
|
concat!(SHORT_VERSION, "\n"),
|
||||||
concat!("build time : ", build::BUILD_TIME, "\n"),
|
concat!("build time : ", build::BUILD_TIME, "\n"),
|
||||||
concat!("build profile: ", build::BUILD_RUST_CHANNEL, "\n"),
|
concat!("build profile: ", build::BUILD_RUST_CHANNEL, "\n"),
|
||||||
concat!("build os : ", build::BUILD_OS, "\n"),
|
concat!("build os : ", build::BUILD_OS, "\n"),
|
||||||
concat!("rust version : ", build::RUST_VERSION, "\n"),
|
concat!("rust version : ", build::RUST_VERSION, "\n"),
|
||||||
concat!("rust channel : ", build::RUST_CHANNEL, "\n"),
|
concat!("rust channel : ", build::RUST_CHANNEL, "\n"),
|
||||||
concat!("git branch : ", build::BRANCH, "\n"),
|
concat!("git branch : ", build::BRANCH, "\n"),
|
||||||
concat!("git commit : ", build::COMMIT_HASH, "\n"),
|
concat!("git commit : ", build::COMMIT_HASH, "\n"),
|
||||||
concat!("git tag : ", build::TAG, "\n"),
|
concat!("git tag : ", build::TAG, "\n"),
|
||||||
concat!("git status :\n", build::GIT_STATUS_FILE),
|
concat!("git status :\n", build::GIT_STATUS_FILE),
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, Parser, Clone)]
|
#[derive(Debug, Parser, Clone)]
|
||||||
|
|||||||
+57
-35
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::config::{RUSTFS_TLS_CERT, RUSTFS_TLS_KEY};
|
||||||
use crate::license::get_license;
|
use crate::license::get_license;
|
||||||
use axum::{
|
use axum::{
|
||||||
body::Body,
|
body::Body,
|
||||||
@@ -16,15 +17,12 @@ use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
|
|||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::signal;
|
use tokio::signal;
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info, instrument};
|
||||||
|
|
||||||
shadow!(build);
|
shadow!(build);
|
||||||
|
|
||||||
const RUSTFS_ADMIN_PREFIX: &str = "/rustfs/admin/v3";
|
const RUSTFS_ADMIN_PREFIX: &str = "/rustfs/admin/v3";
|
||||||
|
|
||||||
const RUSTFS_CONSOLE_TLS_KEY: &str = "rustfs_console_tls_key.pem";
|
|
||||||
const RUSTFS_CONSOLE_TLS_CERT: &str = "rustfs_console_tls_cert.pem";
|
|
||||||
|
|
||||||
#[derive(RustEmbed)]
|
#[derive(RustEmbed)]
|
||||||
#[folder = "$CARGO_MANIFEST_DIR/static"]
|
#[folder = "$CARGO_MANIFEST_DIR/static"]
|
||||||
struct StaticFiles;
|
struct StaticFiles;
|
||||||
@@ -169,32 +167,56 @@ async fn license_handler() -> impl IntoResponse {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_private_ip(ip: std::net::IpAddr) -> bool {
|
||||||
|
match ip {
|
||||||
|
std::net::IpAddr::V4(ip) => {
|
||||||
|
let octets = ip.octets();
|
||||||
|
// 10.0.0.0/8
|
||||||
|
octets[0] == 10 ||
|
||||||
|
// 172.16.0.0/12
|
||||||
|
(octets[0] == 172 && (octets[1] >= 16 && octets[1] <= 31)) ||
|
||||||
|
// 192.168.0.0/16
|
||||||
|
(octets[0] == 192 && octets[1] == 168)
|
||||||
|
}
|
||||||
|
std::net::IpAddr::V6(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::const_is_empty)]
|
#[allow(clippy::const_is_empty)]
|
||||||
|
#[instrument(fields(host))]
|
||||||
async fn config_handler(Host(host): Host) -> impl IntoResponse {
|
async fn config_handler(Host(host): Host) -> impl IntoResponse {
|
||||||
let host_with_port = if host.contains(':') { host } else { format!("{}:80", host) };
|
let host_with_port = if host.contains(':') {
|
||||||
|
host.clone()
|
||||||
let is_addr = host_with_port
|
|
||||||
.to_socket_addrs()
|
|
||||||
.map(|addrs| {
|
|
||||||
addrs.into_iter().find(|v| {
|
|
||||||
if let SocketAddr::V4(ipv4) = v {
|
|
||||||
!ipv4.ip().is_private() && !ipv4.ip().is_loopback() && !ipv4.ip().is_unspecified()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let mut cfg = CONSOLE_CONFIG.get().unwrap().clone();
|
|
||||||
|
|
||||||
let url = if let Some(addr) = is_addr {
|
|
||||||
format!("http://{}:{}", addr.ip(), cfg.port)
|
|
||||||
} else {
|
} else {
|
||||||
let (host, _) = host_with_port.split_once(':').unwrap_or_default();
|
format!("{}:80", host)
|
||||||
format!("http://{}:{}", host, cfg.port)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 将当前配置复制一份
|
||||||
|
let mut cfg = CONSOLE_CONFIG.get().unwrap().clone();
|
||||||
|
|
||||||
|
// 尝试解析为 socket address,但不强制要求一定要是 IP 地址
|
||||||
|
let socket_addr = host_with_port.to_socket_addrs().ok().and_then(|mut addrs| addrs.next());
|
||||||
|
debug!("axum Using host with port: {}, Socket address: {:?}", host_with_port, socket_addr);
|
||||||
|
let url = match socket_addr {
|
||||||
|
Some(addr) if addr.ip().is_ipv4() => {
|
||||||
|
let ipv4 = addr.ip().to_string();
|
||||||
|
// 如果是私有 IP、环回地址或未指定地址,保留原始域名
|
||||||
|
if is_private_ip(addr.ip()) || addr.ip().is_loopback() || addr.ip().is_unspecified() {
|
||||||
|
let (host, _) = host_with_port.split_once(':').unwrap_or((&host, "80"));
|
||||||
|
debug!("axum Using private IPv4 address: {}", host);
|
||||||
|
format!("http://{}:{}", host, cfg.port)
|
||||||
|
} else {
|
||||||
|
debug!("axum Using public IPv4 address");
|
||||||
|
format!("http://{}:{}", ipv4, cfg.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// 如果不是有效的 IPv4 地址,保留原始域名
|
||||||
|
let (host, _) = host_with_port.split_once(':').unwrap_or((&host, "80"));
|
||||||
|
debug!("axum Using domain address: {}", host);
|
||||||
|
format!("http://{}:{}", host, cfg.port)
|
||||||
|
}
|
||||||
|
};
|
||||||
cfg.api.base_url = format!("{}{}", url, RUSTFS_ADMIN_PREFIX);
|
cfg.api.base_url = format!("{}{}", url, RUSTFS_ADMIN_PREFIX);
|
||||||
cfg.s3.endpoint = url;
|
cfg.s3.endpoint = url;
|
||||||
|
|
||||||
@@ -222,21 +244,21 @@ pub async fn start_static_file_server(
|
|||||||
info!(" RootUser: {}", access_key);
|
info!(" RootUser: {}", access_key);
|
||||||
info!(" RootPass: {}", secret_key);
|
info!(" RootPass: {}", secret_key);
|
||||||
|
|
||||||
let tls_path = tls_path.unwrap_or_default();
|
|
||||||
let key_path = format!("{}/{}", tls_path, RUSTFS_CONSOLE_TLS_KEY);
|
|
||||||
let cert_path = format!("{}/{}", tls_path, RUSTFS_CONSOLE_TLS_CERT);
|
|
||||||
// Check and start the HTTPS/HTTP server
|
// Check and start the HTTPS/HTTP server
|
||||||
match start_server(addrs, local_addr, &key_path, &cert_path, app.clone()).await {
|
match start_server(addrs, local_addr, tls_path, app.clone()).await {
|
||||||
Ok(_) => info!("Server shutdown gracefully"),
|
Ok(_) => info!("Server shutdown gracefully"),
|
||||||
Err(e) => error!("Server error: {}", e),
|
Err(e) => error!("Server error: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async fn start_server(addrs: &str, local_addr: SocketAddr, key_path: &str, cert_path: &str, app: Router) -> std::io::Result<()> {
|
async fn start_server(addrs: &str, local_addr: SocketAddr, tls_path: Option<String>, app: Router) -> std::io::Result<()> {
|
||||||
let has_tls_certs = tokio::try_join!(tokio::fs::metadata(key_path), tokio::fs::metadata(cert_path)).is_ok();
|
let tls_path = tls_path.unwrap_or_default();
|
||||||
|
let key_path = format!("{}/{}", tls_path, RUSTFS_TLS_KEY);
|
||||||
|
let cert_path = format!("{}/{}", tls_path, RUSTFS_TLS_CERT);
|
||||||
|
let has_tls_certs = tokio::try_join!(tokio::fs::metadata(&key_path), tokio::fs::metadata(&cert_path)).is_ok();
|
||||||
|
debug!("Console TLS certs: {:?}", has_tls_certs);
|
||||||
if has_tls_certs {
|
if has_tls_certs {
|
||||||
debug!("Found TLS certificates, starting with HTTPS");
|
debug!("Found TLS certificates, starting with HTTPS");
|
||||||
match tokio::try_join!(tokio::fs::read(key_path), tokio::fs::read(cert_path)) {
|
match tokio::try_join!(tokio::fs::read(&key_path), tokio::fs::read(&cert_path)) {
|
||||||
Ok((key_data, cert_data)) => {
|
Ok((key_data, cert_data)) => {
|
||||||
match RustlsConfig::from_pem(cert_data, key_data).await {
|
match RustlsConfig::from_pem(cert_data, key_data).await {
|
||||||
Ok(config) => {
|
Ok(config) => {
|
||||||
@@ -247,7 +269,7 @@ async fn start_server(addrs: &str, local_addr: SocketAddr, key_path: &str, cert_
|
|||||||
shutdown_signal().await;
|
shutdown_signal().await;
|
||||||
handle_clone.graceful_shutdown(Some(Duration::from_secs(10)));
|
handle_clone.graceful_shutdown(Some(Duration::from_secs(10)));
|
||||||
});
|
});
|
||||||
debug!("Starting HTTPS server...");
|
info!("Starting HTTPS server...");
|
||||||
axum_server::bind_rustls(local_addr, config)
|
axum_server::bind_rustls(local_addr, config)
|
||||||
.handle(handle.clone())
|
.handle(handle.clone())
|
||||||
.serve(app.into_make_service())
|
.serve(app.into_make_service())
|
||||||
@@ -275,7 +297,7 @@ async fn start_server(addrs: &str, local_addr: SocketAddr, key_path: &str, cert_
|
|||||||
|
|
||||||
async fn start_http_server(addrs: &str, app: Router) -> std::io::Result<()> {
|
async fn start_http_server(addrs: &str, app: Router) -> std::io::Result<()> {
|
||||||
debug!("Starting HTTP server...");
|
debug!("Starting HTTP server...");
|
||||||
let listener = tokio::net::TcpListener::bind(addrs).await.unwrap();
|
let listener = tokio::net::TcpListener::bind(addrs).await?;
|
||||||
axum::serve(listener, app)
|
axum::serve(listener, app)
|
||||||
.with_graceful_shutdown(shutdown_signal())
|
.with_graceful_shutdown(shutdown_signal())
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ async fn run(opt: config::Opt) -> Result<()> {
|
|||||||
let key_path = format!("{}/{}", tls_path, RUSTFS_TLS_KEY);
|
let key_path = format!("{}/{}", tls_path, RUSTFS_TLS_KEY);
|
||||||
let cert_path = format!("{}/{}", tls_path, RUSTFS_TLS_CERT);
|
let cert_path = format!("{}/{}", tls_path, RUSTFS_TLS_CERT);
|
||||||
let has_tls_certs = tokio::try_join!(tokio::fs::metadata(key_path.clone()), tokio::fs::metadata(cert_path.clone())).is_ok();
|
let has_tls_certs = tokio::try_join!(tokio::fs::metadata(key_path.clone()), tokio::fs::metadata(cert_path.clone())).is_ok();
|
||||||
|
debug!("Main TLS certs: {:?}", has_tls_certs);
|
||||||
let tls_acceptor = if has_tls_certs {
|
let tls_acceptor = if has_tls_certs {
|
||||||
debug!("Found TLS certificates, starting with HTTPS");
|
debug!("Found TLS certificates, starting with HTTPS");
|
||||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export RUSTFS_ADDRESS="0.0.0.0:9000"
|
|||||||
export RUSTFS_CONSOLE_ENABLE=true
|
export RUSTFS_CONSOLE_ENABLE=true
|
||||||
export RUSTFS_CONSOLE_ADDRESS="0.0.0.0:9002"
|
export RUSTFS_CONSOLE_ADDRESS="0.0.0.0:9002"
|
||||||
# export RUSTFS_SERVER_DOMAINS="localhost:9000"
|
# export RUSTFS_SERVER_DOMAINS="localhost:9000"
|
||||||
|
# HTTPS 证书目录
|
||||||
|
# export RUSTFS_TLS_PATH="./deploy/certs"
|
||||||
|
|
||||||
# 具体路径修改为配置文件真实路径,obs.example.toml 仅供参考 其中`RUSTFS_OBS_CONFIG` 和下面变量二选一
|
# 具体路径修改为配置文件真实路径,obs.example.toml 仅供参考 其中`RUSTFS_OBS_CONFIG` 和下面变量二选一
|
||||||
export RUSTFS_OBS_CONFIG="./deploy/config/obs.example.toml"
|
export RUSTFS_OBS_CONFIG="./deploy/config/obs.example.toml"
|
||||||
|
|||||||
Reference in New Issue
Block a user