Bubble proxy service
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
пре 4 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #![deny(warnings)]
  2. /**
  3. * Copyright (c) 2020 Bubble, Inc. All rights reserved.
  4. * For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
  5. */
  6. /**
  7. * This code was adapted from https://github.com/hyperium/hyper/blob/master/examples/http_proxy.rs
  8. * Copyright (c) 2014-2018 Sean McArthur
  9. * License: https://raw.githubusercontent.com/hyperium/hyper/master/LICENSE
  10. */
  11. extern crate log;
  12. extern crate stderrlog;
  13. extern crate rand;
  14. use std::process::exit;
  15. use std::sync::Arc;
  16. use clap::{Arg, ArgMatches, App};
  17. use futures_util::future::join;
  18. use log::{info, error};
  19. use pnet::datalink;
  20. use rand::Rng;
  21. use rand::distributions::Alphanumeric;
  22. use whoami;
  23. use bubble_flexrouter::admin::start_admin;
  24. use bubble_flexrouter::net::is_private_ip;
  25. use bubble_flexrouter::pass::init_password;
  26. use bubble_flexrouter::proxy::start_proxy;
  27. #[tokio::main]
  28. async fn main() {
  29. let args : ArgMatches = App::new("bubble-flexrouter")
  30. .version("0.1.0")
  31. .author("Jonathan Cobb <jonathan@getbubblenow.com>")
  32. .about("Proxy services for Bubble nodes")
  33. .arg(Arg::with_name("dns1")
  34. .short("d")
  35. .long("dns1")
  36. .value_name("IP_ADDRESS")
  37. .help("Primary DNS server")
  38. .default_value("1.1.1.1")
  39. .takes_value(true))
  40. .arg(Arg::with_name("dns2")
  41. .short("e")
  42. .long("dns2")
  43. .value_name("IP_ADDRESS")
  44. .help("Secondary DNS server")
  45. .default_value("1.0.0.1")
  46. .takes_value(true))
  47. .arg(Arg::with_name("proxy_ip")
  48. .short("i")
  49. .long("proxy-ip")
  50. .value_name("IP_ADDRESS")
  51. .help("IP address to listen for proxy connections, must be a private IP")
  52. .takes_value(true))
  53. .arg(Arg::with_name("proxy_port")
  54. .short("p")
  55. .long("proxy-port")
  56. .value_name("PORT")
  57. .help("port to listen for proxy connections")
  58. .default_value("9823")
  59. .takes_value(true))
  60. .arg(Arg::with_name("admin_port")
  61. .short("a")
  62. .long("admin-port")
  63. .value_name("PORT")
  64. .help("port to listen for admin connections")
  65. .default_value("9833")
  66. .takes_value(true))
  67. .arg(Arg::with_name("password_file")
  68. .short("w")
  69. .long("password-file")
  70. .value_name("FILE")
  71. .help("file containing bcrypt-hashed password required for admin commands")
  72. .takes_value(true))
  73. .arg(Arg::with_name("password_env_var")
  74. .short("W")
  75. .long("password-env-var")
  76. .value_name("ENV_VAR_NAME")
  77. .help("environment variable containing the admin password. overwrites previous value")
  78. .takes_value(true))
  79. .arg(Arg::with_name("log_level")
  80. .short("v")
  81. .long("log-level")
  82. .value_name("LOG_LEVEL")
  83. .help("set the log level: off, error, warn, info, debug, trace")
  84. .default_value("warn")
  85. .takes_value(true))
  86. .get_matches();
  87. let (verbosity, quiet) = match args.value_of("log_level").unwrap().to_ascii_lowercase().as_str() {
  88. "off" => (0, true),
  89. "error" => (0, false),
  90. "warn" => (1, false),
  91. "info" => (2, false),
  92. "debug" => (3, false),
  93. "trace" => (4, false),
  94. _ => (2, false)
  95. };
  96. stderrlog::new()
  97. .module(module_path!())
  98. .verbosity(verbosity)
  99. .quiet(quiet)
  100. .init().unwrap();
  101. // todo: ensure we are running as root (or Administrator on Windows)
  102. info!("The ID of the current user is {}", whoami::username());
  103. let password_file_opt = args.value_of("password_file");
  104. if password_file_opt.is_none() {
  105. error!("main: password-file argument is required");
  106. exit(2);
  107. }
  108. let password_file = password_file_opt.unwrap();
  109. let password_opt = args.value_of("password_env_var");
  110. let password_hash = init_password(password_file, password_opt);
  111. let proxy_ip_opt = args.value_of("proxy_ip");
  112. if proxy_ip_opt.is_none() {
  113. error!("main: proxy-ip argument is required");
  114. exit(2);
  115. }
  116. let proxy_ip = proxy_ip_opt.unwrap();
  117. if !is_private_ip(proxy_ip.to_string()) {
  118. error!("main: proxy IP must be a private IP address: {}", proxy_ip);
  119. exit(2);
  120. }
  121. let mut proxy_bind_addr = None;
  122. for iface in datalink::interfaces() {
  123. if iface.is_loopback() { continue; }
  124. if !iface.is_up() { continue; }
  125. for ip in iface.ips {
  126. if ip.ip().to_string().eq(proxy_ip) {
  127. proxy_bind_addr = Some(ip);
  128. }
  129. break;
  130. }
  131. }
  132. if proxy_bind_addr.is_none() {
  133. error!("main: Could not find IP for binding: {}", proxy_ip);
  134. exit(2);
  135. }
  136. let admin_port = args.value_of("admin_port").unwrap().parse::<u16>().unwrap();
  137. let dns1_ip = args.value_of("dns1").unwrap();
  138. let dns2_ip = args.value_of("dns2").unwrap();
  139. let proxy_port = args.value_of("proxy_port").unwrap().parse::<u16>().unwrap();
  140. let proxy_ip = proxy_bind_addr.unwrap().ip();
  141. // create a random token
  142. let auth_token = Arc::new(rand::thread_rng()
  143. .sample_iter(&Alphanumeric)
  144. .take(50)
  145. .collect::<String>());
  146. let admin = start_admin(
  147. admin_port,
  148. proxy_ip.to_string(),
  149. proxy_port,
  150. password_hash,
  151. auth_token.clone()
  152. );
  153. let proxy = start_proxy(
  154. dns1_ip,
  155. dns2_ip,
  156. proxy_ip,
  157. proxy_port,
  158. auth_token.clone()
  159. );
  160. join(admin, proxy).await;
  161. }