server(new): add more explanation text at beginning

pull/71/head^2
Jake McGinty 2021-05-09 21:04:49 +09:00
parent d4d0d7301a
commit 54e7c1b183
3 changed files with 41 additions and 26 deletions

View File

@ -27,12 +27,26 @@ static CLOUDFLARE_QNAME: &[&str] = &["whoami", "cloudflare"];
const CLOUDFLARE_IPV4: Ipv4Addr = Ipv4Addr::new(1, 1, 1, 1); const CLOUDFLARE_IPV4: Ipv4Addr = Ipv4Addr::new(1, 1, 1, 1);
const CLOUDFLARE_IPV6: Ipv6Addr = Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111); const CLOUDFLARE_IPV6: Ipv6Addr = Ipv6Addr::new(0x2606, 0x4700, 0x4700, 0, 0, 0, 0, 0x1111);
pub fn public_ip() -> Result<(Option<Ipv4Addr>, Option<Ipv6Addr>), Error> { pub enum Preference {
Ipv4,
Ipv6,
}
pub fn get_both() -> Result<(Option<Ipv4Addr>, Option<Ipv6Addr>), Error> {
let ipv4 = Request::start(CLOUDFLARE_IPV4)?; let ipv4 = Request::start(CLOUDFLARE_IPV4)?;
let ipv6 = Request::start(CLOUDFLARE_IPV6)?; let ipv6 = Request::start(CLOUDFLARE_IPV6)?;
Ok((ipv4.read_response().ok(), ipv6.read_response().ok())) Ok((ipv4.read_response().ok(), ipv6.read_response().ok()))
} }
pub fn get_any(preference: Preference) -> Result<Option<IpAddr>, Error> {
let (v4, v6) = get_both()?;
let (v4, v6) = (v4.map(IpAddr::from), v6.map(IpAddr::from));
Ok(match preference {
Preference::Ipv4 => v4.or(v6),
Preference::Ipv6 => v6.or(v4),
})
}
struct Request<T> { struct Request<T> {
socket: UdpSocket, socket: UdpSocket,
id: [u8; 2], id: [u8; 2],
@ -169,7 +183,7 @@ mod tests {
#[ignore] #[ignore]
fn it_works() -> Result<(), Error> { fn it_works() -> Result<(), Error> {
let now = Instant::now(); let now = Instant::now();
let (v4, v6) = public_ip()?; let (v4, v6) = get_both()?;
println!("Done in {}ms", now.elapsed().as_millis()); println!("Done in {}ms", now.elapsed().as_millis());
println!("v4: {:?}, v6: {:?}", v4, v6); println!("v4: {:?}, v6: {:?}", v4, v6);
assert!(v4.is_some()); assert!(v4.is_some());

View File

@ -2,6 +2,7 @@ use crate::*;
use db::DatabaseCidr; use db::DatabaseCidr;
use dialoguer::{theme::ColorfulTheme, Input}; use dialoguer::{theme::ColorfulTheme, Input};
use indoc::printdoc; use indoc::printdoc;
use publicip::Preference;
use rusqlite::{params, Connection}; use rusqlite::{params, Connection};
use shared::{ use shared::{
prompts, CidrContents, Endpoint, Hostname, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS, prompts, CidrContents, Endpoint, Hostname, PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
@ -105,11 +106,24 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
"(are you not running as root?)".bold() "(are you not running as root?)".bold()
) )
})?; })?;
printdoc!(
"\nTime to setup your innernet network.
Your network name can be any hostname-valid string, i.e. \"evilcorp\", and
your network CIDR should be in the RFC1918 IPv4 (10/8, 172.16/12, or 192.168/16),
or RFC4193 IPv6 (fd00::/8) ranges.
The external endpoint specified is a <host>:<port> string that is the address clients
will connect to. It's up to you to forward/open ports in your routers/firewalls
as needed.
For more usage instructions, see https://github.com/tonarino/innernet#usage
\n"
);
let name: Hostname = if let Some(name) = opts.network_name { let name: Hostname = if let Some(name) = opts.network_name {
name name
} else { } else {
println!("Here you'll specify the network CIDR, which will encompass the entire network.");
Input::with_theme(&theme) Input::with_theme(&theme)
.with_prompt("Network name") .with_prompt("Network name")
.interact()? .interact()?
@ -130,14 +144,11 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
let endpoint: Endpoint = if let Some(endpoint) = opts.external_endpoint { let endpoint: Endpoint = if let Some(endpoint) = opts.external_endpoint {
endpoint endpoint
} else { } else {
let (v4, v6) = publicip::public_ip()?;
let external_ip = v4.map(IpAddr::from).or(v6.map(IpAddr::from));
if opts.auto_external_endpoint { if opts.auto_external_endpoint {
let ip = external_ip.ok_or("couldn't get external IP")?; let ip = publicip::get_any(Preference::Ipv4)?.ok_or("couldn't get external IP")?;
SocketAddr::new(ip, 51820).into() SocketAddr::new(ip, 51820).into()
} else { } else {
prompts::ask_endpoint(external_ip)? prompts::ask_endpoint()?
} }
}; };
@ -197,7 +208,7 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
" "
{star} Setup finished. {star} Setup finished.
Network {interface} has been {created}! Network {interface} has been {created}, but it's not started yet!
Your new network starts with only one peer: this innernet server. Next, Your new network starts with only one peer: this innernet server. Next,
you'll want to create additional CIDRs and peers using the commands: you'll want to create additional CIDRs and peers using the commands:
@ -205,7 +216,8 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
{wg_manage_server} {add_cidr} {interface}, and {wg_manage_server} {add_cidr} {interface}, and
{wg_manage_server} {add_peer} {interface} {wg_manage_server} {add_peer} {interface}
See the documentation for more detailed instruction on designing your network. See https://github.com/tonarino/innernet for more detailed instruction
on designing your network.
When you're ready to start the network, you can auto-start the server: When you're ready to start the network, you can auto-start the server:

View File

@ -7,10 +7,8 @@ use colored::*;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select}; use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
use ipnetwork::IpNetwork; use ipnetwork::IpNetwork;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::{ use publicip::Preference;
net::{IpAddr, SocketAddr}, use std::{net::SocketAddr, time::SystemTime};
time::SystemTime,
};
use wgctrl::{InterfaceName, KeyPair}; use wgctrl::{InterfaceName, KeyPair};
lazy_static! { lazy_static! {
@ -356,15 +354,10 @@ pub fn set_listen_port(
} }
} }
pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<Endpoint, Error> { pub fn ask_endpoint() -> Result<Endpoint, Error> {
println!("getting external IP address."); println!("getting external IP address.");
let external_ip = if external_ip.is_some() { let external_ip = publicip::get_any(Preference::Ipv4)?;
external_ip
} else {
let (v4, v6) = publicip::public_ip()?;
v4.map(IpAddr::from).or(v6.map(IpAddr::from))
};
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 {
@ -379,11 +372,7 @@ pub fn ask_endpoint(external_ip: Option<IpAddr>) -> Result<Endpoint, Error> {
} }
pub fn override_endpoint(unset: bool) -> Result<Option<Option<Endpoint>>, Error> { pub fn override_endpoint(unset: bool) -> Result<Option<Option<Endpoint>>, Error> {
let endpoint = if !unset { let endpoint = if !unset { Some(ask_endpoint()?) } else { None };
Some(ask_endpoint(None)?)
} else {
None
};
Ok( Ok(
if Confirm::with_theme(&*THEME) if Confirm::with_theme(&*THEME)