mirror of
https://codeberg.org/icewind/netnsd.git
synced 2026-06-03 09:04:07 +02:00
use landlock to further lock down proxy process
This commit is contained in:
parent
d48f61b4fa
commit
63a800e20f
4 changed files with 82 additions and 21 deletions
|
|
@ -10,6 +10,12 @@ pub struct ForwardTarget {
|
|||
pub addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl ForwardTarget {
|
||||
pub fn port(&self) -> u16 {
|
||||
self.addr.port()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ForwardTarget> for SocketAddr {
|
||||
fn from(value: ForwardTarget) -> Self {
|
||||
value.addr
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@ use std::net::SocketAddr;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command};
|
||||
use std::thread::spawn;
|
||||
use landlock::{Access, AccessFs, AccessNet, NetPort, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, RulesetStatus, ABI};
|
||||
use nix::errno::Errno;
|
||||
use thiserror::Error;
|
||||
use tokio::runtime::Builder;
|
||||
use tokio::signal::ctrl_c;
|
||||
use tracing::error;
|
||||
use tracing::{error, info, warn};
|
||||
use uzers::{get_group_by_name, get_user_by_name};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
@ -144,31 +145,34 @@ pub fn proxy(
|
|||
}
|
||||
};
|
||||
|
||||
if let Some(listen_namespace) = listen_namespace
|
||||
&& let Err(error) = setns(listen_namespace, CloneFlags::CLONE_NEWNET)
|
||||
{
|
||||
error!(%error, "Failed to join listen network namespace for proxy");
|
||||
return Err(error.into());
|
||||
}
|
||||
|
||||
let proxy = match Proxy::listen(&source) {
|
||||
Ok(proxy) => proxy,
|
||||
Err(error) => {
|
||||
error!(%error, "Failed to listen to {source}");
|
||||
rt.block_on(async {
|
||||
if let Some(listen_namespace) = listen_namespace
|
||||
&& let Err(error) = setns(listen_namespace, CloneFlags::CLONE_NEWNET)
|
||||
{
|
||||
error!(%error, "Failed to join listen network namespace for proxy");
|
||||
return Err(error.into());
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(error) = setns(target_namespace, CloneFlags::CLONE_NEWNET) {
|
||||
error!(%error, "Failed to join target network namespace for proxy");
|
||||
return Err(error.into());
|
||||
}
|
||||
let proxy = match Proxy::listen(&source) {
|
||||
Ok(proxy) => proxy,
|
||||
Err(error) => {
|
||||
error!(%error, "Failed to listen to {source}");
|
||||
return Err(error.into());
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(error) = drop_to_nobody() {
|
||||
error!(%error, "Failed to drop privileges");
|
||||
}
|
||||
if let Err(error) = setns(target_namespace, CloneFlags::CLONE_NEWNET) {
|
||||
error!(%error, "Failed to join target network namespace for proxy");
|
||||
return Err(error.into());
|
||||
}
|
||||
|
||||
if let Err(error) = drop_to_nobody() {
|
||||
error!(%error, "Failed to drop privileges");
|
||||
}
|
||||
if let Err(error) = landlock(target.port()) {
|
||||
error!(%error, "Failed to apply landlock sandbox");
|
||||
}
|
||||
|
||||
rt.block_on(async {
|
||||
tokio::spawn(async move {
|
||||
let _ = ctrl_c().await;
|
||||
abort.abort();
|
||||
|
|
@ -193,4 +197,22 @@ fn drop_to_nobody() -> Result<(), Errno> {
|
|||
);
|
||||
|
||||
setgid(nobody_gid).and_then(|_| setuid(nobody_uid))
|
||||
}
|
||||
|
||||
fn landlock(port: u16) -> Result<(), RulesetError> {
|
||||
let abi = ABI::V6;
|
||||
let status = Ruleset::default()
|
||||
.handle_access(AccessNet::ConnectTcp)?
|
||||
.handle_access(AccessNet::BindTcp)?
|
||||
.handle_access(AccessFs::from_all(abi))?
|
||||
.create()?
|
||||
.add_rule(NetPort::new(port, AccessNet::ConnectTcp))?
|
||||
.restrict_self()?;
|
||||
|
||||
match status.ruleset {
|
||||
RulesetStatus::FullyEnforced => info!("Fully sandboxed."),
|
||||
RulesetStatus::PartiallyEnforced => warn!("Partially sandboxed."),
|
||||
RulesetStatus::NotEnforced => error!("Not sandboxed! Please update your kernel."),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue