mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
fix(gateway): prevent routing loops (#6096)
In some weird conditions there might be routing loops in the gateway too, so this fixes it and it doesn't do any harm. Could be the cause behind [these logs](https://github.com/firezone/firezone/issues/6067#issuecomment-2259081958)
This commit is contained in:
2
rust/Cargo.lock
generated
2
rust/Cargo.lock
generated
@@ -1791,8 +1791,10 @@ dependencies = [
|
||||
"libc",
|
||||
"netlink-packet-core",
|
||||
"netlink-packet-route",
|
||||
"nix 0.28.0",
|
||||
"ring",
|
||||
"rtnetlink",
|
||||
"socket-factory",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-log",
|
||||
|
||||
@@ -25,7 +25,9 @@ tokio = { workspace = true, features = ["macros"] }
|
||||
libc = "0.2"
|
||||
netlink-packet-core = { version = "0.7", default-features = false }
|
||||
netlink-packet-route = { version = "0.19", default-features = false }
|
||||
nix = { version = "0.28.0", features = ["socket"] }
|
||||
rtnetlink = { workspace = true }
|
||||
socket-factory = { workspace = true }
|
||||
zbus = "4.4" # Can't use `zbus`'s `tokio` feature here, or it will break toast popups all the way over in `gui-client`.
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
use std::{io, net::SocketAddr};
|
||||
|
||||
use crate::FIREZONE_MARK;
|
||||
use nix::sys::socket::{setsockopt, sockopt};
|
||||
use socket_factory::{TcpSocket, UdpSocket};
|
||||
|
||||
const FIREZONE_DNS_CONTROL: &str = "FIREZONE_DNS_CONTROL";
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@@ -29,3 +35,15 @@ impl DnsControlMethod {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tcp_socket_factory(socket_addr: &SocketAddr) -> io::Result<TcpSocket> {
|
||||
let socket = socket_factory::tcp(socket_addr)?;
|
||||
setsockopt(&socket, sockopt::Mark, &FIREZONE_MARK)?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn udp_socket_factory(socket_addr: &SocketAddr) -> io::Result<UdpSocket> {
|
||||
let socket = socket_factory::udp(socket_addr)?;
|
||||
setsockopt(&socket, sockopt::Mark, &FIREZONE_MARK)?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
@@ -180,9 +180,13 @@ impl ClientTunnel {
|
||||
}
|
||||
|
||||
impl GatewayTunnel {
|
||||
pub fn new(private_key: StaticSecret) -> std::io::Result<Self> {
|
||||
pub fn new(
|
||||
private_key: StaticSecret,
|
||||
tcp_socket_factory: Arc<dyn SocketFactory<TcpSocket>>,
|
||||
udp_socket_factory: Arc<dyn SocketFactory<UdpSocket>>,
|
||||
) -> std::io::Result<Self> {
|
||||
Ok(Self {
|
||||
io: Io::new(Arc::new(socket_factory::tcp), Arc::new(socket_factory::udp))?,
|
||||
io: Io::new(tcp_socket_factory, udp_socket_factory)?,
|
||||
role_state: GatewayState::new(private_key, rand::random()),
|
||||
write_buf: Box::new([0u8; DEFAULT_MTU + 20 + 16]),
|
||||
ip4_read_buf: Box::new([0u8; MAX_UDP_SIZE]),
|
||||
|
||||
@@ -3,7 +3,10 @@ use anyhow::{Context, Result};
|
||||
use backoff::ExponentialBackoffBuilder;
|
||||
use clap::Parser;
|
||||
use connlib_shared::{get_user_agent, keypair, messages::Interface, LoginUrl, StaticSecret};
|
||||
use firezone_bin_shared::{setup_global_subscriber, TunDeviceManager};
|
||||
use firezone_bin_shared::{
|
||||
linux::{tcp_socket_factory, udp_socket_factory},
|
||||
setup_global_subscriber, TunDeviceManager,
|
||||
};
|
||||
use firezone_tunnel::{GatewayTunnel, IPV4_PEERS, IPV6_PEERS};
|
||||
|
||||
use futures::channel::mpsc;
|
||||
@@ -98,7 +101,11 @@ async fn get_firezone_id(env_id: Option<String>) -> Result<String> {
|
||||
}
|
||||
|
||||
async fn run(login: LoginUrl, private_key: StaticSecret) -> Result<Infallible> {
|
||||
let mut tunnel = GatewayTunnel::new(private_key)?;
|
||||
let mut tunnel = GatewayTunnel::new(
|
||||
private_key,
|
||||
Arc::new(tcp_socket_factory),
|
||||
Arc::new(udp_socket_factory),
|
||||
)?;
|
||||
let portal = PhoenixChannel::connect(
|
||||
Secret::new(login),
|
||||
get_user_agent(None, env!("CARGO_PKG_VERSION")),
|
||||
@@ -107,7 +114,7 @@ async fn run(login: LoginUrl, private_key: StaticSecret) -> Result<Infallible> {
|
||||
ExponentialBackoffBuilder::default()
|
||||
.with_max_elapsed_time(None)
|
||||
.build(),
|
||||
Arc::new(socket_factory::tcp),
|
||||
Arc::new(tcp_socket_factory),
|
||||
)?;
|
||||
|
||||
let (sender, receiver) = mpsc::channel::<Interface>(10);
|
||||
|
||||
@@ -2,36 +2,20 @@
|
||||
|
||||
use super::TOKEN_ENV_KEY;
|
||||
use anyhow::{bail, Result};
|
||||
use firezone_bin_shared::{BUNDLE_ID, FIREZONE_MARK};
|
||||
use nix::sys::socket::{setsockopt, sockopt};
|
||||
use socket_factory::{TcpSocket, UdpSocket};
|
||||
use std::{
|
||||
io,
|
||||
net::SocketAddr,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use firezone_bin_shared::BUNDLE_ID;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
// The Client currently must run as root to control DNS
|
||||
// Root group and user are used to check file ownership on the token
|
||||
const ROOT_GROUP: u32 = 0;
|
||||
const ROOT_USER: u32 = 0;
|
||||
|
||||
pub(crate) fn tcp_socket_factory(socket_addr: &SocketAddr) -> io::Result<TcpSocket> {
|
||||
let socket = socket_factory::tcp(socket_addr)?;
|
||||
setsockopt(&socket, sockopt::Mark, &FIREZONE_MARK)?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub(crate) fn udp_socket_factory(socket_addr: &SocketAddr) -> io::Result<UdpSocket> {
|
||||
let socket = socket_factory::udp(socket_addr)?;
|
||||
setsockopt(&socket, sockopt::Mark, &FIREZONE_MARK)?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub(crate) fn default_token_path() -> PathBuf {
|
||||
PathBuf::from("/etc").join(BUNDLE_ID).join("token")
|
||||
}
|
||||
|
||||
pub use firezone_bin_shared::linux::{tcp_socket_factory, udp_socket_factory};
|
||||
|
||||
pub(crate) fn check_token_permissions(path: &Path) -> Result<()> {
|
||||
let Ok(stat) = nix::sys::stat::fstatat(None, path, nix::fcntl::AtFlags::empty()) else {
|
||||
// File doesn't exist or can't be read
|
||||
|
||||
Reference in New Issue
Block a user