Option to use other tun device file

This commit is contained in:
Dennis Schwerdel 2019-02-12 19:30:38 +01:00
parent 1ae8c9fda5
commit 5561ee412d
6 changed files with 37 additions and 5 deletions

View File

@ -17,6 +17,7 @@ use siphasher::sip::SipHasher24;
pub struct Config { pub struct Config {
pub device_type: Type, pub device_type: Type,
pub device_name: String, pub device_name: String,
pub device_path: Option<String>,
pub ifup: Option<String>, pub ifup: Option<String>,
pub ifdown: Option<String>, pub ifdown: Option<String>,
pub crypto: CryptoMethod, pub crypto: CryptoMethod,
@ -40,7 +41,7 @@ pub struct Config {
impl Default for Config { impl Default for Config {
fn default() -> Self { fn default() -> Self {
Config { Config {
device_type: Type::Tap, device_name: "vpncloud%d".to_string(), device_type: Type::Tap, device_name: "vpncloud%d".to_string(), device_path: None,
ifup: None, ifdown: None, ifup: None, ifdown: None,
crypto: CryptoMethod::ChaCha20, shared_key: None, crypto: CryptoMethod::ChaCha20, shared_key: None,
magic: None, magic: None,
@ -65,6 +66,9 @@ impl Config {
if let Some(val) = file.device_name { if let Some(val) = file.device_name {
self.device_name = val; self.device_name = val;
} }
if let Some(val) = file.device_path {
self.device_path = Some(val);
}
if let Some(val) = file.ifup { if let Some(val) = file.ifup {
self.ifup = Some(val); self.ifup = Some(val);
} }
@ -125,6 +129,9 @@ impl Config {
if let Some(val) = args.flag_device { if let Some(val) = args.flag_device {
self.device_name = val; self.device_name = val;
} }
if let Some(val) = args.flag_device_path {
self.device_path = Some(val);
}
if let Some(val) = args.flag_ifup { if let Some(val) = args.flag_ifup {
self.ifup = Some(val); self.ifup = Some(val);
} }
@ -213,6 +220,7 @@ impl Config {
pub struct ConfigFile { pub struct ConfigFile {
pub device_type: Option<Type>, pub device_type: Option<Type>,
pub device_name: Option<String>, pub device_name: Option<String>,
pub device_path: Option<String>,
pub ifup: Option<String>, pub ifup: Option<String>,
pub ifdown: Option<String>, pub ifdown: Option<String>,
pub crypto: Option<CryptoMethod>, pub crypto: Option<CryptoMethod>,

View File

@ -47,6 +47,7 @@ pub struct Device {
type_: Type, type_: Type,
} }
impl Device { impl Device {
/// Creates a new tun/tap device /// Creates a new tun/tap device
/// ///
@ -67,11 +68,12 @@ impl Device {
/// ///
/// # Panics /// # Panics
/// This method panics if the interface name is longer than 31 bytes. /// This method panics if the interface name is longer than 31 bytes.
pub fn new(ifname: &str, type_: Type) -> io::Result<Self> { pub fn new(ifname: &str, type_: Type, path: Option<&str>) -> io::Result<Self> {
let path = path.unwrap_or_else(|| Self::default_path(type_));
if type_ == Type::Dummy { if type_ == Type::Dummy {
return Self::dummy(ifname, "/dev/null", type_); return Self::dummy(ifname, path, type_);
} }
let fd = try!(fs::OpenOptions::new().read(true).write(true).open("/dev/net/tun")); let fd = try!(fs::OpenOptions::new().read(true).write(true).open(path));
// Add trailing \0 to interface name // Add trailing \0 to interface name
let mut ifname_string = String::with_capacity(32); let mut ifname_string = String::with_capacity(32);
ifname_string.push_str(ifname); ifname_string.push_str(ifname);
@ -95,6 +97,15 @@ impl Device {
} }
} }
/// Returns the default device path for a given type
#[inline]
pub fn default_path(type_: Type) -> &'static str {
match type_ {
Type::Tun | Type::Tap => "/dev/net/tun",
Type::Dummy => "/dev/null"
}
}
/// Returns the interface name of this device. /// Returns the interface name of this device.
#[inline] #[inline]
pub fn ifname(&self) -> &str { pub fn ifname(&self) -> &str {

View File

@ -68,6 +68,7 @@ static USAGE: &'static str = include_str!("usage.txt");
pub struct Args { pub struct Args {
flag_config: Option<String>, flag_config: Option<String>,
flag_type: Option<Type>, flag_type: Option<Type>,
flag_device_path: Option<String>,
flag_mode: Option<Mode>, flag_mode: Option<Mode>,
flag_shared_key: Option<String>, flag_shared_key: Option<String>,
flag_crypto: Option<CryptoMethod>, flag_crypto: Option<CryptoMethod>,
@ -204,7 +205,7 @@ impl<P: Protocol> AnyCloud<P> {
fn run<P: Protocol> (config: Config) { fn run<P: Protocol> (config: Config) {
let device = try_fail!(Device::new(&config.device_name, config.device_type), let device = try_fail!(Device::new(&config.device_name, config.device_type, config.device_path.as_ref().map(|s| s as &str)),
"Failed to open virtual {} interface {}: {}", config.device_type, config.device_name); "Failed to open virtual {} interface {}: {}", config.device_type, config.device_name);
info!("Opened device {}", device.ifname()); info!("Opened device {}", device.ifname());
let mut ranges = Vec::with_capacity(config.subnets.len()); let mut ranges = Vec::with_capacity(config.subnets.len());

View File

@ -446,6 +446,7 @@ fn config_file() {
let config_file = " let config_file = "
device_type: tun device_type: tun
device_name: vpncloud%d device_name: vpncloud%d
device_path: /dev/net/tun
magic: 0123ABCD magic: 0123ABCD
ifup: ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up ifup: ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up
ifdown: 'true' ifdown: 'true'
@ -470,6 +471,7 @@ stats_file: /var/log/vpncloud.stats
assert_eq!(serde_yaml::from_str::<ConfigFile>(config_file).unwrap(), ConfigFile{ assert_eq!(serde_yaml::from_str::<ConfigFile>(config_file).unwrap(), ConfigFile{
device_type: Some(Type::Tun), device_type: Some(Type::Tun),
device_name: Some("vpncloud%d".to_string()), device_name: Some("vpncloud%d".to_string()),
device_path: Some("/dev/net/tun".to_string()),
ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()), ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()),
ifdown: Some("true".to_string()), ifdown: Some("true".to_string()),
crypto: Some(CryptoMethod::AES256), crypto: Some(CryptoMethod::AES256),
@ -496,6 +498,7 @@ fn config_merge() {
config.merge_file(ConfigFile{ config.merge_file(ConfigFile{
device_type: Some(Type::Tun), device_type: Some(Type::Tun),
device_name: Some("vpncloud%d".to_string()), device_name: Some("vpncloud%d".to_string()),
device_path: None,
ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()), ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()),
ifdown: Some("true".to_string()), ifdown: Some("true".to_string()),
crypto: Some(CryptoMethod::AES256), crypto: Some(CryptoMethod::AES256),
@ -517,6 +520,7 @@ fn config_merge() {
assert_eq!(config, Config{ assert_eq!(config, Config{
device_type: Type::Tun, device_type: Type::Tun,
device_name: "vpncloud%d".to_string(), device_name: "vpncloud%d".to_string(),
device_path: None,
ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()), ifup: Some("ifconfig $IFNAME 10.0.1.1/16 mtu 1400 up".to_string()),
ifdown: Some("true".to_string()), ifdown: Some("true".to_string()),
magic: Some("0123ABCD".to_string()), magic: Some("0123ABCD".to_string()),
@ -539,6 +543,7 @@ fn config_merge() {
config.merge_args(Args{ config.merge_args(Args{
flag_type: Some(Type::Tap), flag_type: Some(Type::Tap),
flag_device: Some("vpncloud0".to_string()), flag_device: Some("vpncloud0".to_string()),
flag_device_path: Some("/dev/null".to_string()),
flag_ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()), flag_ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()),
flag_ifdown: Some("ifconfig $IFNAME down".to_string()), flag_ifdown: Some("ifconfig $IFNAME down".to_string()),
flag_crypto: Some(CryptoMethod::ChaCha20), flag_crypto: Some(CryptoMethod::ChaCha20),
@ -562,6 +567,7 @@ fn config_merge() {
assert_eq!(config, Config{ assert_eq!(config, Config{
device_type: Type::Tap, device_type: Type::Tap,
device_name: "vpncloud0".to_string(), device_name: "vpncloud0".to_string(),
device_path: Some("/dev/null".to_string()),
ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()), ifup: Some("ifconfig $IFNAME 10.0.1.2/16 mtu 1400 up".to_string()),
ifdown: Some("ifconfig $IFNAME down".to_string()), ifdown: Some("ifconfig $IFNAME down".to_string()),
magic: Some("hash:mynet".to_string()), magic: Some("hash:mynet".to_string()),

View File

@ -5,6 +5,7 @@ Options:
--config <file> Read configuration options from the --config <file> Read configuration options from the
specified file. specified file.
-t <type>, --type <type> Set the type of network ("tap" or "tun"). -t <type>, --type <type> Set the type of network ("tap" or "tun").
--device-path <path> Set the path of the base device.
-d <name>, --device <name> Name of the virtual device. -d <name>, --device <name> Name of the virtual device.
-m <mode>, --mode <mode> The mode of the VPN ("hub", "switch", -m <mode>, --mode <mode> The mode of the VPN ("hub", "switch",
"router", or "normal"). "router", or "normal").

View File

@ -25,6 +25,10 @@ vpncloud(1) -- Peer-to-peer VPN
Name of the virtual device. Any `%d` will be filled with a free number. Name of the virtual device. Any `%d` will be filled with a free number.
[default: `vpncloud%d`] [default: `vpncloud%d`]
* `--device-path <path>`:
The path of the base device inode, e.g. /dev/net/run.
* `-m <mode>`, `--mode <mode>`: * `-m <mode>`, `--mode <mode>`:
The mode of the VPN. The VPN can like a router, a switch or a hub. A **hub** The mode of the VPN. The VPN can like a router, a switch or a hub. A **hub**
@ -270,6 +274,7 @@ detailed descriptions of the options.
* `device_type`: Set the type of network. Same as `--type` * `device_type`: Set the type of network. Same as `--type`
* `device_name`: Name of the virtual device. Same as `--device` * `device_name`: Name of the virtual device. Same as `--device`
* `device_path`: Set the path of the base device. Same as `--device-path`
* `ifup`: A command to setup the network interface. Same as `--ifup` * `ifup`: A command to setup the network interface. Same as `--ifup`
* `ifdown`: A command to bring down the network interface. Same as `--ifdown` * `ifdown`: A command to bring down the network interface. Same as `--ifdown`
* `crypto`: The encryption method to use. Same as `--crypto` * `crypto`: The encryption method to use. Same as `--crypto`