Skip to content

Commit 78c8b2c

Browse files
committed
simplify logic
1 parent 2b26ddd commit 78c8b2c

File tree

1 file changed

+48
-44
lines changed

1 file changed

+48
-44
lines changed

src/packet_sources/tun.rs

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::messages::{
44
use crate::network::{add_network_layer, MAX_PACKET_SIZE};
55
use crate::packet_sources::{PacketSourceConf, PacketSourceTask};
66
use crate::shutdown;
7-
use anyhow::{Context, Result};
7+
use anyhow::{bail, Context, Result};
88
use std::cmp::max;
99
use std::{fs, io::ErrorKind};
1010
use tokio::sync::mpsc::Sender;
@@ -47,59 +47,63 @@ impl PacketSourceConf for TunConf {
4747
}
4848

4949
pub fn create_tun_device(tun_name: Option<String>) -> Result<(tun::AsyncDevice, String)> {
50-
let mut persistent_config = tun::Configuration::default();
51-
if let Some(tun_name) = &tun_name {
52-
persistent_config.tun_name(tun_name);
53-
}
54-
let mut config = persistent_config.clone();
50+
let mut config = tun::Configuration::default();
5551
config.mtu(MAX_PACKET_SIZE as u16);
5652
// Setting a local address and a destination is required on Linux.
5753
config.address("169.254.0.1");
5854
// config.netmask("0.0.0.0");
5955
// config.destination("169.254.0.1");
6056
config.up();
57+
if let Some(tun_name) = &tun_name {
58+
config.tun_name(tun_name);
59+
}
6160

62-
let (device_result, is_new_device) = match tun::create_as_async(&config) {
63-
// If we are instructed to create a tun device with a specific name, it is possible that the
64-
// user wants us to reuse an existing persistent tun interface. A persistent tun interface
65-
// is usually pre-configured, so that mitmproxy does not need to perform configuration, and
66-
// therefore does not need CAP_NET_ADMIN or sudo.
67-
//
68-
// The default `config` will set MTU and address etc which *do* require CAP_NET_ADMIN, which
69-
// will result in PermissionDenied in the non-privileged context. To deal with the case of
70-
// pre-configured persistent interface, we retry `create_as_async` without the MTU/address
71-
// settings.
72-
Err(tun::Error::Io(e)) if e.kind() == ErrorKind::PermissionDenied && tun_name.is_some() => {
73-
(tun::create_as_async(&persistent_config), false)
74-
}
75-
result => (result, true),
76-
};
77-
let device = device_result.context("Failed to create TUN device")?;
78-
let tun_name = device.tun_name().context("Failed to get TUN name")?;
79-
80-
if is_new_device {
81-
// In case of a persistent tun device, these are supposed to be pre-configured,
82-
// and we should not have permission to write these. So don't try.
83-
84-
if let Err(e) = disable_rp_filter(&tun_name) {
85-
log::error!("failed to set rp_filter: {e}");
61+
match tun::create_as_async(&config) {
62+
Ok(device) => {
63+
let tun_name = device.tun_name().context("Failed to get TUN name")?;
64+
configure_device(&tun_name);
65+
Ok((device, tun_name))
8666
}
87-
if let Err(e) = fs::write(
88-
format!("/proc/sys/net/ipv4/conf/{tun_name}/route_localnet"),
89-
"1",
90-
) {
91-
log::error!("Failed to enable route_localnet: {e}");
92-
}
93-
// Update accept_local so that injected packets with a local address (e.g. 127.0.0.1)
94-
// as source address are accepted.
95-
if let Err(e) = fs::write(
96-
format!("/proc/sys/net/ipv4/conf/{tun_name}/accept_local"),
97-
"1",
98-
) {
99-
log::error!("Failed to enable accept_local: {e}");
67+
Err(tun::Error::Io(e)) if e.kind() == ErrorKind::PermissionDenied => {
68+
// If we are instructed to create a tun device with a specific name, it is possible that the
69+
// user wants us to reuse an existing persistent tun interface. A persistent tun interface
70+
// is usually pre-configured, so that mitmproxy does not need to perform configuration, and
71+
// therefore does not need CAP_NET_ADMIN or sudo.
72+
//
73+
// The default `config` will set MTU and address etc which *do* require CAP_NET_ADMIN, which
74+
// will result in PermissionDenied in the non-privileged context. To deal with the case of
75+
// pre-configured persistent interface, we retry `create_as_async` without the MTU/address
76+
// settings.
77+
if let Some(tun_name) = tun_name {
78+
tun::create_as_async(tun::Configuration::default().tun_name(&tun_name))
79+
.map(|d| (d, tun_name))
80+
} else {
81+
Err(tun::Error::Io(e))
82+
}
10083
}
84+
Err(e) => Err(e),
85+
}
86+
.context("Failed to create TUN device")
87+
}
88+
89+
fn configure_device(tun_name: &str) {
90+
if let Err(e) = disable_rp_filter(&tun_name) {
91+
log::error!("failed to set rp_filter: {e}");
92+
}
93+
if let Err(e) = fs::write(
94+
format!("/proc/sys/net/ipv4/conf/{tun_name}/route_localnet"),
95+
"1",
96+
) {
97+
log::error!("Failed to enable route_localnet: {e}");
98+
}
99+
// Update accept_local so that injected packets with a local address (e.g. 127.0.0.1)
100+
// as source address are accepted.
101+
if let Err(e) = fs::write(
102+
format!("/proc/sys/net/ipv4/conf/{tun_name}/accept_local"),
103+
"1",
104+
) {
105+
log::error!("Failed to enable accept_local: {e}");
101106
}
102-
Ok((device, tun_name))
103107
}
104108

105109
pub struct TunTask {

0 commit comments

Comments
 (0)