修改部署文件;
This commit is contained in:
@@ -239,8 +239,12 @@ fn validate_aspa(customer_asn: u32, provider_asns: &[u32]) -> Result<()> {
|
||||
return Err(anyhow!("provider list must not be empty"));
|
||||
}
|
||||
|
||||
if provider_asns.iter().any(|asn| *asn == 0) {
|
||||
return Err(anyhow!("provider list must not contain AS0"));
|
||||
if provider_asns.iter().any(|asn| *asn == 0)
|
||||
&& !(provider_asns.len() == 1 && provider_asns[0] == 0)
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"provider list containing AS0 must be exactly [0]"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -163,10 +163,12 @@ impl Aspa {
|
||||
));
|
||||
}
|
||||
|
||||
if self.provider_asns.iter().any(|asn| asn.into_u32() == 0) {
|
||||
if self.provider_asns.iter().any(|asn| asn.into_u32() == 0)
|
||||
&& !(self.provider_asns.len() == 1 && self.provider_asns[0].into_u32() == 0)
|
||||
{
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"ASPA provider list must not contain AS0",
|
||||
"ASPA provider list containing AS0 must be exactly [0]",
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -1317,10 +1317,12 @@ impl Aspa {
|
||||
"ASPA withdrawal must not contain provider ASNs",
|
||||
));
|
||||
}
|
||||
if self.provider_asns.iter().any(|asn| *asn == 0) {
|
||||
if self.provider_asns.iter().any(|asn| *asn == 0)
|
||||
&& !(self.provider_asns.len() == 1 && self.provider_asns[0] == 0)
|
||||
{
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"ASPA provider list must not contain AS0",
|
||||
"ASPA provider list containing AS0 must be exactly [0]",
|
||||
));
|
||||
}
|
||||
if self.provider_asns.windows(2).any(|pair| pair[0] >= pair[1]) {
|
||||
|
||||
@@ -3,20 +3,24 @@ use std::time::Duration;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RtrServiceConfig {
|
||||
pub max_connections: usize,
|
||||
pub max_concurrent_handshakes: usize,
|
||||
pub notify_queue_size: usize,
|
||||
pub tcp_keepalive: Option<Duration>,
|
||||
pub warn_insecure_tcp: bool,
|
||||
pub require_tls_server_dns_name_san: bool,
|
||||
pub enforce_tls_client_san_ip_match: bool,
|
||||
}
|
||||
|
||||
impl Default for RtrServiceConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_connections: 1024,
|
||||
max_concurrent_handshakes: 128,
|
||||
notify_queue_size: 1024,
|
||||
tcp_keepalive: Some(Duration::from_secs(60)),
|
||||
warn_insecure_tcp: true,
|
||||
require_tls_server_dns_name_san: false,
|
||||
enforce_tls_client_san_ip_match: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,10 @@ pub async fn handle_tls_connection(
|
||||
stream: TcpStream,
|
||||
peer_addr: SocketAddr,
|
||||
acceptor: TlsAcceptor,
|
||||
enforce_client_san_ip_match: bool,
|
||||
notify_rx: broadcast::Receiver<()>,
|
||||
shutdown_rx: watch::Receiver<bool>,
|
||||
handshake_permit: Option<OwnedSemaphorePermit>,
|
||||
) -> Result<()> {
|
||||
info!("RTR TLS handshake started for {}", peer_addr);
|
||||
let tls_stream = acceptor
|
||||
@@ -69,13 +71,24 @@ pub async fn handle_tls_connection(
|
||||
.await
|
||||
.with_context(|| format!("TLS handshake failed for {}", peer_addr))?;
|
||||
info!("RTR TLS handshake completed for {}", peer_addr);
|
||||
verify_peer_certificate_ip(&tls_stream, peer_addr.ip()).with_context(|| {
|
||||
format!(
|
||||
"TLS client certificate SAN IP validation failed for {}",
|
||||
peer_addr
|
||||
)
|
||||
})?;
|
||||
info!("RTR TLS client certificate validated for {}", peer_addr);
|
||||
match verify_peer_certificate_ip(&tls_stream, peer_addr.ip()) {
|
||||
Ok(()) => info!("RTR TLS client certificate SAN IP validated for {}", peer_addr),
|
||||
Err(err) => {
|
||||
if enforce_client_san_ip_match {
|
||||
return Err(err).with_context(|| {
|
||||
format!(
|
||||
"TLS client certificate SAN IP validation failed for {}",
|
||||
peer_addr
|
||||
)
|
||||
});
|
||||
}
|
||||
warn!(
|
||||
"RTR TLS client certificate SAN IP validation failed but allowed by configuration for {}: {}",
|
||||
peer_addr, err
|
||||
);
|
||||
}
|
||||
}
|
||||
drop(handshake_permit);
|
||||
|
||||
let session = RtrSession::new(cache, tls_stream, notify_rx, shutdown_rx);
|
||||
session.run().await?;
|
||||
|
||||
@@ -11,7 +11,7 @@ use russh::server::{self, Msg, Session};
|
||||
use russh::{Channel, ChannelId, Disconnect};
|
||||
use socket2::{SockRef, TcpKeepalive};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::sync::{Semaphore, broadcast, watch};
|
||||
use tokio::sync::{OwnedSemaphorePermit, Semaphore, broadcast, watch};
|
||||
use tokio_rustls::TlsAcceptor;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
@@ -30,6 +30,9 @@ type TransportFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
|
||||
|
||||
pub trait TransportAcceptor: Clone + Send + Sync + 'static {
|
||||
fn name(&self) -> &'static str;
|
||||
fn requires_handshake_limit(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn handle_connection(
|
||||
&self,
|
||||
@@ -38,6 +41,7 @@ pub trait TransportAcceptor: Clone + Send + Sync + 'static {
|
||||
peer_addr: SocketAddr,
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
handshake_permit: Option<OwnedSemaphorePermit>,
|
||||
) -> TransportFuture;
|
||||
}
|
||||
|
||||
@@ -56,6 +60,7 @@ impl TransportAcceptor for TcpTransport {
|
||||
peer_addr: SocketAddr,
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
_handshake_permit: Option<OwnedSemaphorePermit>,
|
||||
) -> TransportFuture {
|
||||
Box::pin(async move {
|
||||
handle_tcp_connection(
|
||||
@@ -73,12 +78,16 @@ impl TransportAcceptor for TcpTransport {
|
||||
#[derive(Clone)]
|
||||
struct TlsTransport {
|
||||
acceptor: TlsAcceptor,
|
||||
enforce_client_san_ip_match: bool,
|
||||
}
|
||||
|
||||
impl TransportAcceptor for TlsTransport {
|
||||
fn name(&self) -> &'static str {
|
||||
"TLS"
|
||||
}
|
||||
fn requires_handshake_limit(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn handle_connection(
|
||||
&self,
|
||||
@@ -87,16 +96,20 @@ impl TransportAcceptor for TlsTransport {
|
||||
peer_addr: SocketAddr,
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
handshake_permit: Option<OwnedSemaphorePermit>,
|
||||
) -> TransportFuture {
|
||||
let acceptor = self.acceptor.clone();
|
||||
let enforce_client_san_ip_match = self.enforce_client_san_ip_match;
|
||||
Box::pin(async move {
|
||||
handle_tls_connection(
|
||||
cache,
|
||||
stream,
|
||||
peer_addr,
|
||||
acceptor,
|
||||
enforce_client_san_ip_match,
|
||||
notify_tx.subscribe(),
|
||||
shutdown_tx.subscribe(),
|
||||
handshake_permit,
|
||||
)
|
||||
.await
|
||||
})
|
||||
@@ -120,6 +133,7 @@ impl TransportAcceptor for SshTransport {
|
||||
peer_addr: SocketAddr,
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
_handshake_permit: Option<OwnedSemaphorePermit>,
|
||||
) -> TransportFuture {
|
||||
let runtime = self.runtime.clone();
|
||||
Box::pin(async move {
|
||||
@@ -171,6 +185,7 @@ pub struct RtrServer {
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
connection_limiter: Arc<Semaphore>,
|
||||
handshake_limiter: Arc<Semaphore>,
|
||||
active_connections: Arc<AtomicUsize>,
|
||||
config: RtrServiceConfig,
|
||||
}
|
||||
@@ -182,6 +197,7 @@ impl RtrServer {
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
connection_limiter: Arc<Semaphore>,
|
||||
handshake_limiter: Arc<Semaphore>,
|
||||
active_connections: Arc<AtomicUsize>,
|
||||
config: RtrServiceConfig,
|
||||
) -> Self {
|
||||
@@ -191,6 +207,7 @@ impl RtrServer {
|
||||
notify_tx,
|
||||
shutdown_tx,
|
||||
connection_limiter,
|
||||
handshake_limiter,
|
||||
active_connections,
|
||||
config,
|
||||
}
|
||||
@@ -231,6 +248,7 @@ impl RtrServer {
|
||||
pub async fn run_tls(self, tls_config: Arc<ServerConfig>) -> Result<()> {
|
||||
let transport = TlsTransport {
|
||||
acceptor: TlsAcceptor::from(tls_config),
|
||||
enforce_client_san_ip_match: self.config.enforce_tls_client_san_ip_match,
|
||||
};
|
||||
self.run_with_transport(transport).await
|
||||
}
|
||||
@@ -317,6 +335,24 @@ impl RtrServer {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let handshake_permit = if transport.requires_handshake_limit() {
|
||||
match self.handshake_limiter.clone().try_acquire_owned() {
|
||||
Ok(permit) => Some(permit),
|
||||
Err(_) => {
|
||||
warn!(
|
||||
"RTR {} connection rejected for {}: max concurrent handshakes reached ({})",
|
||||
transport.name(),
|
||||
peer_addr,
|
||||
self.config.max_concurrent_handshakes
|
||||
);
|
||||
drop(stream);
|
||||
drop(permit);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cache = self.cache.clone();
|
||||
let notify_tx = self.notify_tx.clone();
|
||||
@@ -341,7 +377,14 @@ impl RtrServer {
|
||||
);
|
||||
|
||||
if let Err(err) = transport_instance
|
||||
.handle_connection(cache, stream, peer_addr, notify_tx, shutdown_tx)
|
||||
.handle_connection(
|
||||
cache,
|
||||
stream,
|
||||
peer_addr,
|
||||
notify_tx,
|
||||
shutdown_tx,
|
||||
handshake_permit,
|
||||
)
|
||||
.await
|
||||
{
|
||||
let active_after_close = guard.active_count().saturating_sub(1);
|
||||
|
||||
@@ -20,6 +20,7 @@ pub struct RtrService {
|
||||
notify_tx: broadcast::Sender<()>,
|
||||
shutdown_tx: watch::Sender<bool>,
|
||||
connection_limiter: Arc<Semaphore>,
|
||||
handshake_limiter: Arc<Semaphore>,
|
||||
active_connections: Arc<AtomicUsize>,
|
||||
config: RtrServiceConfig,
|
||||
}
|
||||
@@ -38,6 +39,7 @@ impl RtrService {
|
||||
notify_tx,
|
||||
shutdown_tx,
|
||||
connection_limiter: Arc::new(Semaphore::new(config.max_connections)),
|
||||
handshake_limiter: Arc::new(Semaphore::new(config.max_concurrent_handshakes)),
|
||||
active_connections: Arc::new(AtomicUsize::new(0)),
|
||||
config,
|
||||
}
|
||||
@@ -70,6 +72,7 @@ impl RtrService {
|
||||
self.notify_tx.clone(),
|
||||
self.shutdown_tx.clone(),
|
||||
self.connection_limiter.clone(),
|
||||
self.handshake_limiter.clone(),
|
||||
self.active_connections.clone(),
|
||||
self.config.clone(),
|
||||
)
|
||||
@@ -82,6 +85,7 @@ impl RtrService {
|
||||
self.notify_tx.clone(),
|
||||
self.shutdown_tx.clone(),
|
||||
self.connection_limiter.clone(),
|
||||
self.handshake_limiter.clone(),
|
||||
self.active_connections.clone(),
|
||||
self.config.clone(),
|
||||
)
|
||||
@@ -94,6 +98,7 @@ impl RtrService {
|
||||
self.notify_tx.clone(),
|
||||
self.shutdown_tx.clone(),
|
||||
self.connection_limiter.clone(),
|
||||
self.handshake_limiter.clone(),
|
||||
self.active_connections.clone(),
|
||||
self.config.clone(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user