Paolo Asperti лет назад: 3
Родитель
Сommit
d878222fc1
2 измененных файлов с 89 добавлено и 4 удалено
  1. 2 0
      Cargo.toml
  2. 87 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" }

+ 87 - 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,79 @@ 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
+        for ip in ips.iter() {
136
+            println!(" - {}", ip);
137
+        }
138
+
139
+        for ip in ips.iter() {
140
+            doctor_ip(*ip, Some(server_address));
141
+        }
142
+    } else {
143
+        // user requested an ip address
144
+        doctor_ip(server_ipaddr.unwrap(), None);
145
+    }
146
+}
147
+
71 148
 fn main() {
72 149
     let args: Vec<_> = env::args().collect();
73 150
     if args.len() <= 1 {
@@ -88,6 +165,12 @@ fn main() {
88 165
             }
89 166
             println!("Key pair is VALID");
90 167
         }
168
+        "doctor" => {
169
+            if args.len() <= 2 {
170
+                error_then_help("You must supply the rustdesk-server address");
171
+            }
172
+            doctor(args[2].as_str());
173
+        }
91 174
         _ => print_help(),
92 175
     }
93 176
 }