server: non-interactive network creation
parent
b92ad65b17
commit
c4e369ee54
|
@ -89,6 +89,12 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
|
@ -666,6 +672,15 @@ version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -686,9 +701,9 @@ checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.20.1"
|
version = "0.22.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd"
|
checksum = "2f6332d94daa84478d55a6aa9dbb3b305ed6500fb0cb9400cb9e1525d0e0e188"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
|
@ -1027,10 +1042,25 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "ring"
|
||||||
version = "0.24.2"
|
version = "0.16.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d5f38ee71cbab2c827ec0ac24e76f82eca723cee92c509a65f67dee393c25112"
|
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"spin",
|
||||||
|
"untrusted",
|
||||||
|
"web-sys",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusqlite"
|
||||||
|
version = "0.25.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48381bf52627e7b0e02c4c0e4c0c88fc1cf2228a2eb7461d9499b1372399f1da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"fallible-iterator",
|
"fallible-iterator",
|
||||||
|
@ -1047,6 +1077,19 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.19.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"log",
|
||||||
|
"ring",
|
||||||
|
"sct",
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
@ -1065,6 +1108,16 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sct"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.125"
|
version = "1.0.125"
|
||||||
|
@ -1137,6 +1190,7 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
"ureq",
|
||||||
"warp",
|
"warp",
|
||||||
"wgctrl",
|
"wgctrl",
|
||||||
]
|
]
|
||||||
|
@ -1199,6 +1253,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -1496,6 +1556,12 @@ version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
|
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ureq"
|
name = "ureq"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
@ -1506,9 +1572,12 @@ dependencies = [
|
||||||
"chunked_transfer",
|
"chunked_transfer",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"rustls",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"url",
|
"url",
|
||||||
|
"webpki",
|
||||||
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1583,6 +1652,89 @@ version = "0.10.2+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki"
|
||||||
|
version = "0.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940"
|
||||||
|
dependencies = [
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wgctrl"
|
name = "wgctrl"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
|
@ -52,7 +52,8 @@ enum Command {
|
||||||
/// Install a new innernet config.
|
/// Install a new innernet config.
|
||||||
#[structopt(alias = "redeem")]
|
#[structopt(alias = "redeem")]
|
||||||
Install {
|
Install {
|
||||||
config: PathBuf,
|
/// Path to the invitation file
|
||||||
|
invite: PathBuf,
|
||||||
|
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
hosts: HostsOpt,
|
hosts: HostsOpt,
|
||||||
|
@ -64,9 +65,11 @@ enum Command {
|
||||||
/// Enumerate all innernet connections.
|
/// Enumerate all innernet connections.
|
||||||
#[structopt(alias = "list")]
|
#[structopt(alias = "list")]
|
||||||
Show {
|
Show {
|
||||||
|
/// One-line peer list
|
||||||
#[structopt(short, long)]
|
#[structopt(short, long)]
|
||||||
short: bool,
|
short: bool,
|
||||||
|
|
||||||
|
/// Display peers in a tree based on the CIDRs
|
||||||
#[structopt(short, long)]
|
#[structopt(short, long)]
|
||||||
tree: bool,
|
tree: bool,
|
||||||
|
|
||||||
|
@ -841,10 +844,10 @@ fn run(opt: Opt) -> Result<(), Error> {
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
Command::Install {
|
Command::Install {
|
||||||
config,
|
invite,
|
||||||
hosts,
|
hosts,
|
||||||
opts,
|
opts,
|
||||||
} => install(&config, hosts.into(), opts)?,
|
} => install(&invite, hosts.into(), opts)?,
|
||||||
Command::Show {
|
Command::Show {
|
||||||
short,
|
short,
|
||||||
tree,
|
tree,
|
||||||
|
|
|
@ -21,18 +21,19 @@ hyper = "0.14"
|
||||||
indoc = "1"
|
indoc = "1"
|
||||||
ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129
|
ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libsqlite3-sys = "0.20"
|
libsqlite3-sys = "0.22"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
parking_lot = "0.11"
|
parking_lot = "0.11"
|
||||||
pretty_env_logger = "0.4"
|
pretty_env_logger = "0.4"
|
||||||
regex = { version = "1", default-features = false, features = ["std"] }
|
regex = { version = "1", default-features = false, features = ["std"] }
|
||||||
rusqlite = "0.24"
|
rusqlite = "0.25"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
shared = { path = "../shared" }
|
shared = { path = "../shared" }
|
||||||
subtle = "2"
|
subtle = "2"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
|
ureq = "2"
|
||||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
warp = { git = "https://github.com/tonarino/warp", default-features = false } # pending https://github.com/seanmonstar/warp/issues/830
|
warp = { git = "https://github.com/tonarino/warp", default-features = false } # pending https://github.com/seanmonstar/warp/issues/830
|
||||||
|
|
|
@ -20,9 +20,32 @@ fn create_database<P: AsRef<Path>>(
|
||||||
Ok(conn)
|
Ok(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq, StructOpt)]
|
||||||
|
pub struct InitializeOpts {
|
||||||
|
/// The network name (ex: evilcorp)
|
||||||
|
#[structopt(long)]
|
||||||
|
pub network_name: Option<String>,
|
||||||
|
|
||||||
|
/// The network CIDR (ex: 10.42.0.0/16)
|
||||||
|
#[structopt(long)]
|
||||||
|
pub network_cidr: Option<IpNetwork>,
|
||||||
|
|
||||||
|
/// This server's external endpoint (ex: 100.100.100.100:51820)
|
||||||
|
#[structopt(long, conflicts_with = "auto-external-endpoint")]
|
||||||
|
pub external_endpoint: Option<SocketAddr>,
|
||||||
|
|
||||||
|
/// Auto-resolve external endpoint
|
||||||
|
#[structopt(long = "auto-external-endpoint")]
|
||||||
|
pub auto_external_endpoint: bool,
|
||||||
|
|
||||||
|
/// Port to listen on (for the WireGuard interface)
|
||||||
|
#[structopt(long)]
|
||||||
|
pub listen_port: Option<u16>,
|
||||||
|
}
|
||||||
|
|
||||||
struct DbInitData {
|
struct DbInitData {
|
||||||
root_cidr_name: String,
|
network_name: String,
|
||||||
root_cidr: IpNetwork,
|
network_cidr: IpNetwork,
|
||||||
server_cidr: IpNetwork,
|
server_cidr: IpNetwork,
|
||||||
our_ip: IpAddr,
|
our_ip: IpAddr,
|
||||||
public_key_base64: String,
|
public_key_base64: String,
|
||||||
|
@ -35,8 +58,8 @@ fn populate_database(conn: &Connection, db_init_data: DbInitData) -> Result<(),
|
||||||
let root_cidr = DatabaseCidr::create(
|
let root_cidr = DatabaseCidr::create(
|
||||||
&conn,
|
&conn,
|
||||||
CidrContents {
|
CidrContents {
|
||||||
name: db_init_data.root_cidr_name.clone(),
|
name: db_init_data.network_name.clone(),
|
||||||
cidr: db_init_data.root_cidr,
|
cidr: db_init_data.network_cidr,
|
||||||
parent: None,
|
parent: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -71,7 +94,7 @@ fn populate_database(conn: &Connection, db_init_data: DbInitData) -> Result<(),
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_wizard(conf: &ServerConfig) -> Result<(), Error> {
|
pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Error> {
|
||||||
let theme = ColorfulTheme::default();
|
let theme = ColorfulTheme::default();
|
||||||
|
|
||||||
shared::ensure_dirs_exist(&[conf.config_dir(), conf.database_dir()]).map_err(|_| {
|
shared::ensure_dirs_exist(&[conf.config_dir(), conf.database_dir()]).map_err(|_| {
|
||||||
|
@ -81,42 +104,57 @@ pub fn init_wizard(conf: &ServerConfig) -> Result<(), Error> {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let (name, root_cidr) = conf.root_cidr.clone().unwrap_or_else(|| {
|
let name: String = if let Some(name) = opts.network_name {
|
||||||
println!("Please specify a root CIDR, which will define the entire network.");
|
name.clone()
|
||||||
let name: String = Input::with_theme(&theme)
|
} else {
|
||||||
|
println!("Here you'll specify the network CIDR, which will encompass the entire network.");
|
||||||
|
Input::with_theme(&theme)
|
||||||
.with_prompt("Network name")
|
.with_prompt("Network name")
|
||||||
.validate_with(hostname_validator)
|
.validate_with(hostname_validator)
|
||||||
.interact()
|
.interact()?
|
||||||
.map_err(|_| println!("failed to get name."))
|
};
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let root_cidr: IpNetwork = Input::with_theme(&theme)
|
let root_cidr: IpNetwork = if let Some(cidr) = opts.network_cidr {
|
||||||
|
cidr.clone()
|
||||||
|
} else {
|
||||||
|
Input::with_theme(&theme)
|
||||||
.with_prompt("Network CIDR")
|
.with_prompt("Network CIDR")
|
||||||
.with_initial_text("10.42.0.0/16")
|
.with_initial_text("10.42.0.0/16")
|
||||||
.interact()
|
.interact()?
|
||||||
.map_err(|_| println!("failed to get cidr."))
|
};
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
(name, root_cidr)
|
|
||||||
});
|
|
||||||
|
|
||||||
// This probably won't error because of the `hostname_validator` regex.
|
// This probably won't error because of the `hostname_validator` regex.
|
||||||
let name = name.parse()?;
|
let name = name.parse()?;
|
||||||
|
|
||||||
let endpoint: SocketAddr = conf.endpoint.unwrap_or_else(|| {
|
let endpoint: SocketAddr = if let Some(endpoint) = opts.external_endpoint {
|
||||||
prompts::ask_endpoint()
|
endpoint.clone()
|
||||||
.map_err(|_| println!("failed to get endpoint."))
|
} else {
|
||||||
.unwrap()
|
let external_ip: Option<IpAddr> = ureq::get("http://4.icanhazip.com")
|
||||||
});
|
.call()
|
||||||
|
.ok()
|
||||||
|
.map(|res| res.into_string().ok())
|
||||||
|
.flatten()
|
||||||
|
.map(|body| body.trim().to_string())
|
||||||
|
.and_then(|body| body.parse().ok());
|
||||||
|
|
||||||
let listen_port: u16 = conf.listen_port.unwrap_or_else(|| {
|
if opts.auto_external_endpoint {
|
||||||
|
let ip = external_ip.ok_or("couldn't get external IP")?;
|
||||||
|
(ip, 51820).into()
|
||||||
|
} else {
|
||||||
|
prompts::ask_endpoint(external_ip)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let listen_port: u16 = if let Some(listen_port) = opts.listen_port {
|
||||||
|
listen_port
|
||||||
|
} else {
|
||||||
Input::with_theme(&theme)
|
Input::with_theme(&theme)
|
||||||
.with_prompt("Listen port")
|
.with_prompt("Listen port")
|
||||||
.default(51820)
|
.default(51820)
|
||||||
.interact()
|
.interact()
|
||||||
.map_err(|_| println!("failed to get listen port."))
|
.map_err(|_| "failed to get listen port.")?
|
||||||
.unwrap()
|
};
|
||||||
});
|
|
||||||
let our_ip = root_cidr
|
let our_ip = root_cidr
|
||||||
.iter()
|
.iter()
|
||||||
.find(|ip| root_cidr.is_assignable(*ip))
|
.find(|ip| root_cidr.is_assignable(*ip))
|
||||||
|
@ -134,8 +172,8 @@ pub fn init_wizard(conf: &ServerConfig) -> Result<(), Error> {
|
||||||
config.write_to_path(&config_path)?;
|
config.write_to_path(&config_path)?;
|
||||||
|
|
||||||
let db_init_data = DbInitData {
|
let db_init_data = DbInitData {
|
||||||
root_cidr_name: name.to_string(),
|
network_name: name.to_string(),
|
||||||
root_cidr,
|
network_cidr: root_cidr,
|
||||||
server_cidr,
|
server_cidr,
|
||||||
our_ip,
|
our_ip,
|
||||||
public_key_base64: our_keypair.public.to_base64(),
|
public_key_base64: our_keypair.public.to_base64(),
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub use endpoints::Endpoints;
|
||||||
pub use error::ServerError;
|
pub use error::ServerError;
|
||||||
use shared::{prompts, wg, CidrTree, Error, Interface, SERVER_CONFIG_DIR, SERVER_DATABASE_DIR};
|
use shared::{prompts, wg, CidrTree, Error, Interface, SERVER_CONFIG_DIR, SERVER_DATABASE_DIR};
|
||||||
pub use shared::{Association, AssociationContents};
|
pub use shared::{Association, AssociationContents};
|
||||||
|
use initialize::InitializeOpts;
|
||||||
|
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
@ -51,7 +52,10 @@ struct Opt {
|
||||||
enum Command {
|
enum Command {
|
||||||
/// Create a new network.
|
/// Create a new network.
|
||||||
#[structopt(alias = "init")]
|
#[structopt(alias = "init")]
|
||||||
New,
|
New {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
opts: InitializeOpts
|
||||||
|
},
|
||||||
|
|
||||||
/// Permanently uninstall a created network, rendering it unusable. Use with care.
|
/// Permanently uninstall a created network, rendering it unusable. Use with care.
|
||||||
Uninstall { interface: Interface },
|
Uninstall { interface: Interface },
|
||||||
|
@ -153,10 +157,6 @@ impl ConfigFile {
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
wg_manage_dir_override: Option<PathBuf>,
|
wg_manage_dir_override: Option<PathBuf>,
|
||||||
wg_dir_override: Option<PathBuf>,
|
wg_dir_override: Option<PathBuf>,
|
||||||
root_cidr: Option<(String, IpNetwork)>,
|
|
||||||
endpoint: Option<SocketAddr>,
|
|
||||||
listen_port: Option<u16>,
|
|
||||||
noninteractive: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerConfig {
|
impl ServerConfig {
|
||||||
|
@ -204,8 +204,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let conf = ServerConfig::default();
|
let conf = ServerConfig::default();
|
||||||
|
|
||||||
match opt.command {
|
match opt.command {
|
||||||
Command::New => {
|
Command::New { opts } => {
|
||||||
if let Err(e) = initialize::init_wizard(&conf) {
|
if let Err(e) = initialize::init_wizard(&conf, opts) {
|
||||||
println!("{}: {}.", "creation failed".red(), e);
|
println!("{}: {}.", "creation failed".red(), e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -237,7 +237,7 @@ fn open_database_connection(
|
||||||
fn add_peer(
|
fn add_peer(
|
||||||
interface: &InterfaceName,
|
interface: &InterfaceName,
|
||||||
conf: &ServerConfig,
|
conf: &ServerConfig,
|
||||||
args: AddPeerOpts,
|
opts: AddPeerOpts,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let config = ConfigFile::from_file(conf.config_path(interface))?;
|
let config = ConfigFile::from_file(conf.config_path(interface))?;
|
||||||
let conn = open_database_connection(interface, conf)?;
|
let conn = open_database_connection(interface, conf)?;
|
||||||
|
@ -248,7 +248,7 @@ fn add_peer(
|
||||||
let cidrs = DatabaseCidr::list(&conn)?;
|
let cidrs = DatabaseCidr::list(&conn)?;
|
||||||
let cidr_tree = CidrTree::new(&cidrs[..]);
|
let cidr_tree = CidrTree::new(&cidrs[..]);
|
||||||
|
|
||||||
if let Some((peer_request, keypair)) = shared::prompts::add_peer(&peers, &cidr_tree, &args)? {
|
if let Some((peer_request, keypair)) = shared::prompts::add_peer(&peers, &cidr_tree, &opts)? {
|
||||||
let peer = DatabasePeer::create(&conn, peer_request)?;
|
let peer = DatabasePeer::create(&conn, peer_request)?;
|
||||||
if cfg!(not(test)) && DeviceInfo::get_by_name(interface).is_ok() {
|
if cfg!(not(test)) && DeviceInfo::get_by_name(interface).is_ok() {
|
||||||
// Update the current WireGuard interface with the new peers.
|
// Update the current WireGuard interface with the new peers.
|
||||||
|
@ -268,7 +268,7 @@ fn add_peer(
|
||||||
&cidr_tree,
|
&cidr_tree,
|
||||||
keypair,
|
keypair,
|
||||||
&SocketAddr::new(config.address, config.listen_port),
|
&SocketAddr::new(config.address, config.listen_port),
|
||||||
&args.save_config,
|
&opts.save_config,
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
println!("exited without creating peer.");
|
println!("exited without creating peer.");
|
||||||
|
@ -280,11 +280,11 @@ fn add_peer(
|
||||||
fn add_cidr(
|
fn add_cidr(
|
||||||
interface: &InterfaceName,
|
interface: &InterfaceName,
|
||||||
conf: &ServerConfig,
|
conf: &ServerConfig,
|
||||||
args: AddCidrOpts,
|
opts: AddCidrOpts,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let conn = open_database_connection(interface, conf)?;
|
let conn = open_database_connection(interface, conf)?;
|
||||||
let cidrs = DatabaseCidr::list(&conn)?;
|
let cidrs = DatabaseCidr::list(&conn)?;
|
||||||
if let Some(cidr_request) = shared::prompts::add_cidr(&cidrs, &args)? {
|
if let Some(cidr_request) = shared::prompts::add_cidr(&cidrs, &opts)? {
|
||||||
let cidr = DatabaseCidr::create(&conn, cidr_request)?;
|
let cidr = DatabaseCidr::create(&conn, cidr_request)?;
|
||||||
printdoc!(
|
printdoc!(
|
||||||
"
|
"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{DatabaseCidr, DatabasePeer},
|
db::{DatabaseCidr, DatabasePeer},
|
||||||
endpoints::Endpoints,
|
endpoints::Endpoints,
|
||||||
initialize::init_wizard,
|
initialize::{init_wizard, InitializeOpts},
|
||||||
Context, ServerConfig,
|
Context, ServerConfig,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
@ -64,12 +64,16 @@ impl Server {
|
||||||
let conf = ServerConfig {
|
let conf = ServerConfig {
|
||||||
wg_manage_dir_override: Some(test_dir_path.to_path_buf()),
|
wg_manage_dir_override: Some(test_dir_path.to_path_buf()),
|
||||||
wg_dir_override: Some(test_dir_path.to_path_buf()),
|
wg_dir_override: Some(test_dir_path.to_path_buf()),
|
||||||
root_cidr: Some((interface.clone(), ROOT_CIDR.parse()?)),
|
|
||||||
endpoint: Some("155.155.155.155:54321".parse()?),
|
|
||||||
listen_port: Some(54321),
|
|
||||||
noninteractive: true,
|
|
||||||
};
|
};
|
||||||
init_wizard(&conf).map_err(|_| anyhow!("init_wizard failed"))?;
|
|
||||||
|
let opts = InitializeOpts {
|
||||||
|
network_name: Some(interface.clone()),
|
||||||
|
network_cidr: Some(ROOT_CIDR.parse()?),
|
||||||
|
external_endpoint: Some("155.155.155.155:54321".parse()?),
|
||||||
|
listen_port: Some(54321),
|
||||||
|
auto_external_endpoint: false,
|
||||||
|
};
|
||||||
|
init_wizard(&conf, opts).map_err(|_| anyhow!("init_wizard failed"))?;
|
||||||
|
|
||||||
let interface = interface.parse().unwrap();
|
let interface = interface.parse().unwrap();
|
||||||
// Add developer CIDR and user CIDR and some peers for testing.
|
// Add developer CIDR and user CIDR and some peers for testing.
|
||||||
|
|
|
@ -362,16 +362,20 @@ pub fn set_listen_port(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ask_endpoint() -> Result<SocketAddr, Error> {
|
pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<SocketAddr, Error> {
|
||||||
println!("getting external IP address.");
|
println!("getting external IP address.");
|
||||||
|
|
||||||
let external_ip: Option<IpAddr> = ureq::get("http://4.icanhazip.com")
|
let external_ip = if external_ip.is_some() {
|
||||||
|
external_ip
|
||||||
|
} else {
|
||||||
|
ureq::get("http://4.icanhazip.com")
|
||||||
.call()
|
.call()
|
||||||
.ok()
|
.ok()
|
||||||
.map(|res| res.into_string().ok())
|
.map(|res| res.into_string().ok())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|body| body.trim().to_string())
|
.map(|body| body.trim().to_string())
|
||||||
.and_then(|body| body.parse().ok());
|
.and_then(|body| body.parse().ok())
|
||||||
|
};
|
||||||
|
|
||||||
let mut endpoint_builder = Input::with_theme(&*THEME);
|
let mut endpoint_builder = Input::with_theme(&*THEME);
|
||||||
if let Some(ip) = external_ip {
|
if let Some(ip) = external_ip {
|
||||||
|
@ -386,7 +390,11 @@ pub fn ask_endpoint() -> Result<SocketAddr, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn override_endpoint(unset: bool) -> Result<Option<Option<SocketAddr>>, Error> {
|
pub fn override_endpoint(unset: bool) -> Result<Option<Option<SocketAddr>>, Error> {
|
||||||
let endpoint = if !unset { Some(ask_endpoint()?) } else { None };
|
let endpoint = if !unset {
|
||||||
|
Some(ask_endpoint(None)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
if Confirm::with_theme(&*THEME)
|
if Confirm::with_theme(&*THEME)
|
||||||
|
|
Loading…
Reference in New Issue