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

feat: Add KeyExchange and Encrypted tcpstream

From https://github.com/rustdesk/rustdesk-server/pull/400/commits/7e6ddf06a988d31beaf80dc6ea12ad70068b38cb

------
lejianwen 1 год назад
Родитель
Сommit
9bae660559
3 измененных файлов с 203 добавлено и 33 удалено
  1. 5 0
      libs/hbb_common/protos/rendezvous.proto
  2. 75 23
      libs/hbb_common/src/tcp.rs
  3. 123 10
      src/rendezvous_server.rs

+ 5 - 0
libs/hbb_common/protos/rendezvous.proto

@@ -157,6 +157,10 @@ message OnlineResponse {
157 157
   bytes states = 1;
158 158
 }
159 159
 
160
+message KeyExchange {
161
+  repeated bytes keys = 1;
162
+}
163
+
160 164
 message RendezvousMessage {
161 165
   oneof union {
162 166
     RegisterPeer register_peer = 6;
@@ -178,5 +182,6 @@ message RendezvousMessage {
178 182
     PeerDiscovery peer_discovery = 22;
179 183
     OnlineRequest online_request = 23;
180 184
     OnlineResponse online_response = 24;
185
+    KeyExchange key_exchange = 25;
181 186
   }
182 187
 }

+ 75 - 23
libs/hbb_common/src/tcp.rs

@@ -3,7 +3,10 @@ use anyhow::Context as AnyhowCtx;
3 3
 use bytes::{BufMut, Bytes, BytesMut};
4 4
 use futures::{SinkExt, StreamExt};
5 5
 use protobuf::Message;
6
-use sodiumoxide::crypto::secretbox::{self, Key, Nonce};
6
+use sodiumoxide::crypto::{
7
+    box_,
8
+    secretbox::{self, Key, Nonce},
9
+};
7 10
 use std::{
8 11
     io::{self, Error, ErrorKind},
9 12
     net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
@@ -21,10 +24,13 @@ use tokio_util::codec::Framed;
21 24
 pub trait TcpStreamTrait: AsyncRead + AsyncWrite + Unpin {}
22 25
 pub struct DynTcpStream(Box<dyn TcpStreamTrait + Send + Sync>);
23 26
 
27
+#[derive(Clone)]
28
+pub struct Encrypt(Key, u64, u64);
29
+
24 30
 pub struct FramedStream(
25 31
     Framed<DynTcpStream, BytesCodec>,
26 32
     SocketAddr,
27
-    Option<(Key, u64, u64)>,
33
+    Option<Encrypt>,
28 34
     u64,
29 35
 );
30 36
 
@@ -130,7 +136,7 @@ impl FramedStream {
130 136
                     ms_timeout,
131 137
                     Socks5Stream::connect_with_socket(stream, target),
132 138
                 )
133
-                .await??
139
+                    .await??
134 140
             } else {
135 141
                 super::timeout(
136 142
                     ms_timeout,
@@ -138,7 +144,7 @@ impl FramedStream {
138 144
                         stream, target, username, password,
139 145
                     ),
140 146
                 )
141
-                .await??
147
+                    .await??
142 148
             };
143 149
             let addr = stream.local_addr()?;
144 150
             return Ok(Self(
@@ -185,10 +191,10 @@ impl FramedStream {
185 191
     #[inline]
186 192
     pub async fn send_raw(&mut self, msg: Vec<u8>) -> ResultType<()> {
187 193
         let mut msg = msg;
194
+        log::debug!("Send message: {:?}", msg);
188 195
         if let Some(key) = self.2.as_mut() {
189
-            key.1 += 1;
190
-            let nonce = Self::get_nonce(key.1);
191
-            msg = secretbox::seal(&msg, &nonce, &key.0);
196
+            log::debug!("Encrypting message");
197
+            msg = key.enc(&msg);
192 198
         }
193 199
         self.send_bytes(bytes::Bytes::from(msg)).await?;
194 200
         Ok(())
@@ -207,18 +213,10 @@ impl FramedStream {
207 213
     #[inline]
208 214
     pub async fn next(&mut self) -> Option<Result<BytesMut, Error>> {
209 215
         let mut res = self.0.next().await;
210
-        if let Some(key) = self.2.as_mut() {
211
-            if let Some(Ok(bytes)) = res.as_mut() {
212
-                key.2 += 1;
213
-                let nonce = Self::get_nonce(key.2);
214
-                match secretbox::open(bytes, &nonce, &key.0) {
215
-                    Ok(res) => {
216
-                        bytes.clear();
217
-                        bytes.put_slice(&res);
218
-                    }
219
-                    Err(()) => {
220
-                        return Some(Err(Error::new(ErrorKind::Other, "decryption error")));
221
-                    }
216
+        if let Some(Ok(bytes)) = res.as_mut() {
217
+            if let Some(key) = self.2.as_mut() {
218
+                if let Err(err) = key.dec(bytes) {
219
+                    return Some(Err(err));
222 220
                 }
223 221
             }
224 222
         }
@@ -235,7 +233,7 @@ impl FramedStream {
235 233
     }
236 234
 
237 235
     pub fn set_key(&mut self, key: Key) {
238
-        self.2 = Some((key, 0, 0));
236
+        self.2 = Some(Encrypt::new(key));
239 237
     }
240 238
 
241 239
     fn get_nonce(seqnum: u64) -> Nonce {
@@ -274,6 +272,8 @@ pub async fn listen_any(port: u16, reuse: bool) -> ResultType<TcpListener> {
274 272
         }
275 273
         #[cfg(unix)]
276 274
         {
275
+            socket.set_reuseport(true).ok();
276
+            socket.set_reuseaddr(true).ok();
277 277
             use std::os::unix::io::{FromRawFd, IntoRawFd};
278 278
             let raw_fd = socket.into_raw_fd();
279 279
             let sock2 = unsafe { socket2::Socket::from_raw_fd(raw_fd) };
@@ -297,9 +297,11 @@ pub async fn listen_any(port: u16, reuse: bool) -> ResultType<TcpListener> {
297 297
             }
298 298
         }
299 299
     }
300
-    let s = TcpSocket::new_v4()?;
301
-    s.bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port))?;
302
-    Ok(s.listen(DEFAULT_BACKLOG)?)
300
+    Ok(new_socket(
301
+        SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), port),
302
+        true,
303
+    )?
304
+        .listen(DEFAULT_BACKLOG)?)
303 305
 }
304 306
 
305 307
 impl Unpin for DynTcpStream {}
@@ -333,3 +335,53 @@ impl AsyncWrite for DynTcpStream {
333 335
 }
334 336
 
335 337
 impl<R: AsyncRead + AsyncWrite + Unpin> TcpStreamTrait for R {}
338
+
339
+impl Encrypt {
340
+    pub fn new(key: Key) -> Self {
341
+        Self(key, 0, 0)
342
+    }
343
+
344
+    pub fn dec(&mut self, bytes: &mut bytes::BytesMut) -> Result<(), Error> {
345
+        if bytes.len() <= 1 {
346
+            return Ok(());
347
+        }
348
+        self.2 += 1;
349
+        let nonce = FramedStream::get_nonce(self.2);
350
+        match secretbox::open(bytes, &nonce, &self.0) {
351
+            Ok(res) => {
352
+                bytes.clear();
353
+                bytes.put_slice(&res);
354
+                Ok(())
355
+            }
356
+            Err(()) => Err(Error::new(ErrorKind::Other, "decryption error")),
357
+        }
358
+    }
359
+
360
+    pub fn enc(&mut self, data: &[u8]) -> Vec<u8> {
361
+        self.1 += 1;
362
+        let nonce = FramedStream::get_nonce(self.1);
363
+        secretbox::seal(&data, &nonce, &self.0)
364
+    }
365
+
366
+    pub fn decode(
367
+        symmetric_data: &[u8],
368
+        their_pk_b: &[u8],
369
+        our_sk_b: &box_::SecretKey,
370
+    ) -> ResultType<Key> {
371
+        if their_pk_b.len() != box_::PUBLICKEYBYTES {
372
+            anyhow::bail!("Handshake failed: pk length {}", their_pk_b.len());
373
+        }
374
+        let nonce = box_::Nonce([0u8; box_::NONCEBYTES]);
375
+        let mut pk_ = [0u8; box_::PUBLICKEYBYTES];
376
+        pk_[..].copy_from_slice(their_pk_b);
377
+        let their_pk_b = box_::PublicKey(pk_);
378
+        let symmetric_key = box_::open(symmetric_data, &nonce, &their_pk_b, &our_sk_b)
379
+            .map_err(|_| anyhow::anyhow!("Handshake failed: box decryption failure"))?;
380
+        if symmetric_key.len() != secretbox::KEYBYTES {
381
+            anyhow::bail!("Handshake failed: invalid secret key length from peer");
382
+        }
383
+        let mut key = [0u8; secretbox::KEYBYTES];
384
+        key[..].copy_from_slice(&symmetric_key);
385
+        Ok(Key(key))
386
+    }
387
+}

+ 123 - 10
src/rendezvous_server.rs

@@ -1,5 +1,6 @@
1 1
 use crate::common::*;
2 2
 use crate::peer::*;
3
+use hbb_common::bytes::BufMut;
3 4
 use hbb_common::{
4 5
     allow_err, bail,
5 6
     bytes::{Bytes, BytesMut},
@@ -13,9 +14,15 @@ use hbb_common::{
13 14
     log,
14 15
     protobuf::{Message as _, MessageField},
15 16
     rendezvous_proto::{
16
-        register_pk_response::Result::{TOO_FREQUENT, UUID_MISMATCH},
17
+        register_pk_response::Result::{INVALID_ID_FORMAT, TOO_FREQUENT, UUID_MISMATCH},
17 18
         *,
18 19
     },
20
+    sodiumoxide::crypto::{
21
+        box_, box_::PublicKey, box_::SecretKey, secretbox, secretbox::Key, secretbox::Nonce, sign,
22
+    },
23
+    sodiumoxide::hex,
24
+    tcp,
25
+    tcp::Encrypt,
19 26
     tcp::{listen_any, FramedStream},
20 27
     timeout,
21 28
     tokio::{
@@ -31,7 +38,7 @@ use hbb_common::{
31 38
     AddrMangle, ResultType,
32 39
 };
33 40
 use ipnetwork::Ipv4Network;
34
-use sodiumoxide::crypto::sign;
41
+
35 42
 use std::{
36 43
     collections::HashMap,
37 44
     net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
@@ -50,10 +57,14 @@ enum Data {
50 57
 const REG_TIMEOUT: i32 = 30_000;
51 58
 type TcpStreamSink = SplitSink<Framed<TcpStream, BytesCodec>, Bytes>;
52 59
 type WsSink = SplitSink<tokio_tungstenite::WebSocketStream<TcpStream>, tungstenite::Message>;
53
-enum Sink {
60
+enum SinkType {
54 61
     TcpStream(TcpStreamSink),
55 62
     Ws(WsSink),
56 63
 }
64
+struct Sink {
65
+    tx: SinkType,
66
+    key: Arc<Mutex<Option<Encrypt>>>,
67
+}
57 68
 type Sender = mpsc::UnboundedSender<Data>;
58 69
 type Receiver = mpsc::UnboundedReceiver<Data>;
59 70
 static ROTATION_RELAY_SERVER: AtomicUsize = AtomicUsize::new(0);
@@ -69,6 +80,8 @@ struct Inner {
69 80
     mask: Option<Ipv4Network>,
70 81
     local_ip: String,
71 82
     sk: Option<sign::SecretKey>,
83
+    secure_tcp_pk_b: PublicKey,
84
+    secure_tcp_sk_b: SecretKey,
72 85
 }
73 86
 
74 87
 #[derive(Clone)]
@@ -119,6 +132,8 @@ impl RendezvousServer {
119 132
                     .unwrap_or_default(),
120 133
             )
121 134
         };
135
+        // For privacy use per connection key pair
136
+        let (secure_tcp_pk_b, secure_tcp_sk_b) = box_::gen_keypair();
122 137
         let mut rs = Self {
123 138
             tcp_punch: Arc::new(Mutex::new(HashMap::new())),
124 139
             pm,
@@ -133,6 +148,8 @@ impl RendezvousServer {
133 148
                 sk,
134 149
                 mask,
135 150
                 local_ip,
151
+                secure_tcp_pk_b,
152
+                secure_tcp_sk_b,
136 153
             }),
137 154
         };
138 155
         log::info!("mask: {:?}", rs.inner.mask);
@@ -554,6 +571,37 @@ impl RendezvousServer {
554 571
                     });
555 572
                     Self::send_to_sink(sink, msg_out).await;
556 573
                 }
574
+                Some(rendezvous_message::Union::KeyExchange(ex)) => {
575
+                    log::trace!("KeyExchange {:?} <- bytes: {:?}", addr, hex::encode(&bytes));
576
+                    if ex.keys.len() != 2 {
577
+                        log::error!("Handshake failed: invalid phase 2 key exchange message");
578
+                        return false;
579
+                    }
580
+                    log::trace!("KeyExchange their_pk: {:?}", hex::encode(&ex.keys[0]));
581
+                    log::trace!("KeyExchange box: {:?}", hex::encode(&ex.keys[1]));
582
+                    let their_pk: [u8; 32] = ex.keys[0].to_vec().try_into().unwrap();
583
+                    let cryptobox: [u8; 48] = ex.keys[1].to_vec().try_into().unwrap();
584
+                    let symetric_key = get_symetric_key_from_msg(
585
+                        self.inner.secure_tcp_sk_b.0,
586
+                        their_pk,
587
+                        &cryptobox,
588
+                    );
589
+                    log::debug!("KeyExchange symetric key: {:?}", hex::encode(&symetric_key));
590
+                    let key = secretbox::Key::from_slice(&symetric_key);
591
+                    match key {
592
+                        Some(key) => {
593
+                            if let Some(sink) = sink.as_mut() {
594
+                                sink.key.lock().await.replace(Encrypt::new(key));
595
+                            }
596
+                            log::debug!("KeyExchange symetric key set");
597
+                            return true;
598
+                        }
599
+                        None => {
600
+                            log::error!("KeyExchange symetric key NOT set");
601
+                            return false;
602
+                        }
603
+                    }
604
+                }
557 605
                 _ => {}
558 606
             }
559 607
         }
@@ -803,12 +851,15 @@ impl RendezvousServer {
803 851
     #[inline]
804 852
     async fn send_to_sink(sink: &mut Option<Sink>, msg: RendezvousMessage) {
805 853
         if let Some(sink) = sink.as_mut() {
806
-            if let Ok(bytes) = msg.write_to_bytes() {
807
-                match sink {
808
-                    Sink::TcpStream(s) => {
854
+            if let Ok(mut bytes) = msg.write_to_bytes() {
855
+                if let Some(enc) = &mut sink.key.lock().await.as_mut() {
856
+                    bytes = enc.enc(&bytes);
857
+                }
858
+                match &mut sink.tx {
859
+                    SinkType::TcpStream(s) => {
809 860
                         allow_err!(s.send(Bytes::from(bytes)).await);
810 861
                     }
811
-                    Sink::Ws(ws) => {
862
+                    SinkType::Ws(ws) => {
812 863
                         allow_err!(ws.send(tungstenite::Message::Binary(bytes)).await);
813 864
                     }
814 865
                 }
@@ -1130,7 +1181,10 @@ impl RendezvousServer {
1130 1181
             };
1131 1182
             let ws_stream = tokio_tungstenite::accept_hdr_async(stream, callback).await?;
1132 1183
             let (a, mut b) = ws_stream.split();
1133
-            sink = Some(Sink::Ws(a));
1184
+            sink = Some(Sink {
1185
+                tx: SinkType::Ws(a),
1186
+                key: Arc::new(Mutex::new(None)),
1187
+            });
1134 1188
             while let Ok(Some(Ok(msg))) = timeout(30_000, b.next()).await {
1135 1189
                 if let tungstenite::Message::Binary(bytes) = msg {
1136 1190
                     if !self.handle_tcp(&bytes, &mut sink, addr, key, ws).await {
@@ -1140,8 +1194,23 @@ impl RendezvousServer {
1140 1194
             }
1141 1195
         } else {
1142 1196
             let (a, mut b) = Framed::new(stream, BytesCodec::new()).split();
1143
-            sink = Some(Sink::TcpStream(a));
1144
-            while let Ok(Some(Ok(bytes))) = timeout(30_000, b.next()).await {
1197
+            let enc = Arc::new(Mutex::new(None));
1198
+            sink = Some(Sink {
1199
+                tx: SinkType::TcpStream(a),
1200
+                key: enc.clone(),
1201
+            });
1202
+            // Avoid key exchange if answering on nat helper port
1203
+            if !key.is_empty() {
1204
+                self.key_exchange_phase1(addr, &mut sink).await;
1205
+            }
1206
+            while let Ok(Some(Ok(mut bytes))) = timeout(30_000, b.next()).await {
1207
+                let mut enc_lock = enc.lock().await;
1208
+                if enc_lock.is_some() {
1209
+                    if let Err(err) = enc_lock.as_mut().unwrap().dec(&mut bytes) {
1210
+                        return Err(err.into());
1211
+                    }
1212
+                }
1213
+                drop(enc_lock);
1145 1214
                 if !self.handle_tcp(&bytes, &mut sink, addr, key, ws).await {
1146 1215
                     break;
1147 1216
                 }
@@ -1224,6 +1293,31 @@ impl RendezvousServer {
1224 1293
         }
1225 1294
         false
1226 1295
     }
1296
+
1297
+    async fn key_exchange_phase1(&mut self, addr: SocketAddr, sink: &mut Option<Sink>) {
1298
+        let mut msg_out = RendezvousMessage::new();
1299
+        log::debug!("KeyExchange phase 1: send our pk for this tcp connection in a message signed with our server key");
1300
+        let sk = &self.inner.sk;
1301
+        match sk {
1302
+            Some(sk) => {
1303
+                let our_pk_b = self.inner.secure_tcp_pk_b.clone();
1304
+                let sm = sign::sign(&our_pk_b.0, &sk);
1305
+
1306
+                let bytes_sm = Bytes::from(sm);
1307
+                msg_out.set_key_exchange(KeyExchange {
1308
+                    keys: vec![bytes_sm],
1309
+                    ..Default::default()
1310
+                });
1311
+                log::trace!(
1312
+                    "KeyExchange {:?} -> bytes: {:?}",
1313
+                    addr,
1314
+                    hex::encode(Bytes::from(msg_out.write_to_bytes().unwrap()))
1315
+                );
1316
+                Self::send_to_sink(sink, msg_out).await;
1317
+            }
1318
+            None => {}
1319
+        }
1320
+    }
1227 1321
 }
1228 1322
 
1229 1323
 async fn check_relay_servers(rs0: Arc<RelayServers>, tx: Sender) {
@@ -1323,3 +1417,22 @@ async fn create_tcp_listener(port: i32) -> ResultType<TcpListener> {
1323 1417
     log::debug!("listen on tcp {:?}", s.local_addr());
1324 1418
     Ok(s)
1325 1419
 }
1420
+
1421
+fn get_symetric_key_from_msg(
1422
+    our_sk_b: [u8; 32],
1423
+    their_pk_b: [u8; 32],
1424
+    sealed_value: &[u8; 48],
1425
+) -> [u8; 32] {
1426
+    let their_pk_b = box_::PublicKey(their_pk_b);
1427
+    let nonce = box_::Nonce([0u8; box_::NONCEBYTES]);
1428
+    let sk = box_::SecretKey(our_sk_b);
1429
+    let key = box_::open(sealed_value, &nonce, &their_pk_b, &sk);
1430
+    match key {
1431
+        Ok(key) => {
1432
+            let mut key_array = [0u8; 32];
1433
+            key_array.copy_from_slice(&key);
1434
+            key_array
1435
+        }
1436
+        Err(e) => panic!("Error while opening the seal key{:?}", e),
1437
+    }
1438
+}