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:
ZhenYi 2026-04-16 22:40:59 +08:00
parent 9368df54da
commit 0a998affbb
3 changed files with 2 additions and 70 deletions

View File

@ -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);

View File

@ -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()?;

View File

@ -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,
) )