@@ -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 ;
@@ -54,14 +54,40 @@ pub fn create_tun_device(tun_name: Option<String>) -> Result<(tun::AsyncDevice,
5454 // config.netmask("0.0.0.0");
5555 // config.destination("169.254.0.1");
5656 config. up ( ) ;
57- if let Some ( tun_name) = tun_name {
58- config. tun_name ( & tun_name) ;
57+ if let Some ( tun_name) = & tun_name {
58+ config. tun_name ( tun_name) ;
5959 }
6060
61- let device = tun:: create_as_async ( & config) . context ( "Failed to create TUN device" ) ?;
62- let tun_name = device. tun_name ( ) . context ( "Failed to get TUN name" ) ?;
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) )
66+ }
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+ }
83+ }
84+ Err ( e) => Err ( e) ,
85+ }
86+ . context ( "Failed to create TUN device" )
87+ }
6388
64- if let Err ( e) = disable_rp_filter ( & tun_name) {
89+ fn configure_device ( tun_name : & str ) {
90+ if let Err ( e) = disable_rp_filter ( tun_name) {
6591 log:: error!( "failed to set rp_filter: {e}" ) ;
6692 }
6793 if let Err ( e) = fs:: write (
@@ -78,7 +104,6 @@ pub fn create_tun_device(tun_name: Option<String>) -> Result<(tun::AsyncDevice,
78104 ) {
79105 log:: error!( "Failed to enable accept_local: {e}" ) ;
80106 }
81- Ok ( ( device, tun_name) )
82107}
83108
84109pub struct TunTask {
0 commit comments