@@ -6,7 +6,7 @@ use crate::packet_sources::{PacketSourceConf, PacketSourceTask};
66use crate :: shutdown;
77use anyhow:: { Context , Result } ;
88use std:: cmp:: max;
9- use std:: fs ;
9+ use std:: { fs , io :: ErrorKind } ;
1010use tokio:: sync:: mpsc:: Sender ;
1111use tokio:: sync:: mpsc:: { Permit , Receiver , UnboundedReceiver } ;
1212use tun:: AbstractDevice ;
@@ -47,36 +47,57 @@ impl PacketSourceConf for TunConf {
4747}
4848
4949pub fn create_tun_device ( tun_name : Option < String > ) -> Result < ( tun:: AsyncDevice , String ) > {
50- let mut config = tun:: Configuration :: default ( ) ;
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 ( ) ;
5155 config. mtu ( MAX_PACKET_SIZE as u16 ) ;
5256 // Setting a local address and a destination is required on Linux.
5357 config. address ( "169.254.0.1" ) ;
5458 // config.netmask("0.0.0.0");
5559 // config.destination("169.254.0.1");
5660 config. up ( ) ;
57- if let Some ( tun_name) = tun_name {
58- config. tun_name ( & tun_name) ;
59- }
6061
61- let device = tun:: create_as_async ( & config) . context ( "Failed to create TUN device" ) ?;
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" ) ?;
6278 let tun_name = device. tun_name ( ) . context ( "Failed to get TUN name" ) ?;
6379
64- if let Err ( e) = disable_rp_filter ( & tun_name) {
65- log:: error!( "failed to set rp_filter: {e}" ) ;
66- }
67- if let Err ( e) = fs:: write (
68- format ! ( "/proc/sys/net/ipv4/conf/{tun_name}/route_localnet" ) ,
69- "1" ,
70- ) {
71- log:: error!( "Failed to enable route_localnet: {e}" ) ;
72- }
73- // Update accept_local so that injected packets with a local address (e.g. 127.0.0.1)
74- // as source address are accepted.
75- if let Err ( e) = fs:: write (
76- format ! ( "/proc/sys/net/ipv4/conf/{tun_name}/accept_local" ) ,
77- "1" ,
78- ) {
79- log:: error!( "Failed to enable accept_local: {e}" ) ;
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}" ) ;
86+ }
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}" ) ;
100+ }
80101 }
81102 Ok ( ( device, tun_name) )
82103}
0 commit comments