Просмотр исходного кода

Merge pull request #88 from paspo/doctor

rustdesk-server doctor
RustDesk лет назад: 3
Родитель
Сommit
85af668a4f
2 измененных файлов с 86 добавлено и 4 удалено
  1. 2 0
      Cargo.toml
  2. 84 4
      src/utils.rs

+ 2 - 0
Cargo.toml

@@ -49,6 +49,8 @@ http = "0.2"
49 49
 flexi_logger = { version = "0.22", features = ["async", "use_chrono_for_offset"] }
50 50
 ipnetwork = "0.20"
51 51
 local-ip-address = "0.4"
52
+dns-lookup = "1.0.8"
53
+ping = "0.4.0"
52 54
 
53 55
 [build-dependencies]
54 56
 hbb_common = { path = "libs/hbb_common" }

+ 84 - 4
src/utils.rs

@@ -1,8 +1,11 @@
1
+use dns_lookup::{lookup_addr, lookup_host};
1 2
 use hbb_common::{bail, ResultType};
2 3
 use sodiumoxide::crypto::sign;
3
-use std::env;
4
-use std::process;
5
-use std::str;
4
+use std::{
5
+    env,
6
+    net::{IpAddr, TcpStream},
7
+    process, str,
8
+};
6 9
 
7 10
 fn print_help() {
8 11
     println!(
@@ -10,7 +13,8 @@ fn print_help() {
10 13
     rustdesk-util [command]\n
11 14
 Available Commands:
12 15
     genkeypair                                   Generate a new keypair
13
-    validatekeypair [public key] [secret key]    Validate an existing keypair"
16
+    validatekeypair [public key] [secret key]    Validate an existing keypair
17
+    doctor [rustdesk-server]                     Check for server connection problems"
14 18
     );
15 19
     process::exit(0x0001);
16 20
 }
@@ -68,6 +72,76 @@ fn validate_keypair(pk: &str, sk: &str) -> ResultType<()> {
68 72
     Ok(())
69 73
 }
70 74
 
75
+fn doctor_tcp(address: std::net::IpAddr, port: &str, desc: &str) {
76
+    let start = std::time::Instant::now();
77
+    let conn = format!("{}:{}", address, port);
78
+    if let Ok(_stream) = TcpStream::connect(conn.as_str()) {
79
+        let elapsed = std::time::Instant::now().duration_since(start);
80
+        println!(
81
+            "TCP Port {} ({}): OK in {} ms",
82
+            port,
83
+            desc,
84
+            elapsed.as_millis()
85
+        );
86
+    } else {
87
+        println!("TCP Port {} ({}): ERROR", port, desc);
88
+    }
89
+}
90
+
91
+fn doctor_ip(server_ip_address: std::net::IpAddr, server_address: Option<&str>) {
92
+    println!("\nChecking IP address: {}", server_ip_address);
93
+    println!("Is IPV4: {}", server_ip_address.is_ipv4());
94
+    println!("Is IPV6: {}", server_ip_address.is_ipv6());
95
+
96
+    // reverse dns lookup
97
+    // TODO: (check) doesn't seem to do reverse lookup on OSX...
98
+    let reverse = lookup_addr(&server_ip_address).unwrap();
99
+    if server_address.is_some() {
100
+        if reverse == server_address.unwrap() {
101
+            println!("Reverse DNS lookup: '{}' MATCHES server address", reverse);
102
+        } else {
103
+            println!(
104
+                "Reverse DNS lookup: '{}' DOESN'T MATCH server address '{}'",
105
+                reverse,
106
+                server_address.unwrap()
107
+            );
108
+        }
109
+    }
110
+
111
+    // TODO: ICMP ping?
112
+
113
+    // port check TCP (UDP is hard to check)
114
+    doctor_tcp(server_ip_address, "21114", "API");
115
+    doctor_tcp(server_ip_address, "21115", "hbbs extra port for nat test");
116
+    doctor_tcp(server_ip_address, "21116", "hbbs");
117
+    doctor_tcp(server_ip_address, "21117", "hbbr tcp");
118
+    doctor_tcp(server_ip_address, "21118", "hbbs websocket");
119
+    doctor_tcp(server_ip_address, "21119", "hbbr websocket");
120
+
121
+    // TODO: key check
122
+}
123
+
124
+fn doctor(server_address_unclean: &str) {
125
+    let server_address3 = server_address_unclean.trim();
126
+    let server_address2 = server_address3.to_lowercase();
127
+    let server_address = server_address2.as_str();
128
+    println!("Checking server:  {}\n", server_address);
129
+    let server_ipaddr = server_address.parse::<IpAddr>();
130
+    if server_ipaddr.is_err() {
131
+        // the passed string is not an ip address
132
+        let ips: Vec<std::net::IpAddr> = lookup_host(server_address).unwrap();
133
+        println!("Found {} IP addresses: ", ips.iter().count());
134
+
135
+        ips.iter().for_each(|ip| println!(" - {ip}"));
136
+
137
+        ips.iter().for_each(|ip| doctor_ip(*ip, Some(server_address)));
138
+
139
+    } else {
140
+        // user requested an ip address
141
+        doctor_ip(server_ipaddr.unwrap(), None);
142
+    }
143
+}
144
+
71 145
 fn main() {
72 146
     let args: Vec<_> = env::args().collect();
73 147
     if args.len() <= 1 {
@@ -88,6 +162,12 @@ fn main() {
88 162
             }
89 163
             println!("Key pair is VALID");
90 164
         }
165
+        "doctor" => {
166
+            if args.len() <= 2 {
167
+                error_then_help("You must supply the rustdesk-server address");
168
+            }
169
+            doctor(args[2].as_str());
170
+        }
91 171
         _ => print_help(),
92 172
     }
93 173
 }