Manage the overlay interface instead of asking for it
The agent printed a list of `ip` commands and asked a human to run them. That is fragile in the way hand-held setup always is: a persistent TUN does not survive a reboot, a changed address allocation needs another manual round, and a run that died leaves a half-configured interface the next run trips over. On Linux the agent now creates the interface, sets the MTU, brings it up and assigns both overlay addresses itself, over netlink in process. No `ip` is invoked, so nothing this path does can be influenced by PATH, a shell, or anything a remote peer said. Cleanup stops being an action. The interface is tied to an open file descriptor and is deliberately not persistent, so the kernel removes it when the agent goes — cleanly, by panic, by SIGKILL or by power loss alike. That also retires `keep_addr_on_down` and `nodad`, which existed only because an interface nobody held open lost carrier. Anything still left behind is repaired rather than tripped over: an abandoned TUN is replaced along with its stale addresses. Two cases refuse instead of guessing — a link that is not a TUN, because a name collision is no reason to destroy somebody's bridge, and a TUN another process holds open, because that is a working overlay belonging to someone else. CAP_NET_ADMIN is kept out of the effective set except around the calls that use it. Two facts shape how: capabilities are per thread, and netlink checks the credentials of whichever thread calls sendmsg, which with an async client is the connection task rather than the caller. So netlink runs on one dedicated thread with a current-thread runtime where nothing is polled outside a block_on, and opening the TUN descriptor is synchronous with no await between the guard and its release. The decision of what to change is a pure function, tested on every platform; only the execution is behind the provisioner trait. macOS and Windows get an implementation that refuses with an explanation and falls back to attaching to a prepared interface, plus a mock host the tests drive the whole plugin lifecycle against. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
944d98389f
commit
b23e832a73
15 files changed
+2598
-150
No files matched your search
@@ -34,9 +34,11 @@
|
||||
//!
|
||||
//! The only part that needs privileges is the packet interface. With
|
||||
//! [`tun::MemoryTunFactory`] the whole data plane — handshake, encryption,
|
||||
//! routing, address ownership — runs and is tested with no privileges at all;
|
||||
//! `SystemTunFactory` swaps in a real interface when you want traffic to
|
||||
//! reach the operating system.
|
||||
//! routing, address ownership — runs and is tested with no privileges at all.
|
||||
//! For real traffic there are two ways in: [`provision::ManagedTunFactory`],
|
||||
//! where the agent creates and configures the interface itself over netlink
|
||||
//! and removes it again on exit, and `SystemTunFactory`, which attaches to an
|
||||
//! interface somebody else prepared and needs no privileges.
|
||||
//!
|
||||
//! See `docs/wireguard.md` for the full picture.
|
||||
|
||||
@@ -47,6 +49,7 @@ pub mod keys;
|
||||
pub mod overlay;
|
||||
pub mod packet;
|
||||
pub mod plugin;
|
||||
pub mod provision;
|
||||
pub mod store;
|
||||
pub mod tun;
|
||||
|
||||
@@ -61,9 +64,17 @@ pub use plugin::{
|
||||
DEFAULT_MTU, MIN_MTU, NetworkOverview, PeerOverview, WIREGUARD_OVERHEAD, WIREGUARD_PROTOCOL,
|
||||
WireguardConfig, WireguardPlugin,
|
||||
};
|
||||
pub use provision::{
|
||||
Changes, InterfacePlan, InterfaceProvisioner, InterfaceState, LinkKind, ManagedTunFactory,
|
||||
MockHost, MockProvisioner, Privilege, Provisioned, UnsupportedProvisioner, plan_changes,
|
||||
probe_net_admin,
|
||||
};
|
||||
pub use store::WgKeyStore;
|
||||
pub use tun::{MemoryTun, MemoryTunFactory, TunDevice, TunFactory, TunRequest, address_is_local};
|
||||
|
||||
#[cfg(all(feature = "tun-device", target_os = "linux"))]
|
||||
pub use provision::NetlinkProvisioner;
|
||||
|
||||
#[cfg(feature = "tun-device")]
|
||||
pub use tun::{
|
||||
Assigned, SystemTunFactory, interface_addresses, interface_exists, parse_if_inet6,
|
||||
|
||||
Reference in new issue
Block a user