|
|
|
|
@ -1,23 +1,22 @@ |
|
|
|
|
use nix::{ |
|
|
|
|
sys::signal::{signal, SigHandler, Signal}, |
|
|
|
|
unistd::{close as fdclose, fork, getppid, setsid, ForkResult}, |
|
|
|
|
sys::signal::{SigHandler, Signal, signal}, |
|
|
|
|
unistd::{ForkResult, close as fdclose, fork, getppid, setsid}, |
|
|
|
|
}; |
|
|
|
|
use reqwest::{blocking::Client, header, Proxy}; |
|
|
|
|
use reqwest::{Proxy, blocking::Client, header}; |
|
|
|
|
use std::{ |
|
|
|
|
env, |
|
|
|
|
io::Result as IOResult, |
|
|
|
|
net::ToSocketAddrs, |
|
|
|
|
panic, |
|
|
|
|
process::{exit, Child, Command, Stdio}, |
|
|
|
|
sync::{Mutex, MutexGuard}, |
|
|
|
|
process::{Child, Command, Stdio, exit}, |
|
|
|
|
sync::{Mutex, MutexGuard, OnceLock}, |
|
|
|
|
thread, time, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
use once_cell::sync::OnceCell; |
|
|
|
|
|
|
|
|
|
mod ssh_config; |
|
|
|
|
use ssh_config::TinySSHConfig; |
|
|
|
|
|
|
|
|
|
const HOST: &str = "aws-tun"; |
|
|
|
|
const HOST: &str = "ortem-tun"; |
|
|
|
|
const BASE_CONFIG: &str = concat!(env!("HOME"), "/.ssh/config"); |
|
|
|
|
|
|
|
|
|
static mut DAEMONIZED: bool = false; |
|
|
|
|
@ -43,11 +42,11 @@ impl ThresholdCaller { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn get<'m>() -> MutexGuard<'m, Self> { |
|
|
|
|
static FAIL_NOTIFIER: OnceCell<Mutex<ThresholdCaller>> = OnceCell::new(); |
|
|
|
|
static FAIL_NOTIFIER: OnceLock<Mutex<ThresholdCaller>> = OnceLock::new(); |
|
|
|
|
FAIL_NOTIFIER |
|
|
|
|
.get_or_init(|| { |
|
|
|
|
Mutex::new(ThresholdCaller::new( |
|
|
|
|
|info| notify(format!("Can't setup socks proxy: {}", info), true), |
|
|
|
|
|info| notify(format!("Can't setup socks proxy: {}", info), false), |
|
|
|
|
5, |
|
|
|
|
)) |
|
|
|
|
}) |
|
|
|
|
@ -134,10 +133,22 @@ fn _dbg() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn notify<S: Into<String>>(msg: S, critical: bool) { |
|
|
|
|
let urg = if critical { "critical" } else { "normal" }; |
|
|
|
|
let (urg, prefix) = if critical { |
|
|
|
|
("critical", "Отвалилась жопа: ") |
|
|
|
|
} else { |
|
|
|
|
("normal", "") |
|
|
|
|
}; |
|
|
|
|
spawn( |
|
|
|
|
"notify-send", |
|
|
|
|
&["-t", "5000", "-u", urg, &format!("sockser: {}", msg.into())], |
|
|
|
|
&[ |
|
|
|
|
"-a", |
|
|
|
|
env!("CARGO_PKG_NAME"), |
|
|
|
|
"-t", |
|
|
|
|
"5000", |
|
|
|
|
"-u", |
|
|
|
|
urg, |
|
|
|
|
&format!("{prefix}{}", msg.into()), |
|
|
|
|
], |
|
|
|
|
) |
|
|
|
|
.unwrap() |
|
|
|
|
.wait() |
|
|
|
|
@ -177,7 +188,7 @@ fn kill_by_cmd(cmd: &str) { |
|
|
|
|
fn monitor_connection(ssh_host: &str) -> ! { |
|
|
|
|
let config = TinySSHConfig::parse(BASE_CONFIG).expect("ssh config file has wrong format"); |
|
|
|
|
let host = config.get_host(ssh_host).expect("no host found in config"); |
|
|
|
|
assert!(host.can_be_proxy()); |
|
|
|
|
assert!(host.can_be_proxy(), "expected DynamicForward entry"); |
|
|
|
|
let proxy = Proxy::all(&format!( |
|
|
|
|
"socks5://127.0.0.1:{}", |
|
|
|
|
host.get("DynamicForward").unwrap() |
|
|
|
|
@ -194,7 +205,11 @@ fn monitor_connection(ssh_host: &str) -> ! { |
|
|
|
|
.default_headers(headers) |
|
|
|
|
.build() |
|
|
|
|
.unwrap(); |
|
|
|
|
let proxy_ip = host.get("HostName").unwrap(); |
|
|
|
|
let proxy_ip = { |
|
|
|
|
let host = host.get("HostName").unwrap(); |
|
|
|
|
let host = format!("{host}:80"); |
|
|
|
|
host.to_socket_addrs().unwrap().next().unwrap().ip() |
|
|
|
|
}; |
|
|
|
|
let killer = |msg| { |
|
|
|
|
ThresholdCaller::get().append_fail(Some(msg)); |
|
|
|
|
kill_by_cmd(ssh_host); |
|
|
|
|
@ -204,11 +219,11 @@ fn monitor_connection(ssh_host: &str) -> ! { |
|
|
|
|
match client.get("https://2ip.ru/").send() { |
|
|
|
|
Ok(resp) => match resp.text() { |
|
|
|
|
Ok(received_ip) => { |
|
|
|
|
if received_ip.trim() != *proxy_ip { |
|
|
|
|
if received_ip.trim() != proxy_ip.to_string() { |
|
|
|
|
killer("wrong ip"); |
|
|
|
|
} else { |
|
|
|
|
if ThresholdCaller::get().was_triggered() { |
|
|
|
|
notify("reconnected", false); |
|
|
|
|
notify("Соединение восстановлено", false); |
|
|
|
|
} |
|
|
|
|
ThresholdCaller::get().reset(); |
|
|
|
|
} |
|
|
|
|
|