1pub mod actions;
69pub mod keymethod;
70pub mod packet;
71pub mod peer;
72pub mod reliable;
73pub mod session;
74pub mod tls_channel;
75
76use crate::llm::action_helper::call_llm;
77use crate::llm::actions::protocol_trait::ActionResult;
78use crate::llm::ollama_client::OllamaClient;
79use crate::logging::emit::Log;
80use crate::protocol::Event;
81use crate::server::connection::ConnectionId;
82use crate::state::app_state::AppState;
83use crate::state::server::{ConnectionState, ConnectionStatus, ProtocolConnectionInfo};
84use crate::utils::clock::Instant;
85use crate::utils::wire_failure::WireFailure;
86use actions::{OpenvpnProtocol, OPENVPN_KEY_EXCHANGE_EVENT, OPENVPN_PEER_RESET_EVENT};
87use anyhow::{Context, Result};
88use keymethod::ClientKeyMethod2;
89use packet::{ControlFrame, DataFrame};
90use peer::{Peer, PeerAdmission, PeerManager};
91use session::{ControlSession, SessionEvent, SessionManager};
92use std::net::SocketAddr;
93use std::sync::Arc;
94use tokio::net::UdpSocket;
95use tokio::sync::mpsc;
96use tracing::{debug, error, trace, warn};
97
98const MAX_PEERS: usize = 100;
100
101const PEER_IDLE_TIMEOUT_SECS: u64 = 120;
103
104const SWEEP_INTERVAL_SECS: u64 = 30;
106
107const RETRANSMIT_TICK_MS: u64 = 250;
110
111pub struct OpenvpnServer {
113 socket: Arc<UdpSocket>,
114 local_addr: SocketAddr,
115 peer_manager: Arc<PeerManager>,
116 sessions: Arc<SessionManager>,
117 server_session_id: u64,
119 tls_config: Arc<rustls::ServerConfig>,
120 llm_client: Arc<OllamaClient>,
121}
122
123impl OpenvpnServer {
124 pub async fn spawn_with_llm_actions(
131 bind_addr: SocketAddr,
132 llm_client: Arc<OllamaClient>,
133 app_state: Arc<AppState>,
134 server_id: crate::state::ServerId,
135 status_tx: mpsc::UnboundedSender<String>,
136 ) -> Result<SocketAddr> {
137 let tls = tokio::task::spawn_blocking(tls_channel::build_control_channel_tls)
140 .await
141 .context("TLS setup task for the OpenVPN control channel panicked")??;
142
143 let socket = UdpSocket::bind(bind_addr)
144 .await
145 .with_context(|| format!("Failed to bind OpenVPN UDP socket on {}", bind_addr))?;
146 let local_addr = socket.local_addr()?;
147
148 let server_session_id = rand::random::<u64>();
149
150 let log = Log::new(Some(&status_tx));
151 log.info(format!(
152 "OpenVPN control-channel server listening on {} (session id {:016x})",
153 local_addr, server_session_id
154 ));
155 log.info(format!(
159 "OpenVPN control channel peer fingerprint SHA256={}",
160 tls.fingerprint
161 ));
162 log.warn(
163 "OpenVPN carries no traffic: the control channel completes a TLS handshake and the \
164 key method 2 exchange, but PUSH_REQUEST is not answered, no data channel keys are \
165 derived and there is no TUN device, so no tunnel is ever established. Use WireGuard \
166 for a real VPN.",
167 );
168
169 let server = Arc::new(OpenvpnServer {
170 socket: Arc::new(socket),
171 local_addr,
172 peer_manager: Arc::new(PeerManager::new()),
173 sessions: Arc::new(SessionManager::new()),
174 server_session_id,
175 tls_config: tls.config,
176 llm_client,
177 });
178
179 let loop_server = server.clone();
184 let loop_state = app_state.clone();
185 let loop_status = status_tx.clone();
186 let accept_handle = tokio::spawn(async move {
187 tokio::select! {
188 res = loop_server.clone().recv_loop(loop_state.clone(), server_id, loop_status.clone()) => {
189 if let Err(e) = res {
190 error!("OpenVPN receive loop stopped: {}", e);
191 }
192 }
193 _ = loop_server.clone().sweep_loop(loop_state, server_id) => {}
194 _ = loop_server.retransmit_loop() => {}
195 }
196 });
197
198 app_state
199 .register_server_task(server_id, accept_handle)
200 .await;
201
202 log.info(format!("OpenVPN server ready on {}", local_addr));
203 Ok(local_addr)
204 }
205
206 async fn recv_loop(
208 self: Arc<Self>,
209 app_state: Arc<AppState>,
210 server_id: crate::state::ServerId,
211 status_tx: mpsc::UnboundedSender<String>,
212 ) -> Result<()> {
213 let mut buf = vec![0u8; packet::MAX_PACKET_SIZE];
214
215 loop {
216 let (len, peer_addr) = self.socket.recv_from(&mut buf).await?;
217 let datagram = &buf[..len];
218
219 trace!("OpenVPN: {} bytes from {}", len, peer_addr);
220
221 let (opcode, key_id) = match packet::parse_opcode_byte(datagram) {
222 Ok(v) => v,
223 Err(e) => {
224 debug!("OpenVPN: undecodable datagram from {}: {}", peer_addr, e);
225 continue;
226 }
227 };
228
229 if opcode.is_tls_crypt_v2() {
230 Log::new(Some(&status_tx)).warn(format!(
231 "OpenVPN: {} uses tls-crypt-v2 ({:?}), which this server cannot decode; ignoring",
232 peer_addr, opcode
233 ));
234 continue;
235 }
236
237 if opcode.is_data() {
238 self.handle_data(datagram, peer_addr, &status_tx).await;
239 continue;
240 }
241
242 let frame = match ControlFrame::parse(datagram) {
243 Ok(f) => f,
244 Err(e) => {
245 debug!("OpenVPN: malformed {:?} from {}: {}", opcode, peer_addr, e);
246 continue;
247 }
248 };
249
250 if opcode.is_client_reset() {
251 self.clone()
252 .handle_client_reset(
253 frame,
254 peer_addr,
255 key_id,
256 app_state.clone(),
257 server_id,
258 status_tx.clone(),
259 )
260 .await;
261 } else if opcode.is_ack() {
262 self.handle_ack(frame, peer_addr).await;
263 } else {
264 self.clone()
265 .handle_control(
266 frame,
267 peer_addr,
268 app_state.clone(),
269 server_id,
270 status_tx.clone(),
271 )
272 .await;
273 }
274 }
275 }
276
277 async fn sweep_loop(
280 self: Arc<Self>,
281 app_state: Arc<AppState>,
282 server_id: crate::state::ServerId,
283 ) {
284 let mut ticker = tokio::time::interval(std::time::Duration::from_secs(SWEEP_INTERVAL_SECS));
285 ticker.tick().await; loop {
288 ticker.tick().await;
289 let expired = self
290 .peer_manager
291 .remove_idle_peers(std::time::Duration::from_secs(PEER_IDLE_TIMEOUT_SECS))
292 .await;
293 for peer in expired {
294 debug!("OpenVPN: forgetting idle peer {}", peer.addr);
295 self.sessions.remove(&peer.addr).await;
296 if peer.admission == PeerAdmission::Accepted {
297 app_state
298 .close_connection_on_server(server_id, peer.connection_id)
299 .await;
300 }
301 }
302 }
303 }
304
305 async fn retransmit_loop(self: Arc<Self>) {
312 let mut ticker =
313 tokio::time::interval(std::time::Duration::from_millis(RETRANSMIT_TICK_MS));
314 loop {
315 ticker.tick().await;
316 let (datagrams, dead) = self.sessions.drain_all(Instant::now()).await;
317 for (addr, datagram) in datagrams {
318 if let Err(e) = self.socket.send_to(&datagram, addr).await {
319 warn!("OpenVPN: retransmission to {} failed: {}", addr, e);
320 }
321 }
322 for addr in dead {
323 debug!(
324 "OpenVPN: {} stopped acknowledging control packets; dropping its session",
325 addr
326 );
327 self.sessions.remove(&addr).await;
328 }
329 }
330 }
331
332 async fn handle_client_reset(
335 self: Arc<Self>,
336 frame: ControlFrame,
337 peer_addr: SocketAddr,
338 key_id: u8,
339 app_state: Arc<AppState>,
340 server_id: crate::state::ServerId,
341 status_tx: mpsc::UnboundedSender<String>,
342 ) {
343 if !frame.is_plain_reset() {
347 Log::new(Some(&status_tx)).warn(format!(
348 "OpenVPN: reset from {} is not a plain reset ({} payload bytes, {} ACKs); \
349 the client is probably using --tls-auth or --tls-crypt, which is not \
350 supported. Ignoring rather than mis-parsing it.",
351 peer_addr,
352 frame.payload.len(),
353 frame.ack_packet_ids.len()
354 ));
355 return;
356 }
357
358 let client_packet_id = frame.packet_id.unwrap_or(0);
359
360 if let Some(existing) = self.peer_manager.get_peer(&peer_addr).await {
364 if existing.session_id == frame.session_id {
365 match existing.admission {
366 PeerAdmission::Deciding => {
367 trace!(
368 "OpenVPN: reset retransmit from {} while a decision is in flight",
369 peer_addr
370 );
371 }
372 PeerAdmission::Accepted => {
373 self.sessions
375 .with(&peer_addr, |s| s.on_client_reset_retransmit())
376 .await;
377 self.flush_peer(peer_addr).await;
378 }
379 PeerAdmission::Rejected => {
380 trace!(
381 "OpenVPN: ignoring reset retransmit from rejected {}",
382 peer_addr
383 );
384 }
385 }
386 self.peer_manager.touch(&peer_addr).await;
387 return;
388 }
389 debug!("OpenVPN: {} restarted with a new session id", peer_addr);
391 self.peer_manager.remove_peer(&peer_addr).await;
392 self.sessions.remove(&peer_addr).await;
393 }
394
395 if self.peer_manager.count().await >= MAX_PEERS {
396 Log::new(Some(&status_tx)).warn(format!(
397 "OpenVPN: peer table full ({}), ignoring reset from {}",
398 MAX_PEERS, peer_addr
399 ));
400 return;
401 }
402
403 let connection_id = ConnectionId::new(app_state.get_next_unified_id().await);
404 let peer = Peer::new(connection_id, peer_addr, frame.session_id, key_id);
405 self.peer_manager.add_peer(peer).await;
406
407 Log::new(Some(&status_tx)).info(format!(
408 "OpenVPN reset from {} (session {:016x}, {:?})",
409 peer_addr, frame.session_id, frame.opcode
410 ));
411
412 let this = self.clone();
415 let task_owner = app_state.clone();
417 task_owner
418 .spawn_server_task(server_id, async move {
419 this.decide_and_answer(
420 peer_addr,
421 connection_id,
422 frame,
423 key_id,
424 client_packet_id,
425 app_state,
426 server_id,
427 status_tx,
428 )
429 .await;
430 })
431 .await;
432 }
433
434 #[allow(clippy::too_many_arguments)]
459 async fn decide_and_answer(
460 &self,
461 peer_addr: SocketAddr,
462 connection_id: ConnectionId,
463 frame: ControlFrame,
464 key_id: u8,
465 client_packet_id: u32,
466 app_state: Arc<AppState>,
467 server_id: crate::state::ServerId,
468 status_tx: mpsc::UnboundedSender<String>,
469 ) {
470 let event = Event::new(
471 &OPENVPN_PEER_RESET_EVENT,
472 serde_json::json!({
473 "peer_addr": peer_addr.to_string(),
474 "client_session_id": format!("{:016x}", frame.session_id),
475 "key_id": key_id,
476 "reset_type": format!("{:?}", frame.opcode),
477 "packet_id": client_packet_id,
478 "peer_count": self.peer_manager.count().await,
479 }),
480 );
481
482 let protocol = OpenvpnProtocol::new();
483 let outcome = call_llm(
484 &self.llm_client,
485 &app_state,
486 server_id,
487 Some(connection_id),
488 &event,
489 &protocol,
490 )
491 .await;
492
493 let log = Log::new(Some(&status_tx));
494 let decision = match outcome {
495 Ok(result) => {
496 for message in &result.messages {
497 log.info(message);
498 }
499 extract_decision(&result.protocol_results, actions::PEER_DECISION_RESULT)
500 }
501 Err(e) => {
502 let class = match WireFailure::classify(&e) {
507 WireFailure::Overloaded => "overloaded",
508 WireFailure::Unavailable => "unavailable",
509 };
510 log.error(format!(
511 "OpenVPN {} decision=fail_closed_llm_error class={} - leaving it \
512 unanswered (the protocol has no reply that is not an admission): {}",
513 peer_addr, class, e
514 ));
515 None
516 }
517 };
518
519 match decision {
520 Some(Decision::Accept { reason }) => {
521 self.accept_peer(
522 peer_addr,
523 connection_id,
524 frame.session_id,
525 key_id,
526 client_packet_id,
527 reason,
528 &app_state,
529 server_id,
530 &status_tx,
531 )
532 .await;
533 }
534 Some(Decision::Reject { reason }) => {
535 self.peer_manager
536 .set_admission(&peer_addr, PeerAdmission::Rejected)
537 .await;
538 log.info(format!(
539 "OpenVPN {} decision=model_reject - refused, no reply sent ({})",
540 peer_addr,
541 reason.as_deref().unwrap_or("no reason given")
542 ));
543 }
544 None => {
545 self.peer_manager
549 .set_admission(&peer_addr, PeerAdmission::Rejected)
550 .await;
551 log.warn(format!(
552 "OpenVPN {} decision=fail_closed_no_action - the model produced neither \
553 accept_peer nor reject_peer; leaving it unanswered",
554 peer_addr
555 ));
556 }
557 }
558 }
559
560 #[allow(clippy::too_many_arguments)]
562 async fn accept_peer(
563 &self,
564 peer_addr: SocketAddr,
565 connection_id: ConnectionId,
566 client_session_id: u64,
567 key_id: u8,
568 client_packet_id: u32,
569 reason: Option<String>,
570 app_state: &Arc<AppState>,
571 server_id: crate::state::ServerId,
572 status_tx: &mpsc::UnboundedSender<String>,
573 ) {
574 let control = match ControlSession::new(
575 connection_id,
576 client_session_id,
577 self.server_session_id,
578 key_id,
579 client_packet_id,
580 self.tls_config.clone(),
581 ) {
582 Ok(s) => s,
583 Err(e) => {
584 self.peer_manager
588 .set_admission(&peer_addr, PeerAdmission::Rejected)
589 .await;
590 Log::new(Some(status_tx)).error(format!(
591 "OpenVPN {} decision=fail_closed_no_control_channel - could not start a \
592 control session, so nothing was sent: {}",
593 peer_addr, e
594 ));
595 return;
596 }
597 };
598
599 self.sessions.insert(peer_addr, control).await;
600 self.peer_manager
601 .update_peer(&peer_addr, |p| {
602 p.admission = PeerAdmission::Accepted;
603 })
604 .await;
605
606 let sent = self.flush_peer(peer_addr).await;
607 if sent == 0 {
608 Log::new(Some(status_tx)).error(format!(
609 "OpenVPN: reply to {} could not be sent; the peer is left unanswered",
610 peer_addr
611 ));
612 self.sessions.remove(&peer_addr).await;
613 self.peer_manager
614 .set_admission(&peer_addr, PeerAdmission::Rejected)
615 .await;
616 return;
617 }
618
619 let now = crate::utils::clock::Instant::now();
620 app_state
621 .add_connection_to_server(
622 server_id,
623 ConnectionState {
624 id: connection_id,
625 remote_addr: peer_addr,
626 local_addr: self.local_addr,
627 bytes_sent: sent,
628 bytes_received: 0,
629 packets_sent: 1,
630 packets_received: 1,
631 last_activity: now,
632 status: ConnectionStatus::Active,
633 status_changed_at: now,
634 protocol_info: ProtocolConnectionInfo::empty(),
635 },
636 )
637 .await;
638 let _ = status_tx.send("__UPDATE_UI__".to_string());
639
640 Log::new(Some(status_tx)).info(format!(
641 "OpenVPN {} decision=model_accept - answered with HARD_RESET_SERVER_V2 ({} bytes){}",
642 peer_addr,
643 sent,
644 reason.map(|r| format!(" - {}", r)).unwrap_or_default()
645 ));
646 }
647
648 async fn flush_peer(&self, peer_addr: SocketAddr) -> u64 {
655 let datagrams = self
656 .sessions
657 .with(&peer_addr, |s| s.drain_datagrams(Instant::now()))
658 .await
659 .unwrap_or_default();
660
661 let mut sent = 0u64;
662 for datagram in &datagrams {
663 match self.socket.send_to(datagram, peer_addr).await {
664 Ok(n) => sent = sent.saturating_add(n as u64),
665 Err(e) => {
666 warn!("OpenVPN: send to {} failed: {}", peer_addr, e);
667 break;
668 }
669 }
670 }
671 if sent > 0 {
672 self.peer_manager
673 .update_peer(&peer_addr, |p| p.record_sent(sent))
674 .await;
675 }
676 sent
677 }
678
679 async fn handle_control(
682 self: Arc<Self>,
683 frame: ControlFrame,
684 peer_addr: SocketAddr,
685 app_state: Arc<AppState>,
686 server_id: crate::state::ServerId,
687 status_tx: mpsc::UnboundedSender<String>,
688 ) {
689 match self.peer_manager.get_peer(&peer_addr).await {
690 Some(p) if p.admission == PeerAdmission::Accepted => {}
691 Some(_) => {
692 trace!("OpenVPN: control packet from unanswered peer {}", peer_addr);
693 return;
694 }
695 None => {
696 trace!("OpenVPN: control packet from unknown peer {}", peer_addr);
697 return;
698 }
699 }
700
701 let payload_len = frame.payload.len();
702 let hint = describe_tls_payload(&frame.payload);
703 trace!(
704 "OpenVPN: control payload from {}: {}",
705 peer_addr,
706 hex_prefix(&frame.payload, 64)
707 );
708
709 let events = match self
710 .sessions
711 .with(&peer_addr, |s| s.on_control_frame(frame))
712 .await
713 {
714 Some(events) => events,
715 None => {
716 trace!("OpenVPN: control packet from {} has no session", peer_addr);
717 return;
718 }
719 };
720
721 let (first_control, connection_id) = self
722 .peer_manager
723 .update_peer_returning(&peer_addr, |p| {
724 p.record_received(payload_len as u64);
725 let first = !p.saw_control_payload;
726 p.saw_control_payload = true;
727 (first, Some(p.connection_id))
728 })
729 .await
730 .unwrap_or((false, None));
731
732 if let Some(connection_id) = connection_id {
736 app_state
737 .update_connection_stats(
738 server_id,
739 connection_id,
740 Some(payload_len as u64),
741 None,
742 Some(1),
743 None,
744 )
745 .await;
746 }
747
748 if first_control && payload_len > 0 {
749 Log::new(Some(&status_tx)).info(format!(
750 "OpenVPN: {} sent {} ({} bytes); feeding it to the control-channel TLS session",
751 peer_addr, hint, payload_len
752 ));
753 }
754
755 self.flush_peer(peer_addr).await;
757
758 for event in events {
759 self.clone()
760 .handle_session_event(event, peer_addr, &app_state, server_id, &status_tx)
761 .await;
762 }
763 }
764
765 async fn handle_session_event(
767 self: Arc<Self>,
768 event: SessionEvent,
769 peer_addr: SocketAddr,
770 app_state: &Arc<AppState>,
771 server_id: crate::state::ServerId,
772 status_tx: &mpsc::UnboundedSender<String>,
773 ) {
774 let log = Log::new(Some(status_tx));
775 match event {
776 SessionEvent::TlsEstablished { version, cipher } => {
777 log.info(format!(
778 "OpenVPN {} control channel TLS handshake completed ({}, {})",
779 peer_addr, version, cipher
780 ));
781 }
782 SessionEvent::ClientKeyExchange(km2) => {
783 let connection_id = self
784 .sessions
785 .with(&peer_addr, |s| s.connection_id)
786 .await
787 .unwrap_or_else(|| ConnectionId::new(0));
788
789 log.info(format!(
790 "OpenVPN {} sent key method 2: username {:?}, {} bytes of peer info",
791 peer_addr,
792 km2.username,
793 km2.peer_info.len()
794 ));
795 debug!(
799 "OpenVPN {} credentials: username={:?} password={:?} options={:?}",
800 peer_addr, km2.username, km2.password, km2.options
801 );
802
803 let this = self.clone();
804 let state = app_state.clone();
805 let status = status_tx.clone();
806 let task_owner = app_state.clone();
808 task_owner
809 .spawn_server_task(server_id, async move {
810 this.decide_key_exchange(
811 peer_addr,
812 connection_id,
813 km2,
814 state,
815 server_id,
816 status,
817 )
818 .await;
819 })
820 .await;
821 }
822 SessionEvent::ControlMessage(message) => {
823 if message.starts_with("PUSH_REQUEST") {
824 log.warn(format!(
825 "OpenVPN {} sent PUSH_REQUEST, which this server does not answer: it \
826 derives no data channel keys and has no TUN device, so the client will \
827 time out here rather than build a tunnel",
828 peer_addr
829 ));
830 } else {
831 log.info(format!(
832 "OpenVPN {} control message: {}",
833 peer_addr,
834 crate::utils::truncate::truncate_for_log(&message, 200)
835 ));
836 }
837 }
838 SessionEvent::TlsFailed(reason) => {
839 log.warn(format!(
840 "OpenVPN {} control-channel TLS session failed: {}",
841 peer_addr, reason
842 ));
843 self.flush_peer(peer_addr).await;
846 }
847 }
848 }
849
850 async fn decide_key_exchange(
865 self: Arc<Self>,
866 peer_addr: SocketAddr,
867 connection_id: ConnectionId,
868 km2: Box<ClientKeyMethod2>,
869 app_state: Arc<AppState>,
870 server_id: crate::state::ServerId,
871 status_tx: mpsc::UnboundedSender<String>,
872 ) {
873 let event = Event::new(
877 &OPENVPN_KEY_EXCHANGE_EVENT,
878 serde_json::json!({
879 "peer_addr": peer_addr.to_string(),
880 "username": km2.username,
881 "password": km2.password,
882 "has_credentials": !km2.username.is_empty(),
883 "options": km2.options,
884 "peer_info": keymethod::peer_info_map(&km2.peer_info),
885 }),
886 );
887
888 let protocol = OpenvpnProtocol::new();
889 let outcome = call_llm(
890 &self.llm_client,
891 &app_state,
892 server_id,
893 Some(connection_id),
894 &event,
895 &protocol,
896 )
897 .await;
898
899 let log = Log::new(Some(&status_tx));
900 let decision = match outcome {
901 Ok(result) => {
902 for message in &result.messages {
903 log.info(message);
904 }
905 extract_decision(
906 &result.protocol_results,
907 actions::KEY_EXCHANGE_DECISION_RESULT,
908 )
909 }
910 Err(e) => {
911 let class = match WireFailure::classify(&e) {
912 WireFailure::Overloaded => "overloaded",
913 WireFailure::Unavailable => "unavailable",
914 };
915 log.error(format!(
916 "OpenVPN {} decision=fail_closed_llm_error class={} - key exchange left \
917 unanswered (no message at this point in the handshake means anything but \
918 'admitted'): {}",
919 peer_addr, class, e
920 ));
921 None
922 }
923 };
924
925 match decision {
926 Some(Decision::Accept { reason }) => {
927 let written = self
928 .sessions
929 .with(&peer_addr, |s| s.write_key_method_2_answer(&km2.options))
930 .await;
931 match written {
932 Some(Ok(options)) => {
933 self.flush_peer(peer_addr).await;
934 log.info(format!(
935 "OpenVPN {} decision=model_accept - answered key method 2 with \
936 options {:?}{}",
937 peer_addr,
938 crate::utils::truncate::truncate_for_log(&options, 160),
939 reason.map(|r| format!(" - {}", r)).unwrap_or_default()
940 ));
941 }
942 Some(Err(e)) => log.error(format!(
943 "OpenVPN {} decision=fail_closed_write_error - the key method 2 answer \
944 could not be written: {}",
945 peer_addr, e
946 )),
947 None => log.warn(format!(
948 "OpenVPN {} decision=fail_closed_no_session - the control session was \
949 gone before the key method 2 answer could be written",
950 peer_addr
951 )),
952 }
953 }
954 Some(Decision::Reject { reason }) => {
955 log.info(format!(
956 "OpenVPN {} decision=model_reject - key exchange refused, nothing sent ({})",
957 peer_addr,
958 reason.as_deref().unwrap_or("no reason given")
959 ));
960 self.sessions.remove(&peer_addr).await;
961 }
962 None => {
963 log.warn(format!(
964 "OpenVPN {} decision=fail_closed_no_action - the model produced neither \
965 accept_key_exchange nor reject_key_exchange; the key exchange is left \
966 unanswered",
967 peer_addr
968 ));
969 self.sessions.remove(&peer_addr).await;
970 }
971 }
972 }
973
974 async fn handle_ack(&self, frame: ControlFrame, peer_addr: SocketAddr) {
977 trace!(
978 "OpenVPN: ACK from {} for {:?}",
979 peer_addr,
980 frame.ack_packet_ids
981 );
982 self.sessions
983 .with(&peer_addr, |s| s.on_ack_frame(&frame))
984 .await;
985 self.peer_manager.touch(&peer_addr).await;
986 }
987
988 async fn handle_data(
996 &self,
997 datagram: &[u8],
998 peer_addr: SocketAddr,
999 status_tx: &mpsc::UnboundedSender<String>,
1000 ) {
1001 let frame = match DataFrame::parse(datagram) {
1002 Ok(f) => f,
1003 Err(e) => {
1004 debug!("OpenVPN: malformed data packet from {}: {}", peer_addr, e);
1005 return;
1006 }
1007 };
1008
1009 let first = self
1010 .peer_manager
1011 .update_peer_returning(&peer_addr, |p| {
1012 p.record_received(frame.payload.len() as u64);
1013 let first = !p.saw_data_packet;
1014 p.saw_data_packet = true;
1015 first
1016 })
1017 .await
1018 .unwrap_or(false);
1019
1020 debug!(
1021 "OpenVPN: dropping {:?} from {} ({} ciphertext bytes, peer id {:?}): no data \
1022 channel keys exist",
1023 frame.opcode,
1024 peer_addr,
1025 frame.payload.len(),
1026 frame.peer_id
1027 );
1028
1029 if first {
1030 Log::new(Some(status_tx)).warn(format!(
1031 "OpenVPN: {} sent a data packet, but this server derives no data channel keys, \
1032 so it cannot be decrypted and is dropped",
1033 peer_addr
1034 ));
1035 }
1036 }
1037
1038 pub async fn accepted_peers(&self) -> Vec<SocketAddr> {
1040 self.peer_manager
1041 .get_all_peers()
1042 .await
1043 .into_iter()
1044 .filter(|p| p.admission == PeerAdmission::Accepted)
1045 .map(|p| p.addr)
1046 .collect()
1047 }
1048}
1049
1050enum Decision {
1052 Accept { reason: Option<String> },
1053 Reject { reason: Option<String> },
1054}
1055
1056fn extract_decision(results: &[ActionResult], wanted: &str) -> Option<Decision> {
1062 fn walk(results: &[ActionResult], wanted: &str, out: &mut Option<Decision>) {
1063 for result in results {
1064 if out.is_some() {
1065 return;
1066 }
1067 match result {
1068 ActionResult::Custom { name, data } if name == wanted => {
1069 let reason = data
1070 .get("reason")
1071 .and_then(|v| v.as_str())
1072 .map(|s| s.to_string());
1073 match data.get("accept").and_then(|v| v.as_bool()) {
1074 Some(true) => *out = Some(Decision::Accept { reason }),
1075 Some(false) => *out = Some(Decision::Reject { reason }),
1076 None => {}
1077 }
1078 }
1079 ActionResult::Multiple(inner) => walk(inner, wanted, out),
1080 _ => {}
1081 }
1082 }
1083 }
1084
1085 let mut out = None;
1086 walk(results, wanted, &mut out);
1087 out
1088}
1089
1090fn describe_tls_payload(payload: &[u8]) -> &'static str {
1092 match payload.first() {
1093 Some(0x16) => "a TLS handshake record (ClientHello)",
1094 Some(0x14) => "a TLS change-cipher-spec record",
1095 Some(0x15) => "a TLS alert record",
1096 Some(0x17) => "a TLS application-data record",
1097 Some(_) => "a non-TLS control payload",
1098 None => "an empty control payload",
1099 }
1100}
1101
1102fn hex_prefix(data: &[u8], limit: usize) -> String {
1104 let shown = &data[..data.len().min(limit)];
1105 let mut s = String::with_capacity(shown.len() * 2 + 16);
1106 for b in shown {
1107 s.push_str(&format!("{:02x}", b));
1108 }
1109 if data.len() > shown.len() {
1110 s.push_str(&format!("... ({} bytes total)", data.len()));
1111 }
1112 s
1113}