@@ -4,7 +4,7 @@ use crate::messages::{
44use crate :: network:: { add_network_layer, MAX_PACKET_SIZE } ;
55use crate :: packet_sources:: { PacketSourceConf , PacketSourceTask } ;
66use crate :: shutdown;
7- use anyhow:: { Context , Result } ;
7+ use anyhow:: { bail , Context , Result } ;
88use std:: cmp:: max;
99use std:: { fs, io:: ErrorKind } ;
1010use tokio:: sync:: mpsc:: Sender ;
@@ -47,59 +47,63 @@ impl PacketSourceConf for TunConf {
4747}
4848
4949pub 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
105109pub struct TunTask {
0 commit comments