mirror of https://github.com/dswd/vpncloud.git
Offer to migrate old configs
This commit is contained in:
parent
16da58b8df
commit
ca0e5e9791
|
@ -10,6 +10,7 @@ This project follows [semantic versioning](http://semver.org).
|
||||||
- [added] Automatically set optimal MTU on interface
|
- [added] Automatically set optimal MTU on interface
|
||||||
- [added] Warning for disabled or loose rp_filter setting
|
- [added] Warning for disabled or loose rp_filter setting
|
||||||
- [added] Add --fix-rp-filter to fix rp filter settings
|
- [added] Add --fix-rp-filter to fix rp filter settings
|
||||||
|
- [added] Offer to migrate old configs
|
||||||
- [changed] **Complete change of network protocol**
|
- [changed] **Complete change of network protocol**
|
||||||
- [changed] Negotiate crypto method per peer, select best method
|
- [changed] Negotiate crypto method per peer, select best method
|
||||||
- [changed] Make encryption the default, no encryption must be stated explicitly
|
- [changed] Make encryption the default, no encryption must be stated explicitly
|
||||||
|
|
|
@ -319,9 +319,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
version = "0.5.18"
|
version = "0.5.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
|
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
|
|
|
@ -454,7 +454,11 @@ pub struct Args {
|
||||||
|
|
||||||
/// Print logs also to this file
|
/// Print logs also to this file
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
pub log_file: Option<String>
|
pub log_file: Option<String>,
|
||||||
|
|
||||||
|
/// Migrate an old config file
|
||||||
|
#[structopt(long, alias = "migrate", requires = "config")]
|
||||||
|
pub migrate_config: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
|
||||||
|
|
|
@ -277,16 +277,16 @@ impl<P: Payload> PeerCrypto<P> {
|
||||||
if let Some(ref core) = self.core {
|
if let Some(ref core) = self.core {
|
||||||
let algo = core.algorithm();
|
let algo = core.algorithm();
|
||||||
if algo == &aead::CHACHA20_POLY1305 {
|
if algo == &aead::CHACHA20_POLY1305 {
|
||||||
"chacha20"
|
"CHACHA20"
|
||||||
} else if algo == &aead::AES_128_GCM {
|
} else if algo == &aead::AES_128_GCM {
|
||||||
"aes128"
|
"AES128"
|
||||||
} else if algo == &aead::AES_256_GCM {
|
} else if algo == &aead::AES_256_GCM {
|
||||||
"aes256"
|
"AES256"
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"plain"
|
"PLAIN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
src/main.rs
34
src/main.rs
|
@ -23,6 +23,7 @@ pub mod device;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
|
pub mod oldconfig;
|
||||||
pub mod payload;
|
pub mod payload;
|
||||||
pub mod poll;
|
pub mod poll;
|
||||||
pub mod port_forwarding;
|
pub mod port_forwarding;
|
||||||
|
@ -49,8 +50,9 @@ use crate::{
|
||||||
config::{Args, Config},
|
config::{Args, Config},
|
||||||
crypto::Crypto,
|
crypto::Crypto,
|
||||||
device::{Device, TunTapDevice, Type},
|
device::{Device, TunTapDevice, Type},
|
||||||
port_forwarding::PortForwarding,
|
oldconfig::OldConfigFile,
|
||||||
payload::Protocol,
|
payload::Protocol,
|
||||||
|
port_forwarding::PortForwarding,
|
||||||
util::SystemTimeSource
|
util::SystemTimeSource
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -242,11 +244,39 @@ fn main() {
|
||||||
} else {
|
} else {
|
||||||
log::LevelFilter::Info
|
log::LevelFilter::Info
|
||||||
});
|
});
|
||||||
|
if args.migrate_config {
|
||||||
|
let file = args.config.unwrap();
|
||||||
|
info!("Trying to convert from old config format");
|
||||||
|
let f = try_fail!(File::open(&file), "Failed to open config file: {:?}");
|
||||||
|
let config_file_old: OldConfigFile =
|
||||||
|
try_fail!(serde_yaml::from_reader(f), "Config file not valid for version 1: {:?}");
|
||||||
|
let new_config = config_file_old.convert();
|
||||||
|
info!("Successfully converted from old format");
|
||||||
|
info!("Renaming original file to {}.orig", file);
|
||||||
|
try_fail!(fs::rename(&file, format!("{}.orig", file)), "Failed to rename original file: {:?}");
|
||||||
|
info!("Writing new config back into {}", file);
|
||||||
|
let f = try_fail!(File::create(&file), "Failed to open config file: {:?}");
|
||||||
|
try_fail!(fs::set_permissions(&file, fs::Permissions::from_mode(0o600)), "Failed to set permissions on file: {:?}");
|
||||||
|
try_fail!(serde_yaml::to_writer(f, &new_config), "Failed to write converted config: {:?}");
|
||||||
|
return
|
||||||
|
}
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
if let Some(ref file) = args.config {
|
if let Some(ref file) = args.config {
|
||||||
info!("Reading config file '{}'", file);
|
info!("Reading config file '{}'", file);
|
||||||
let f = try_fail!(File::open(file), "Failed to open config file: {:?}");
|
let f = try_fail!(File::open(file), "Failed to open config file: {:?}");
|
||||||
let config_file = try_fail!(serde_yaml::from_reader(f), "Failed to load config file: {:?}");
|
let config_file = match serde_yaml::from_reader(f) {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(err) => {
|
||||||
|
error!("Failed to read config file: {}", err);
|
||||||
|
info!("Trying to convert from old config format");
|
||||||
|
let f = try_fail!(File::open(file), "Failed to open config file: {:?}");
|
||||||
|
let config_file_old: OldConfigFile =
|
||||||
|
try_fail!(serde_yaml::from_reader(f), "Config file is neither version 2 nor version 1: {:?}");
|
||||||
|
let new_config = config_file_old.convert();
|
||||||
|
info!("Successfully converted from old format, please migrate your config using migrate-config");
|
||||||
|
new_config
|
||||||
|
}
|
||||||
|
};
|
||||||
config.merge_file(config_file)
|
config.merge_file(config_file)
|
||||||
}
|
}
|
||||||
config.merge_args(args);
|
config.merge_args(args);
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
use super::{device::Type, types::Mode, util::Duration};
|
||||||
|
use crate::config::{ConfigFile, ConfigFileBeacon, ConfigFileDevice, ConfigFileStatsd, CryptoConfig};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
|
||||||
|
pub enum OldCryptoMethod {
|
||||||
|
#[serde(rename = "chacha20")]
|
||||||
|
ChaCha20,
|
||||||
|
#[serde(rename = "aes256")]
|
||||||
|
AES256,
|
||||||
|
#[serde(rename = "aes128")]
|
||||||
|
AES128
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
|
||||||
|
pub struct OldConfigFile {
|
||||||
|
#[serde(alias = "device-type")]
|
||||||
|
pub device_type: Option<Type>,
|
||||||
|
#[serde(alias = "device-name")]
|
||||||
|
pub device_name: Option<String>,
|
||||||
|
#[serde(alias = "device-path")]
|
||||||
|
pub device_path: Option<String>,
|
||||||
|
pub ifup: Option<String>,
|
||||||
|
pub ifdown: Option<String>,
|
||||||
|
pub crypto: Option<OldCryptoMethod>,
|
||||||
|
#[serde(alias = "shared-key")]
|
||||||
|
pub shared_key: Option<String>,
|
||||||
|
pub magic: Option<String>,
|
||||||
|
pub port: Option<u16>,
|
||||||
|
pub listen: Option<String>,
|
||||||
|
pub peers: Option<Vec<String>>,
|
||||||
|
#[serde(alias = "peer-timeout")]
|
||||||
|
pub peer_timeout: Option<Duration>,
|
||||||
|
pub keepalive: Option<Duration>,
|
||||||
|
#[serde(alias = "beacon-store")]
|
||||||
|
pub beacon_store: Option<String>,
|
||||||
|
#[serde(alias = "beacon-load")]
|
||||||
|
pub beacon_load: Option<String>,
|
||||||
|
#[serde(alias = "beacon-interval")]
|
||||||
|
pub beacon_interval: Option<Duration>,
|
||||||
|
pub mode: Option<Mode>,
|
||||||
|
#[serde(alias = "dst-timeout")]
|
||||||
|
pub dst_timeout: Option<Duration>,
|
||||||
|
pub subnets: Option<Vec<String>>,
|
||||||
|
#[serde(alias = "port-forwarding")]
|
||||||
|
pub port_forwarding: Option<bool>,
|
||||||
|
#[serde(alias = "pid-file")]
|
||||||
|
pub pid_file: Option<String>,
|
||||||
|
#[serde(alias = "stats-file")]
|
||||||
|
pub stats_file: Option<String>,
|
||||||
|
#[serde(alias = "statsd-server")]
|
||||||
|
pub statsd_server: Option<String>,
|
||||||
|
#[serde(alias = "statsd-prefix")]
|
||||||
|
pub statsd_prefix: Option<String>,
|
||||||
|
pub user: Option<String>,
|
||||||
|
pub group: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OldConfigFile {
|
||||||
|
#[allow(clippy::or_fun_call)]
|
||||||
|
pub fn convert(self) -> ConfigFile {
|
||||||
|
if self.device_type.is_none() {
|
||||||
|
warn!("The default device type changed from TAP to TUN")
|
||||||
|
}
|
||||||
|
if self.ifup.is_some() {
|
||||||
|
info!("There is a new option --ip that can handle most use cases of --ifup")
|
||||||
|
}
|
||||||
|
info!("The converted config enables all available encryption algorithms");
|
||||||
|
if self.shared_key.is_none() {
|
||||||
|
warn!("Operation without a password is no longer supported, password set to 'none'");
|
||||||
|
}
|
||||||
|
if self.magic.is_some() {
|
||||||
|
warn!("The magic header functionality is no longer supported")
|
||||||
|
}
|
||||||
|
if self.listen.is_some() && self.port.is_some() {
|
||||||
|
warn!("The port option is no longer available, using listen instead")
|
||||||
|
}
|
||||||
|
if self.peer_timeout.is_none() {
|
||||||
|
info!("The default peer timeout changed from 10 minutes to 5 minutes")
|
||||||
|
}
|
||||||
|
warn!("Even with a converted config file version 2 nodes can not communicate with version 1 nodes");
|
||||||
|
ConfigFile {
|
||||||
|
auto_claim: None,
|
||||||
|
beacon: Some(ConfigFileBeacon {
|
||||||
|
interval: self.beacon_interval,
|
||||||
|
load: self.beacon_load,
|
||||||
|
store: self.beacon_store,
|
||||||
|
password: self.shared_key.clone()
|
||||||
|
}),
|
||||||
|
claims: self.subnets,
|
||||||
|
crypto: CryptoConfig {
|
||||||
|
algorithms: vec![],
|
||||||
|
password: Some(self.shared_key.unwrap_or_else(|| "none".to_string())),
|
||||||
|
private_key: None,
|
||||||
|
public_key: None,
|
||||||
|
trusted_keys: vec![]
|
||||||
|
},
|
||||||
|
device: Some(ConfigFileDevice {
|
||||||
|
fix_rp_filter: None,
|
||||||
|
name: self.device_name,
|
||||||
|
path: self.device_path,
|
||||||
|
type_: self.device_type
|
||||||
|
}),
|
||||||
|
group: self.group,
|
||||||
|
ifdown: self.ifdown,
|
||||||
|
ifup: self.ifup,
|
||||||
|
ip: None,
|
||||||
|
keepalive: self.keepalive,
|
||||||
|
listen: self.listen.or(self.port.map(|p| format!("{}", p))),
|
||||||
|
mode: self.mode,
|
||||||
|
peer_timeout: self.peer_timeout,
|
||||||
|
peers: self.peers,
|
||||||
|
pid_file: self.pid_file,
|
||||||
|
port_forwarding: self.port_forwarding,
|
||||||
|
stats_file: self.stats_file,
|
||||||
|
statsd: Some(ConfigFileStatsd {
|
||||||
|
prefix: self.statsd_prefix,
|
||||||
|
server: self.statsd_server
|
||||||
|
}),
|
||||||
|
switch_timeout: self.dst_timeout,
|
||||||
|
user: self.user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue