Browse Source

Merge branch 'master' of https://github.com/open-trade/hbbs

rustdesk 4 years ago
parent
commit
a8d3ba56b2
7 changed files with 229 additions and 16 deletions
  1. 52 1
      Cargo.lock
  2. 6 1
      Cargo.toml
  3. 1 1
      libs/hbb_common
  4. 7 1
      src/hbbr.rs
  5. 110 0
      src/lic.rs
  6. 9 0
      src/main.rs
  7. 44 12
      src/rendezvous_server.rs

+ 52 - 1
Cargo.lock

@@ -223,6 +223,12 @@ dependencies = [
223
  "lazy_static",
223
  "lazy_static",
224
 ]
224
 ]
225
 
225
 
226
+[[package]]
227
+name = "cryptoxide"
228
+version = "0.3.2"
229
+source = "registry+https://github.com/rust-lang/crates.io-index"
230
+checksum = "46212f5d1792f89c3e866fb10636139464060110c568edd7f73ab5e9f736c26d"
231
+
226
 [[package]]
232
 [[package]]
227
 name = "ct-logs"
233
 name = "ct-logs"
228
 version = "0.6.0"
234
 version = "0.6.0"
@@ -514,6 +520,7 @@ dependencies = [
514
  "protobuf-codegen-pure",
520
  "protobuf-codegen-pure",
515
  "quinn",
521
  "quinn",
516
  "rand",
522
  "rand",
523
+ "regex",
517
  "serde",
524
  "serde",
518
  "serde_derive",
525
  "serde_derive",
519
  "serde_json",
526
  "serde_json",
@@ -530,15 +537,20 @@ dependencies = [
530
 name = "hbbs"
537
 name = "hbbs"
531
 version = "1.1.3"
538
 version = "1.1.3"
532
 dependencies = [
539
 dependencies = [
533
- "cc",
540
+ "base64 0.13.0",
534
  "clap",
541
  "clap",
542
+ "cryptoxide",
535
  "hbb_common",
543
  "hbb_common",
536
  "lazy_static",
544
  "lazy_static",
545
+ "mac_address",
546
+ "machine-uid",
547
+ "minreq",
537
  "rocksdb",
548
  "rocksdb",
538
  "rust-ini",
549
  "rust-ini",
539
  "serde",
550
  "serde",
540
  "serde_derive",
551
  "serde_derive",
541
  "serde_json",
552
  "serde_json",
553
+ "whoami",
542
 ]
554
 ]
543
 
555
 
544
 [[package]]
556
 [[package]]
@@ -687,12 +699,30 @@ dependencies = [
687
  "winapi 0.3.9",
699
  "winapi 0.3.9",
688
 ]
700
 ]
689
 
701
 
702
+[[package]]
703
+name = "machine-uid"
704
+version = "0.2.0"
705
+source = "registry+https://github.com/rust-lang/crates.io-index"
706
+checksum = "1f1595709b0a7386bcd56ba34d250d626e5503917d05d32cdccddcd68603e212"
707
+dependencies = [
708
+ "winreg",
709
+]
710
+
690
 [[package]]
711
 [[package]]
691
 name = "memchr"
712
 name = "memchr"
692
 version = "2.3.4"
713
 version = "2.3.4"
693
 source = "registry+https://github.com/rust-lang/crates.io-index"
714
 source = "registry+https://github.com/rust-lang/crates.io-index"
694
 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
715
 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
695
 
716
 
717
+[[package]]
718
+name = "minreq"
719
+version = "2.3.1"
720
+source = "registry+https://github.com/rust-lang/crates.io-index"
721
+checksum = "781e56f7d29192378f0a04948b1e6aec67ce561273b2dd26ac510bbe88d7be70"
722
+dependencies = [
723
+ "punycode",
724
+]
725
+
696
 [[package]]
726
 [[package]]
697
 name = "mio"
727
 name = "mio"
698
 version = "0.6.22"
728
 version = "0.6.22"
@@ -945,6 +975,12 @@ dependencies = [
945
  "protobuf-codegen",
975
  "protobuf-codegen",
946
 ]
976
 ]
947
 
977
 
978
+[[package]]
979
+name = "punycode"
980
+version = "0.4.1"
981
+source = "registry+https://github.com/rust-lang/crates.io-index"
982
+checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe"
983
+
948
 [[package]]
984
 [[package]]
949
 name = "quick-error"
985
 name = "quick-error"
950
 version = "1.2.3"
986
 version = "1.2.3"
@@ -1549,6 +1585,12 @@ dependencies = [
1549
  "libc",
1585
  "libc",
1550
 ]
1586
 ]
1551
 
1587
 
1588
+[[package]]
1589
+name = "whoami"
1590
+version = "0.9.0"
1591
+source = "registry+https://github.com/rust-lang/crates.io-index"
1592
+checksum = "7884773ab69074615cb8f8425d0e53f11710786158704fca70f53e71b0e05504"
1593
+
1552
 [[package]]
1594
 [[package]]
1553
 name = "winapi"
1595
 name = "winapi"
1554
 version = "0.2.8"
1596
 version = "0.2.8"
@@ -1592,6 +1634,15 @@ version = "0.4.0"
1592
 source = "registry+https://github.com/rust-lang/crates.io-index"
1634
 source = "registry+https://github.com/rust-lang/crates.io-index"
1593
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1635
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1594
 
1636
 
1637
+[[package]]
1638
+name = "winreg"
1639
+version = "0.6.2"
1640
+source = "registry+https://github.com/rust-lang/crates.io-index"
1641
+checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
1642
+dependencies = [
1643
+ "winapi 0.3.9",
1644
+]
1645
+
1595
 [[package]]
1646
 [[package]]
1596
 name = "ws2_32-sys"
1647
 name = "ws2_32-sys"
1597
 version = "0.2.1"
1648
 version = "0.2.1"

+ 6 - 1
Cargo.toml

@@ -19,9 +19,14 @@ serde_json = "1.0"
19
 lazy_static = "1.4"
19
 lazy_static = "1.4"
20
 clap = "2.33"
20
 clap = "2.33"
21
 rust-ini = "0.16"
21
 rust-ini = "0.16"
22
+minreq = { version = "2.3.1", features = ["punycode"] }
23
+machine-uid = "0.2"
24
+mac_address = "1.1"
25
+whoami = "0.9"
26
+base64 = "0.13"
27
+cryptoxide = "0.3"
22
 
28
 
23
 [build-dependencies]
29
 [build-dependencies]
24
-cc = "1.0"
25
 hbb_common = { path = "libs/hbb_common" }
30
 hbb_common = { path = "libs/hbb_common" }
26
 
31
 
27
 [workspace]
32
 [workspace]

+ 1 - 1
libs/hbb_common

@@ -1 +1 @@
1
-Subproject commit 002939a1037c786d2651a779492a7c813ea4e54a
1
+Subproject commit 99487187a6b25380b9a412f040f43f319ece7545

+ 7 - 1
src/hbbr.rs

@@ -3,14 +3,17 @@ mod relay_server;
3
 use hbb_common::{env_logger::*, ResultType};
3
 use hbb_common::{env_logger::*, ResultType};
4
 use relay_server::*;
4
 use relay_server::*;
5
 use std::sync::{Arc, Mutex};
5
 use std::sync::{Arc, Mutex};
6
+mod lic;
6
 
7
 
7
 fn main() -> ResultType<()> {
8
 fn main() -> ResultType<()> {
8
     init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
9
     init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
9
     let args = format!(
10
     let args = format!(
10
         "-p, --port=[NUMBER(default={})] 'Sets the listening port'
11
         "-p, --port=[NUMBER(default={})] 'Sets the listening port'
11
         -k, --key=[KEY] 'Only allow the client with the same key'
12
         -k, --key=[KEY] 'Only allow the client with the same key'
13
+        {}
12
         ",
14
         ",
13
-        DEFAULT_PORT
15
+        DEFAULT_PORT,
16
+        lic::EMAIL_ARG
14
     );
17
     );
15
     let matches = App::new("hbbr")
18
     let matches = App::new("hbbr")
16
         .version(hbbs::VERSION)
19
         .version(hbbs::VERSION)
@@ -18,6 +21,9 @@ fn main() -> ResultType<()> {
18
         .about("RustDesk Relay Server")
21
         .about("RustDesk Relay Server")
19
         .args_from_usage(&args)
22
         .args_from_usage(&args)
20
         .get_matches();
23
         .get_matches();
24
+    if !lic::check_lic(matches.value_of("email").unwrap_or("")) {
25
+        return Ok(());
26
+    }
21
     let stop: Arc<Mutex<bool>> = Default::default();
27
     let stop: Arc<Mutex<bool>> = Default::default();
22
     start(
28
     start(
23
         matches.value_of("port").unwrap_or(DEFAULT_PORT),
29
         matches.value_of("port").unwrap_or(DEFAULT_PORT),

+ 110 - 0
src/lic.rs

@@ -0,0 +1,110 @@
1
+use hbb_common::{bail, log, ResultType};
2
+use serde_derive::{Deserialize, Serialize};
3
+use std::io::prelude::*;
4
+use std::path::Path;
5
+
6
+#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)]
7
+pub struct Machine {
8
+    #[serde(default)]
9
+    hostname: String,
10
+    #[serde(default)]
11
+    uid: String,
12
+    #[serde(default)]
13
+    mac: String,
14
+}
15
+
16
+#[derive(Debug, PartialEq, Default, Serialize, Deserialize, Clone)]
17
+pub struct Post {
18
+    #[serde(default)]
19
+    machine: String,
20
+    #[serde(default)]
21
+    email: String,
22
+    #[serde(default)]
23
+    status: String,
24
+}
25
+
26
+const LICENSE_FILE: &'static str = ".license.txt";
27
+
28
+pub fn check_lic(email: &str) -> bool {
29
+    let machine = get_lic();
30
+    let path = Path::new(LICENSE_FILE);
31
+    if Path::is_file(&path) {
32
+        let contents = std::fs::read_to_string(&path).unwrap_or("".to_owned());
33
+        if verify(&contents, &machine) {
34
+            return true;
35
+        }
36
+    }
37
+
38
+    if email.is_empty() {
39
+        log::error!("Registered email required (-m option). Please visit https://rustdesk.com/server for more infomration.");
40
+        return false;
41
+    }
42
+
43
+    match check_email(machine, email.to_owned()) {
44
+        Ok(v) => {
45
+            return v;
46
+        }
47
+        Err(err) => {
48
+            log::error!("{}", err);
49
+            return false;
50
+        }
51
+    }
52
+}
53
+
54
+fn write_lic(lic: &str) {
55
+    if let Ok(mut f) = std::fs::File::create(LICENSE_FILE) {
56
+        f.write_all(lic.as_bytes()).ok();
57
+        f.sync_all().ok();
58
+    }
59
+}
60
+
61
+fn check_email(machine: String, email: String) -> ResultType<bool> {
62
+    log::info!("Checking email with the server ...");
63
+    let resp = minreq::post("http://rustdesk.com/api/check-email")
64
+        .with_body(
65
+            serde_json::to_string(&Post {
66
+                machine: machine.clone(),
67
+                email,
68
+                ..Default::default()
69
+            })
70
+            .unwrap(),
71
+        )
72
+        .send()?;
73
+    if resp.reason_phrase == "OK" {
74
+        let p: Post = serde_json::from_str(&resp.as_str()?)?;
75
+        if !p.status.is_empty() {
76
+            bail!("{}", p.status);
77
+        }
78
+        if !verify(&p.machine, &machine) {
79
+            bail!("Verification failure");
80
+        }
81
+        write_lic(&p.machine);
82
+    } else {
83
+        bail!("Server error: {}", resp.reason_phrase);
84
+    }
85
+    Ok(true)
86
+}
87
+
88
+fn get_lic() -> String {
89
+    let hostname = whoami::hostname();
90
+    let uid = machine_uid::get().unwrap_or("".to_owned());
91
+    let mac = if let Ok(Some(ma)) = mac_address::get_mac_address() {
92
+        base64::encode(ma.bytes())
93
+    } else {
94
+        "".to_owned()
95
+    };
96
+    serde_json::to_string(&Machine { hostname, uid, mac }).unwrap()
97
+}
98
+
99
+fn verify(enc_str: &str, msg: &str) -> bool {
100
+    if let Ok(data) = base64::decode(enc_str) {
101
+        let key =
102
+            b"\xf1T\xc0\x1c\xffee\x86,S*\xd9.\x91\xcd\x85\x12:\xec\xa9 \x99:\x8a\xa2S\x1f Yy\x93R";
103
+        cryptoxide::ed25519::verify(msg.as_bytes(), &key[..], &data)
104
+    } else {
105
+        false
106
+    }
107
+}
108
+
109
+pub const EMAIL_ARG: &'static str =
110
+    "-m, --email=[EMAIL] 'Sets your email address registered with RustDesk'";

+ 9 - 0
src/main.rs

@@ -4,6 +4,7 @@
4
 use clap::App;
4
 use clap::App;
5
 use hbb_common::{env_logger::*, log, ResultType};
5
 use hbb_common::{env_logger::*, log, ResultType};
6
 use hbbs::*;
6
 use hbbs::*;
7
+mod lic;
7
 use ini::Ini;
8
 use ini::Ini;
8
 use std::sync::{Arc, Mutex};
9
 use std::sync::{Arc, Mutex};
9
 
10
 
@@ -16,8 +17,11 @@ fn main() -> ResultType<()> {
16
         -R, --rendezvous-servers=[HOSTS] 'Sets rendezvous servers, seperated by colon'
17
         -R, --rendezvous-servers=[HOSTS] 'Sets rendezvous servers, seperated by colon'
17
         -u, --software-url=[URL] 'Sets download url of RustDesk software of newest version'
18
         -u, --software-url=[URL] 'Sets download url of RustDesk software of newest version'
18
         -r, --relay-servers=[HOST] 'Sets the default relay servers, seperated by colon'
19
         -r, --relay-servers=[HOST] 'Sets the default relay servers, seperated by colon'
20
+        -C, --change-id=[BOOL(default=Y)] 'Sets if support to change id'
21
+        {}
19
         -k, --key=[KEY] 'Only allow the client with the same key'",
22
         -k, --key=[KEY] 'Only allow the client with the same key'",
20
         DEFAULT_PORT,
23
         DEFAULT_PORT,
24
+        lic::EMAIL_ARG
21
     );
25
     );
22
     let matches = App::new("hbbs")
26
     let matches = App::new("hbbs")
23
         .version(crate::VERSION)
27
         .version(crate::VERSION)
@@ -43,6 +47,9 @@ fn main() -> ResultType<()> {
43
         }
47
         }
44
         return default.to_owned();
48
         return default.to_owned();
45
     };
49
     };
50
+    if !lic::check_lic(&get_arg("email", "")) {
51
+        return Ok(());
52
+    }
46
     let port = get_arg("port", DEFAULT_PORT);
53
     let port = get_arg("port", DEFAULT_PORT);
47
     let relay_servers: Vec<String> = get_arg("relay-servers", "")
54
     let relay_servers: Vec<String> = get_arg("relay-servers", "")
48
         .split(",")
55
         .split(",")
@@ -50,6 +57,7 @@ fn main() -> ResultType<()> {
50
         .map(|x| x.to_owned())
57
         .map(|x| x.to_owned())
51
         .collect();
58
         .collect();
52
     let serial: i32 = get_arg("serial", "").parse().unwrap_or(0);
59
     let serial: i32 = get_arg("serial", "").parse().unwrap_or(0);
60
+    let id_change_support: bool = get_arg("change-id", "Y").to_uppercase() == "Y";
53
     let rendezvous_servers: Vec<String> = get_arg("rendezvous-servers", "")
61
     let rendezvous_servers: Vec<String> = get_arg("rendezvous-servers", "")
54
         .split(",")
62
         .split(",")
55
         .filter(|x| !x.is_empty() && test_if_valid_server(x, "rendezvous-server").is_ok())
63
         .filter(|x| !x.is_empty() && test_if_valid_server(x, "rendezvous-server").is_ok())
@@ -69,6 +77,7 @@ fn main() -> ResultType<()> {
69
         get_arg("software-url", ""),
77
         get_arg("software-url", ""),
70
         &get_arg("key", ""),
78
         &get_arg("key", ""),
71
         stop,
79
         stop,
80
+        id_change_support,
72
     )?;
81
     )?;
73
     Ok(())
82
     Ok(())
74
 }
83
 }

+ 44 - 12
src/rendezvous_server.rs

@@ -164,6 +164,7 @@ impl RendezvousServer {
164
         software_url: String,
164
         software_url: String,
165
         key: &str,
165
         key: &str,
166
         stop: Arc<Mutex<bool>>,
166
         stop: Arc<Mutex<bool>>,
167
+        id_change_support: bool,
167
     ) -> ResultType<()> {
168
     ) -> ResultType<()> {
168
         if !key.is_empty() {
169
         if !key.is_empty() {
169
             log::info!("Key: {}", key);
170
             log::info!("Key: {}", key);
@@ -171,6 +172,7 @@ impl RendezvousServer {
171
         log::info!("Listening on tcp/udp {}", addr);
172
         log::info!("Listening on tcp/udp {}", addr);
172
         log::info!("Listening on tcp {}, extra port for NAT test", addr2);
173
         log::info!("Listening on tcp {}, extra port for NAT test", addr2);
173
         log::info!("relay-servers={:?}", relay_servers);
174
         log::info!("relay-servers={:?}", relay_servers);
175
+        log::info!("change-id={:?}", id_change_support);
174
         let mut socket = FramedSocket::new(addr).await?;
176
         let mut socket = FramedSocket::new(addr).await?;
175
         let (tx, mut rx) = mpsc::unbounded_channel::<(RendezvousMessage, SocketAddr)>();
177
         let (tx, mut rx) = mpsc::unbounded_channel::<(RendezvousMessage, SocketAddr)>();
176
         let version = hbb_common::get_version_from_url(&software_url);
178
         let version = hbb_common::get_version_from_url(&software_url);
@@ -202,6 +204,7 @@ impl RendezvousServer {
202
                 &mut socket,
204
                 &mut socket,
203
                 key,
205
                 key,
204
                 stop.clone(),
206
                 stop.clone(),
207
+                id_change_support,
205
             )
208
             )
206
             .await;
209
             .await;
207
         }
210
         }
@@ -215,6 +218,7 @@ impl RendezvousServer {
215
         socket: &mut FramedSocket,
218
         socket: &mut FramedSocket,
216
         key: &str,
219
         key: &str,
217
         stop: Arc<Mutex<bool>>,
220
         stop: Arc<Mutex<bool>>,
221
+        id_change_support: bool,
218
     ) {
222
     ) {
219
         let mut timer = interval(Duration::from_millis(100));
223
         let mut timer = interval(Duration::from_millis(100));
220
         loop {
224
         loop {
@@ -321,6 +325,31 @@ impl RendezvousServer {
321
                                         }
325
                                         }
322
                                         break;
326
                                         break;
323
                                     }
327
                                     }
328
+                                    Some(rendezvous_message::Union::register_pk(rk)) => {
329
+                                        if rk.uuid.is_empty() {
330
+                                            break;
331
+                                        }
332
+                                        let mut res = register_pk_response::Result::OK;
333
+                                        if !id_change_support {
334
+                                            res = register_pk_response::Result::NOT_SUPPORT;
335
+                                        } else if !hbb_common::is_valid_custom_id(&rk.id) {
336
+                                            res = register_pk_response::Result::INVALID_ID_FORMAT;
337
+                                        } else if let Some(peer) = rs.pm.get(&rk.id).await {
338
+                                            if peer.uuid != rk.uuid {
339
+                                                res = register_pk_response::Result::ID_EXISTS;
340
+                                            }
341
+                                        }
342
+                                        let mut msg_out = RendezvousMessage::new();
343
+                                        msg_out.set_register_pk_response(RegisterPkResponse {
344
+                                            result: res.into(),
345
+                                            ..Default::default()
346
+                                        });
347
+                                        if let Some(tcp) = sender.as_mut() {
348
+                                            if let Ok(bytes) = msg_out.write_to_bytes() {
349
+                                                allow_err!(tcp.send(Bytes::from(bytes)).await);
350
+                                            }
351
+                                        }
352
+                                    }
324
                                     _ => {
353
                                     _ => {
325
                                         break;
354
                                         break;
326
                                     }
355
                                     }
@@ -372,7 +401,7 @@ impl RendezvousServer {
372
                     let id = rk.id;
401
                     let id = rk.id;
373
                     let mut res = register_pk_response::Result::OK;
402
                     let mut res = register_pk_response::Result::OK;
374
                     if let Some(peer) = self.pm.get(&id).await {
403
                     if let Some(peer) = self.pm.get(&id).await {
375
-                        if !peer.uuid.is_empty() && peer.uuid != rk.uuid {
404
+                        if peer.uuid != rk.uuid {
376
                             log::warn!(
405
                             log::warn!(
377
                                 "Peer {} uuid mismatch: {:?} vs {:?}",
406
                                 "Peer {} uuid mismatch: {:?} vs {:?}",
378
                                 id,
407
                                 id,
@@ -380,7 +409,7 @@ impl RendezvousServer {
380
                                 peer.uuid
409
                                 peer.uuid
381
                             );
410
                             );
382
                             res = register_pk_response::Result::UUID_MISMATCH;
411
                             res = register_pk_response::Result::UUID_MISMATCH;
383
-                        } else if peer.uuid.is_empty() || peer.pk != rk.pk {
412
+                        } else if peer.pk != rk.pk {
384
                             self.pm.update_pk(id, addr, rk.uuid, rk.pk);
413
                             self.pm.update_pk(id, addr, rk.uuid, rk.pk);
385
                         }
414
                         }
386
                     } else {
415
                     } else {
@@ -611,6 +640,17 @@ impl RendezvousServer {
611
                 },
640
                 },
612
             };
641
             };
613
             let socket_addr = AddrMangle::encode(addr);
642
             let socket_addr = AddrMangle::encode(addr);
643
+            let relay_server = {
644
+                if self.relay_servers.is_empty() {
645
+                    "".to_owned()
646
+                } else {
647
+                    let i = unsafe {
648
+                        ROTATION_RELAY_SERVER += 1;
649
+                        ROTATION_RELAY_SERVER % self.relay_servers.len()
650
+                    };
651
+                    self.relay_servers[i].clone()
652
+                }
653
+            };
614
             if same_intranet {
654
             if same_intranet {
615
                 log::debug!(
655
                 log::debug!(
616
                     "Fetch local addr {:?} {:?} request from {:?}",
656
                     "Fetch local addr {:?} {:?} request from {:?}",
@@ -618,13 +658,9 @@ impl RendezvousServer {
618
                     &peer.socket_addr,
658
                     &peer.socket_addr,
619
                     &addr
659
                     &addr
620
                 );
660
                 );
621
-                let i = unsafe {
622
-                    ROTATION_RELAY_SERVER += 1;
623
-                    ROTATION_RELAY_SERVER % self.relay_servers.len()
624
-                };
625
                 msg_out.set_fetch_local_addr(FetchLocalAddr {
661
                 msg_out.set_fetch_local_addr(FetchLocalAddr {
626
                     socket_addr,
662
                     socket_addr,
627
-                    relay_server: self.relay_servers[i].clone(),
663
+                    relay_server,
628
                     ..Default::default()
664
                     ..Default::default()
629
                 });
665
                 });
630
             } else {
666
             } else {
@@ -634,14 +670,10 @@ impl RendezvousServer {
634
                     &peer.socket_addr,
670
                     &peer.socket_addr,
635
                     &addr
671
                     &addr
636
                 );
672
                 );
637
-                let i = unsafe {
638
-                    ROTATION_RELAY_SERVER += 1;
639
-                    ROTATION_RELAY_SERVER % self.relay_servers.len()
640
-                };
641
                 msg_out.set_punch_hole(PunchHole {
673
                 msg_out.set_punch_hole(PunchHole {
642
                     socket_addr,
674
                     socket_addr,
643
                     nat_type: ph.nat_type,
675
                     nat_type: ph.nat_type,
644
-                    relay_server: self.relay_servers[i].clone(),
676
+                    relay_server,
645
                     ..Default::default()
677
                     ..Default::default()
646
                 });
678
                 });
647
             }
679
             }