mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
udp, http: move privilege drop code into aquatic_common
This commit is contained in:
parent
ead7650d41
commit
d6d5cc78b7
11 changed files with 72 additions and 87 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -79,6 +79,7 @@ dependencies = [
|
||||||
"hashbrown 0.11.2",
|
"hashbrown 0.11.2",
|
||||||
"hex",
|
"hex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"privdrop",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
@ -179,7 +180,6 @@ dependencies = [
|
||||||
"mimalloc",
|
"mimalloc",
|
||||||
"mio",
|
"mio",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"privdrop",
|
|
||||||
"quickcheck",
|
"quickcheck",
|
||||||
"quickcheck_macros",
|
"quickcheck_macros",
|
||||||
"rand",
|
"rand",
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,6 @@ arc-swap = "1"
|
||||||
hashbrown = "0.11.2"
|
hashbrown = "0.11.2"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
indexmap = "1"
|
indexmap = "1"
|
||||||
|
privdrop = "0.5"
|
||||||
rand = { version = "0.8", features = ["small_rng"] }
|
rand = { version = "0.8", features = ["small_rng"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use rand::Rng;
|
||||||
|
|
||||||
pub mod access_list;
|
pub mod access_list;
|
||||||
pub mod cpu_pinning;
|
pub mod cpu_pinning;
|
||||||
|
pub mod privileges;
|
||||||
|
|
||||||
/// Peer or connection valid until this instant
|
/// Peer or connection valid until this instant
|
||||||
///
|
///
|
||||||
|
|
|
||||||
59
aquatic_common/src/privileges.rs
Normal file
59
aquatic_common/src/privileges.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
use std::{sync::{Arc, atomic::{AtomicUsize, Ordering}}, time::Duration};
|
||||||
|
|
||||||
|
use privdrop::PrivDrop;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct PrivilegeConfig {
|
||||||
|
/// Chroot and switch user after binding to sockets
|
||||||
|
pub drop_privileges: bool,
|
||||||
|
/// Chroot to this path
|
||||||
|
pub chroot_path: String,
|
||||||
|
/// User to switch to after chrooting
|
||||||
|
pub user: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PrivilegeConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
drop_privileges: false,
|
||||||
|
chroot_path: ".".to_string(),
|
||||||
|
user: "nobody".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop_privileges_after_socket_binding(
|
||||||
|
config: &PrivilegeConfig,
|
||||||
|
num_bound_sockets: Arc<AtomicUsize>,
|
||||||
|
target_num: usize,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
if config.drop_privileges {
|
||||||
|
let mut counter = 0usize;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let num_bound = num_bound_sockets.load(Ordering::SeqCst);
|
||||||
|
|
||||||
|
if num_bound == target_num {
|
||||||
|
PrivDrop::default()
|
||||||
|
.chroot(config.chroot_path.clone())
|
||||||
|
.user(config.user.clone())
|
||||||
|
.apply()?;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
::std::thread::sleep(Duration::from_millis(10));
|
||||||
|
|
||||||
|
counter += 1;
|
||||||
|
|
||||||
|
if counter == 500 {
|
||||||
|
panic!("Sockets didn't bind in time for privilege drop.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{net::SocketAddr, path::PathBuf};
|
use std::{net::SocketAddr, path::PathBuf};
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessListConfig;
|
use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig};
|
||||||
use aquatic_common::cpu_pinning::CpuPinningConfig;
|
use aquatic_common::cpu_pinning::CpuPinningConfig;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -94,17 +94,6 @@ pub struct StatisticsConfig {
|
||||||
pub interval: u64,
|
pub interval: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct PrivilegeConfig {
|
|
||||||
/// Chroot and switch user after binding to sockets
|
|
||||||
pub drop_privileges: bool,
|
|
||||||
/// Chroot to this path
|
|
||||||
pub chroot_path: String,
|
|
||||||
/// User to switch to after chrooting
|
|
||||||
pub user: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -118,7 +107,7 @@ impl Default for Config {
|
||||||
statistics: StatisticsConfig::default(),
|
statistics: StatisticsConfig::default(),
|
||||||
privileges: PrivilegeConfig::default(),
|
privileges: PrivilegeConfig::default(),
|
||||||
access_list: AccessListConfig::default(),
|
access_list: AccessListConfig::default(),
|
||||||
cpu_pinning: CpuPinningConfig::default(),
|
cpu_pinning: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -171,16 +160,6 @@ impl Default for StatisticsConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PrivilegeConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
drop_privileges: false,
|
|
||||||
chroot_path: ".".to_string(),
|
|
||||||
user: "nobody".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TlsConfig {
|
impl Default for TlsConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use std::{
|
||||||
sync::{atomic::AtomicUsize, Arc},
|
sync::{atomic::AtomicUsize, Arc},
|
||||||
};
|
};
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessList;
|
use aquatic_common::{access_list::AccessList, privileges::drop_privileges_after_socket_binding};
|
||||||
use glommio::{channels::channel_mesh::MeshBuilder, prelude::*};
|
use glommio::{channels::channel_mesh::MeshBuilder, prelude::*};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
@ -94,7 +94,7 @@ pub fn run(config: Config) -> anyhow::Result<()> {
|
||||||
executors.push(executor);
|
executors.push(executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop_privileges_after_socket_binding(&config, num_bound_sockets).unwrap();
|
drop_privileges_after_socket_binding(&config.privileges, num_bound_sockets, config.socket_workers).unwrap();
|
||||||
|
|
||||||
for executor in executors {
|
for executor in executors {
|
||||||
executor
|
executor
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ indexmap = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mimalloc = { version = "0.1", default-features = false }
|
mimalloc = { version = "0.1", default-features = false }
|
||||||
parking_lot = "0.11"
|
parking_lot = "0.11"
|
||||||
privdrop = "0.5"
|
|
||||||
rand = { version = "0.8", features = ["small_rng"] }
|
rand = { version = "0.8", features = ["small_rng"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessListConfig;
|
use aquatic_common::{access_list::AccessListConfig, privileges::PrivilegeConfig};
|
||||||
use aquatic_common::cpu_pinning::CpuPinningConfig;
|
use aquatic_common::cpu_pinning::CpuPinningConfig;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
@ -99,17 +99,6 @@ pub struct CleaningConfig {
|
||||||
pub max_connection_age: u64,
|
pub max_connection_age: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct PrivilegeConfig {
|
|
||||||
/// Chroot and switch user after binding to sockets
|
|
||||||
pub drop_privileges: bool,
|
|
||||||
/// Chroot to this path
|
|
||||||
pub chroot_path: String,
|
|
||||||
/// User to switch to after chrooting
|
|
||||||
pub user: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -177,13 +166,3 @@ impl Default for CleaningConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PrivilegeConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
drop_privileges: false,
|
|
||||||
chroot_path: ".".to_string(),
|
|
||||||
user: "nobody".to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use std::sync::{atomic::AtomicUsize, Arc};
|
use std::sync::{atomic::AtomicUsize, Arc};
|
||||||
|
|
||||||
use aquatic_common::access_list::AccessList;
|
use aquatic_common::access_list::AccessList;
|
||||||
|
use aquatic_common::privileges::drop_privileges_after_socket_binding;
|
||||||
use glommio::channels::channel_mesh::MeshBuilder;
|
use glommio::channels::channel_mesh::MeshBuilder;
|
||||||
use glommio::prelude::*;
|
use glommio::prelude::*;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::drop_privileges_after_socket_binding;
|
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
|
|
@ -88,7 +88,7 @@ pub fn run(config: Config) -> anyhow::Result<()> {
|
||||||
executors.push(executor);
|
executors.push(executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_privileges_after_socket_binding(&config, num_bound_sockets).unwrap();
|
drop_privileges_after_socket_binding(&config.privileges, num_bound_sockets, config.socket_workers).unwrap();
|
||||||
|
|
||||||
for executor in executors {
|
for executor in executors {
|
||||||
executor
|
executor
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ pub mod glommio;
|
||||||
pub mod mio;
|
pub mod mio;
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use privdrop::PrivDrop;
|
|
||||||
|
|
||||||
pub const APP_NAME: &str = "aquatic_udp: UDP BitTorrent tracker";
|
pub const APP_NAME: &str = "aquatic_udp: UDP BitTorrent tracker";
|
||||||
|
|
||||||
|
|
@ -28,36 +27,4 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
|
||||||
mio::run(config)
|
mio::run(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_privileges_after_socket_binding(
|
|
||||||
config: &Config,
|
|
||||||
num_bound_sockets: Arc<AtomicUsize>,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
if config.privileges.drop_privileges {
|
|
||||||
let mut counter = 0usize;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let sockets = num_bound_sockets.load(Ordering::SeqCst);
|
|
||||||
|
|
||||||
if sockets == config.socket_workers {
|
|
||||||
PrivDrop::default()
|
|
||||||
.chroot(config.privileges.chroot_path.clone())
|
|
||||||
.user(config.privileges.user.clone())
|
|
||||||
.apply()?;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
::std::thread::sleep(Duration::from_millis(10));
|
|
||||||
|
|
||||||
counter += 1;
|
|
||||||
|
|
||||||
if counter == 500 {
|
|
||||||
panic!("Sockets didn't bind in time for privilege drop.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use aquatic_common::privileges::drop_privileges_after_socket_binding;
|
||||||
use crossbeam_channel::unbounded;
|
use crossbeam_channel::unbounded;
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
|
|
@ -16,7 +17,6 @@ pub mod tasks;
|
||||||
use aquatic_common::access_list::{AccessListArcSwap, AccessListMode, AccessListQuery};
|
use aquatic_common::access_list::{AccessListArcSwap, AccessListMode, AccessListQuery};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::drop_privileges_after_socket_binding;
|
|
||||||
|
|
||||||
use common::State;
|
use common::State;
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ pub fn run(config: Config) -> ::anyhow::Result<()> {
|
||||||
|
|
||||||
start_workers(config.clone(), state.clone(), num_bound_sockets.clone())?;
|
start_workers(config.clone(), state.clone(), num_bound_sockets.clone())?;
|
||||||
|
|
||||||
drop_privileges_after_socket_binding(&config, num_bound_sockets).unwrap();
|
drop_privileges_after_socket_binding(&config.privileges, num_bound_sockets, config.socket_workers).unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
::std::thread::sleep(Duration::from_secs(config.cleaning.interval));
|
::std::thread::sleep(Duration::from_secs(config.cleaning.interval));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue