소스 검색

WIP. moving to ssh tunnel-based connection to node

master
Jonathan Cobb 4 년 전
부모
커밋
24b8d42288
5개의 변경된 파일109개의 추가작업 그리고 40개의 파일을 삭제
  1. +49
    -10
      src/admin.rs
  2. +1
    -1
      src/lib.rs
  3. +27
    -24
      src/main.rs
  4. +2
    -2
      src/proxy.rs
  5. +30
    -3
      src/util.rs

+ 49
- 10
src/admin.rs 파일 보기

@@ -1,4 +1,4 @@
#![deny(warnings)]
//#![deny(warnings)]
/**
* Copyright (c) 2020 Bubble, Inc. All rights reserved.
* For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
@@ -28,16 +28,23 @@ struct AdminRegistration {

#[derive(Debug, Deserialize, Serialize, Clone)]
struct BubbleRegistration {
key: String,
ip: String,
proxy_port: u16,
auth_token: String
}

#[derive(Debug, Deserialize, Serialize, Clone)]
struct BubbleRegistrationResponse {
port: Option<u16>
}

pub async fn start_admin (admin_port : u16,
proxy_ip : String,
proxy_port : u16,
password_hash: String,
auth_token : Arc<String>) {
auth_token : Arc<String>,
ssh_priv_key : Arc<String>,
ssh_pub_key : Arc<String>) {
let admin_sock: SocketAddr = format!("127.0.0.1:{}", admin_port).parse().unwrap();

let register = warp::path!("register")
@@ -47,6 +54,8 @@ pub async fn start_admin (admin_port : u16,
.and(warp::any().map(move || proxy_port))
.and(warp::any().map(move || password_hash.clone()))
.and(warp::any().map(move || auth_token.clone()))
.and(warp::any().map(move || ssh_priv_key.clone()))
.and(warp::any().map(move || ssh_pub_key.clone()))
.and_then(handle_register);

let routes = warp::post().and(register);
@@ -62,7 +71,9 @@ async fn handle_register(registration : AdminRegistration,
proxy_ip: String,
proxy_port : u16,
hashed_password : String,
auth_token : Arc<String>) -> Result<impl warp::Reply, warp::Rejection> {
auth_token : Arc<String>,
ssh_priv_key : Arc<String>,
ssh_pub_key : Arc<String>) -> Result<impl warp::Reply, warp::Rejection> {
let pass_result = is_correct_password(registration.password, hashed_password);
if pass_result.is_err() {
error!("handle_register: error verifying password: {:?}", pass_result.err());
@@ -80,8 +91,8 @@ async fn handle_register(registration : AdminRegistration,

// create the registration object
let bubble_registration = BubbleRegistration {
key: ssh_pub_key.to_string(),
ip: proxy_ip,
proxy_port,
auth_token: auth_token.to_string()
};

@@ -97,13 +108,41 @@ async fn handle_register(registration : AdminRegistration,
match response.status() {
ReqwestStatusCode::OK => {
info!("handle_register: successfully registered with bubble");
Ok(warp::reply::with_status(
"successfully registered with bubble",
http::StatusCode::OK,
))
let body_bytes = &response.bytes().await.unwrap();
let body = String::from_utf8(body_bytes.to_vec()).unwrap();
let reg_opt = serde_json::from_str(body.as_str());
if reg_opt.is_err() {
error!("handle_register: error registering with bubble, error parsing response: {}", body);
Ok(warp::reply::with_status(
"error registering with bubble, error parsing response",
http::StatusCode::PRECONDITION_FAILED,
))
} else {
let reg_response: BubbleRegistrationResponse = reg_opt.unwrap();
info!("handle_register: parsed response object: {:?}", reg_response);
let port_opt = reg_response.port;
if port_opt.is_none() {
error!("handle_register: error registering with bubble, response did not include a port");
Ok(warp::reply::with_status(
"error registering with bubble, response did not include a port",
http::StatusCode::PRECONDITION_FAILED,
))
} else {
let port = port_opt.unwrap();
info!("handle_register: received port: {}", port);
// todo: start or restart ssh service
Ok(warp::reply::with_status(
"successfully registered with bubble",
http::StatusCode::OK,
))
}
}
},
_ => {
error!("handle_register: error registering with bubble: {:?}", response.status());
let status_code = &response.status();
let body_bytes = &response.bytes().await.unwrap();
let body = String::from_utf8(body_bytes.to_vec()).unwrap();
error!("handle_register: error registering with bubble: {:?}: {}", status_code, body);
Ok(warp::reply::with_status(
"error registering with bubble",
http::StatusCode::PRECONDITION_FAILED,


+ 1
- 1
src/lib.rs 파일 보기

@@ -1,4 +1,4 @@
#![deny(warnings)]
//#![deny(warnings)]
/**
* Copyright (c) 2020 Bubble, Inc. All rights reserved.
* For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/


+ 27
- 24
src/main.rs 파일 보기

@@ -1,4 +1,4 @@
#![deny(warnings)]
//#![deny(warnings)]
/**
* Copyright (c) 2020 Bubble, Inc. All rights reserved.
* For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
@@ -14,7 +14,6 @@ extern crate stderrlog;

extern crate rand;

use std::fs;
use std::path::Path;
use std::process::exit;
use std::sync::Arc;
@@ -34,6 +33,8 @@ use bubble_flexrouter::net::is_private_ip;
use bubble_flexrouter::pass::init_password;
use bubble_flexrouter::proxy::start_proxy;
use bubble_flexrouter::util::read_required_env_var_argument;
use bubble_flexrouter::util::read_required_env_var_argument_as_file;
use bubble_flexrouter::util::read_path_to_string;

const MIN_TOKEN_CHARS: usize = 50;
const MAX_TOKEN_CHARS: usize = 100;
@@ -98,6 +99,13 @@ async fn main() {
.help("environment variable naming the file that contains the bubble token")
.default_value("BUBBLE_FR_TOKEN")
.takes_value(true))
.arg(Arg::with_name("ssh_key_file")
.short("s")
.long("ssh-key-file")
.value_name("ENV_VAR_NAME")
.help("environment variable naming the file that contains the SSH key")
.default_value("BUBBLE_FR_SSH_KEY")
.takes_value(true))
.arg(Arg::with_name("log_level")
.short("v")
.long("log-level")
@@ -163,35 +171,29 @@ async fn main() {
let dns1_ip = args.value_of("dns1").unwrap();
let dns2_ip = args.value_of("dns2").unwrap();
let proxy_port = args.value_of("proxy_port").unwrap().parse::<u16>().unwrap();
let proxy_ip = proxy_bind_addr.unwrap().ip();

let token_file_env_var_opt = args.value_of("token_file");
let token_path_string = read_required_env_var_argument("token-file", token_file_env_var_opt);
let token_path = token_path_string.as_str();
let token_file_path = Path::new(token_path);
if !token_file_path.exists() {
error!("main: token file does not exist: {}", token_path);
let ssh_key_file_env_var_opt = args.value_of("ssh_key_file");
let ssh_key_path_path_string = read_required_env_var_argument("ssh-key-file", ssh_key_file_env_var_opt);
let ssh_key_path = Path::new(ssh_key_path_path_string.as_str());
if !ssh_key_path.exists() {
error!("read_required_env_var_argument_as_path: file does not exist: {}", ssh_key_path.to_str().unwrap());
exit(2);
}

let auth_token_result = fs::read_to_string(&token_file_path);
if auth_token_result.is_err() {
let err = auth_token_result.err();
if err.is_none() {
error!("main: error reading token file {}", token_path);
} else {
error!("main: error reading token file {}: {:?}", token_path, err.unwrap());
}
exit(2);
}
let auth_token_string = auth_token_result.unwrap();
let ssh_priv_key = Arc::new(read_path_to_string(ssh_key_path));
let ssh_pub_key_path_name = format!("{}.pub", ssh_key_path.to_str().unwrap());
let ssh_pub_key_path = Path::new(ssh_pub_key_path_name.as_str());
let ssh_pub_key = Arc::new(read_path_to_string(ssh_pub_key_path));

let token_file_env_var_opt = args.value_of("token_file");
let auth_token_string = read_required_env_var_argument_as_file("token-file", token_file_env_var_opt);
let auth_token_val = auth_token_string.trim();
if auth_token_val.len() < MIN_TOKEN_CHARS {
error!("main: auth token in token file {} is too short, must be at least {} chars", token_path, MIN_TOKEN_CHARS);
error!("main: auth token in token file is too short, must be at least {} chars", MIN_TOKEN_CHARS);
exit(2);
}
if auth_token_val.len() > MAX_TOKEN_CHARS {
error!("main: auth token in token file {} is too long, must be at most {} chars", token_path, MAX_TOKEN_CHARS);
error!("main: auth token in token file is too long, must be at most {} chars", MAX_TOKEN_CHARS);
exit(2);
}
let auth_token = Arc::new(String::from(auth_token_val));
@@ -201,12 +203,13 @@ async fn main() {
proxy_ip.to_string(),
proxy_port,
password_hash,
auth_token.clone()
auth_token.clone(),
ssh_priv_key.clone(),
ssh_pub_key.clone()
);
let proxy = start_proxy(
dns1_ip,
dns2_ip,
proxy_ip,
proxy_port,
auth_token.clone()
);


+ 2
- 2
src/proxy.rs 파일 보기

@@ -42,7 +42,6 @@ type HttpClient = Client<hyper_tls::HttpsConnector<HttpConnector<CacheResolver>>

pub async fn start_proxy (dns1_ip : &str,
dns2_ip: &str,
proxy_ip: IpAddr,
proxy_port: u16,
auth_token : Arc<String>) {
let dns1_sock : SocketAddr = format!("{}:53", dns1_ip).parse().unwrap();
@@ -57,7 +56,8 @@ pub async fn start_proxy (dns1_ip : &str,
let client: HttpClient = Client::builder().build(https);
let gateway = Arc::new(ip_gateway());

let addr = SocketAddr::from((proxy_ip, proxy_port));
let proxy_local_ip : IpAddr = "127.0.0.1".parse().unwrap();
let addr = SocketAddr::from((proxy_local_ip, proxy_port));

let make_service = make_service_fn(move |_| {
let client = client.clone();


+ 30
- 3
src/util.rs 파일 보기

@@ -5,13 +5,15 @@
*/

use std::env;
use std::fs;
use std::path::Path;
use std::process::exit;

use log::error;

pub fn read_required_env_var_argument(arg_name : &str, opt : Option<&str>) -> String {
if opt.is_none() {
error!("main: {} argument is required", arg_name);
error!("read_required_env_var_argument: {} argument is required", arg_name);
exit(2);
}
let opt_value = opt.unwrap();
@@ -19,11 +21,36 @@ pub fn read_required_env_var_argument(arg_name : &str, opt : Option<&str>) -> St
if opt_opt.is_err() {
let err = opt_opt.err();
if err.is_none() {
error!("main: {} argument was invalid: {}", arg_name, opt_value);
error!("read_required_env_var_argument: {} argument was invalid: {}", arg_name, opt_value);
} else {
error!("main: {} argument was invalid: {}: {:?}", arg_name, opt_value, err);
error!("read_required_env_var_argument: {} argument was invalid: {}: {:?}", arg_name, opt_value, err);
}
exit(2);
}
opt_opt.unwrap()
}

pub fn read_required_env_var_argument_as_file(arg_name : &str, opt : Option<&str>) -> String {
let path_string = read_required_env_var_argument(arg_name, opt);
let file_path = Path::new(path_string.as_str());
if !file_path.exists() {
error!("read_required_env_var_argument_as_path: file does not exist: {}", file_path.to_str().unwrap());
exit(2);
}
read_path_to_string(file_path)
}

pub fn read_path_to_string(path: &Path) -> String {
let read_result = fs::read_to_string(path);
if read_result.is_err() {
let err = read_result.err();
let path_string = path.to_str().unwrap();
if err.is_none() {
error!("read_required_env_var_argument_as_file: error reading file {}", path_string);
} else {
error!("read_required_env_var_argument_as_file: error reading file {}: {:?}", path_string, err.unwrap());
}
exit(2);
}
read_result.unwrap()
}

불러오는 중...
취소
저장