refactor(git): remove SSH rate limiting
SSH is deployed inside Kubernetes cluster where rate limiting at the application layer is unnecessary. Remove all SSH rate limiter code: - SshRateLimiter from SSHandle and SSHServer structs - is_user_allowed checks in auth_publickey, auth_publickey_offered - is_repo_access_allowed in exec_request - is_ip_allowed in server::new_client - rate_limiter module and start_cleanup
This commit is contained in:
parent
9368df54da
commit
0a998affbb
@ -2,7 +2,6 @@ use crate::ssh::ReceiveSyncService;
|
|||||||
use crate::ssh::RepoReceiveSyncTask;
|
use crate::ssh::RepoReceiveSyncTask;
|
||||||
use crate::ssh::SshTokenService;
|
use crate::ssh::SshTokenService;
|
||||||
use crate::ssh::authz::SshAuthService;
|
use crate::ssh::authz::SshAuthService;
|
||||||
use crate::ssh::rate_limit::SshRateLimiter;
|
|
||||||
use db::cache::AppCache;
|
use db::cache::AppCache;
|
||||||
use db::database::AppDatabase;
|
use db::database::AppDatabase;
|
||||||
use models::repos::{repo, repo_branch_protect};
|
use models::repos::{repo, repo_branch_protect};
|
||||||
@ -20,7 +19,6 @@ use std::net::SocketAddr;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWriteExt};
|
||||||
use tokio::process::ChildStdin;
|
use tokio::process::ChildStdin;
|
||||||
@ -80,7 +78,6 @@ pub struct SSHandle {
|
|||||||
pub sync: ReceiveSyncService,
|
pub sync: ReceiveSyncService,
|
||||||
pub upload_pack_eof_sent: HashSet<ChannelId>,
|
pub upload_pack_eof_sent: HashSet<ChannelId>,
|
||||||
pub logger: Logger,
|
pub logger: Logger,
|
||||||
pub rate_limiter: Arc<SshRateLimiter>,
|
|
||||||
pub token_service: SshTokenService,
|
pub token_service: SshTokenService,
|
||||||
pub client_addr: Option<SocketAddr>,
|
pub client_addr: Option<SocketAddr>,
|
||||||
}
|
}
|
||||||
@ -91,7 +88,6 @@ impl SSHandle {
|
|||||||
cache: AppCache,
|
cache: AppCache,
|
||||||
sync: ReceiveSyncService,
|
sync: ReceiveSyncService,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
rate_limiter: Arc<SshRateLimiter>,
|
|
||||||
token_service: SshTokenService,
|
token_service: SshTokenService,
|
||||||
client_addr: Option<SocketAddr>,
|
client_addr: Option<SocketAddr>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@ -115,7 +111,6 @@ impl SSHandle {
|
|||||||
sync,
|
sync,
|
||||||
upload_pack_eof_sent: HashSet::new(),
|
upload_pack_eof_sent: HashSet::new(),
|
||||||
logger,
|
logger,
|
||||||
rate_limiter,
|
|
||||||
token_service,
|
token_service,
|
||||||
client_addr,
|
client_addr,
|
||||||
}
|
}
|
||||||
@ -201,17 +196,6 @@ impl russh::server::Handler for SSHandle {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let user_id = user_model.uid.to_string();
|
|
||||||
if !self.rate_limiter.is_user_allowed(&user_id).await {
|
|
||||||
warn!(
|
|
||||||
self.logger,
|
|
||||||
"SSH token auth rate limit exceeded: {}, client: {}",
|
|
||||||
user_model.username,
|
|
||||||
client_info
|
|
||||||
);
|
|
||||||
return Err(russh::Error::NotAuthenticated);
|
|
||||||
}
|
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
self.logger,
|
self.logger,
|
||||||
"SSH token authentication successful: user={}, client={}",
|
"SSH token authentication successful: user={}, client={}",
|
||||||
@ -278,16 +262,6 @@ impl russh::server::Handler for SSHandle {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let user_id = user_model.uid.to_string();
|
|
||||||
if !self.rate_limiter.is_user_allowed(&user_id).await {
|
|
||||||
let msg = format!(
|
|
||||||
"User rate limit exceeded: {}, client: {}",
|
|
||||||
user_model.username, client_info
|
|
||||||
);
|
|
||||||
warn!(self.logger, "{}", msg);
|
|
||||||
return Err(russh::Error::NotAuthenticated);
|
|
||||||
}
|
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
self.logger,
|
self.logger,
|
||||||
"SSH authentication successful: user={}, client={}", user_model.username, client_info
|
"SSH authentication successful: user={}, client={}", user_model.username, client_info
|
||||||
@ -345,16 +319,6 @@ impl russh::server::Handler for SSHandle {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let user_id = user_model.uid.to_string();
|
|
||||||
if !self.rate_limiter.is_user_allowed(&user_id).await {
|
|
||||||
let msg = format!(
|
|
||||||
"User rate limit exceeded: {}, client: {}",
|
|
||||||
user_model.username, client_info
|
|
||||||
);
|
|
||||||
warn!(self.logger, "{}", msg);
|
|
||||||
return Err(russh::Error::NotAuthenticated);
|
|
||||||
}
|
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
self.logger,
|
self.logger,
|
||||||
"SSH authentication successful: user={}, client={}", user_model.username, client_info
|
"SSH authentication successful: user={}, client={}", user_model.username, client_info
|
||||||
@ -371,10 +335,7 @@ impl russh::server::Handler for SSHandle {
|
|||||||
channel: ChannelId,
|
channel: ChannelId,
|
||||||
_: &mut Session,
|
_: &mut Session,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
info!(self.logger, "channel_close";
|
info!(self.logger, "{}", format!("channel_close channel={:?} client={:?}", channel, self.client_addr));
|
||||||
"channel" => ?channel,
|
|
||||||
"client" => ?self.client_addr
|
|
||||||
);
|
|
||||||
self.cleanup_channel(channel);
|
self.cleanup_channel(channel);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -682,19 +643,6 @@ impl russh::server::Handler for SSHandle {
|
|||||||
return Err(russh::Error::Disconnect);
|
return Err(russh::Error::Disconnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = operator.uid.to_string();
|
|
||||||
let repo_path = format!("{}/{}", owner, &repo.repo_name);
|
|
||||||
if !self
|
|
||||||
.rate_limiter
|
|
||||||
.is_repo_access_allowed(&user_id, &repo_path)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
let msg = format!("Rate limit exceeded for repository access: {}", repo_path);
|
|
||||||
warn!(self.logger, "{}", format!("Repo access rate limit exceeded user={} repo={}", operator.username, repo.repo_name));
|
|
||||||
session.disconnect(Disconnect::ByApplication, &msg, "").ok();
|
|
||||||
return Err(russh::Error::Disconnect);
|
|
||||||
}
|
|
||||||
|
|
||||||
info!(self.logger, "{}", format!("Access granted user={} repo={} is_write={}", operator.username, repo.repo_name, is_write));
|
info!(self.logger, "{}", format!("Access granted user={} repo={} is_write={}", operator.username, repo.repo_name, is_write));
|
||||||
|
|
||||||
let repo_path = PathBuf::from(&repo.storage_path);
|
let repo_path = PathBuf::from(&repo.storage_path);
|
||||||
|
|||||||
@ -19,7 +19,6 @@ use std::time::Duration;
|
|||||||
|
|
||||||
pub mod authz;
|
pub mod authz;
|
||||||
pub mod handle;
|
pub mod handle;
|
||||||
pub mod rate_limit;
|
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -148,7 +147,6 @@ impl SSHHandle {
|
|||||||
|
|
||||||
// Start the rate limiter cleanup background task so the HashMap
|
// Start the rate limiter cleanup background task so the HashMap
|
||||||
// doesn't grow unbounded over time.
|
// doesn't grow unbounded over time.
|
||||||
let _cleanup = server.rate_limiter.clone().start_cleanup();
|
|
||||||
let ssh_port = self.app.ssh_port()?;
|
let ssh_port = self.app.ssh_port()?;
|
||||||
let bind_addr = format!("0.0.0.0:{}", ssh_port);
|
let bind_addr = format!("0.0.0.0:{}", ssh_port);
|
||||||
let public_host = self.app.ssh_domain()?;
|
let public_host = self.app.ssh_domain()?;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use crate::ssh::ReceiveSyncService;
|
use crate::ssh::ReceiveSyncService;
|
||||||
use crate::ssh::SshTokenService;
|
use crate::ssh::SshTokenService;
|
||||||
use crate::ssh::handle::SSHandle;
|
use crate::ssh::handle::SSHandle;
|
||||||
use crate::ssh::rate_limit::SshRateLimiter;
|
|
||||||
use db::cache::AppCache;
|
use db::cache::AppCache;
|
||||||
use db::database::AppDatabase;
|
use db::database::AppDatabase;
|
||||||
use deadpool_redis::cluster::Pool as RedisPool;
|
use deadpool_redis::cluster::Pool as RedisPool;
|
||||||
@ -9,14 +8,12 @@ use russh::server::Handler;
|
|||||||
use slog::{Logger, info, warn};
|
use slog::{Logger, info, warn};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
pub struct SSHServer {
|
pub struct SSHServer {
|
||||||
pub db: AppDatabase,
|
pub db: AppDatabase,
|
||||||
pub cache: AppCache,
|
pub cache: AppCache,
|
||||||
pub redis_pool: RedisPool,
|
pub redis_pool: RedisPool,
|
||||||
pub logger: Logger,
|
pub logger: Logger,
|
||||||
pub rate_limiter: Arc<SshRateLimiter>,
|
|
||||||
pub token_service: SshTokenService,
|
pub token_service: SshTokenService,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +30,6 @@ impl SSHServer {
|
|||||||
cache,
|
cache,
|
||||||
redis_pool,
|
redis_pool,
|
||||||
logger,
|
logger,
|
||||||
rate_limiter: Arc::new(SshRateLimiter::new()),
|
|
||||||
token_service,
|
token_service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,21 +39,12 @@ impl russh::server::Server for SSHServer {
|
|||||||
|
|
||||||
fn new_client(&mut self, addr: Option<SocketAddr>) -> Self::Handler {
|
fn new_client(&mut self, addr: Option<SocketAddr>) -> Self::Handler {
|
||||||
if let Some(addr) = addr {
|
if let Some(addr) = addr {
|
||||||
let ip = addr.ip().to_string();
|
|
||||||
info!(
|
info!(
|
||||||
self.logger,
|
self.logger,
|
||||||
"New SSH connection from {}:{}",
|
"New SSH connection from {}:{}",
|
||||||
ip,
|
addr.ip(),
|
||||||
addr.port()
|
addr.port()
|
||||||
);
|
);
|
||||||
|
|
||||||
let rate_limiter = self.rate_limiter.clone();
|
|
||||||
let logger = self.logger.clone();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
if !rate_limiter.is_ip_allowed(&ip).await {
|
|
||||||
warn!(logger, "{}", format!("IP rate limit exceeded ip={}", ip));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
info!(self.logger, "New SSH connection from unknown address");
|
info!(self.logger, "New SSH connection from unknown address");
|
||||||
}
|
}
|
||||||
@ -67,7 +54,6 @@ impl russh::server::Server for SSHServer {
|
|||||||
self.cache.clone(),
|
self.cache.clone(),
|
||||||
sync_service,
|
sync_service,
|
||||||
self.logger.clone(),
|
self.logger.clone(),
|
||||||
self.rate_limiter.clone(),
|
|
||||||
self.token_service.clone(),
|
self.token_service.clone(),
|
||||||
addr,
|
addr,
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user