From cbb0093dd5f24dd4abe62998bceeef3306700ff1 Mon Sep 17 00:00:00 2001 From: ospab Date: Thu, 28 May 2026 19:13:39 +0300 Subject: [PATCH] Fix UDP over XHTTP and intercept 10.1.0.1 for panel.ostp --- ostp-flutter/lib/main.dart | 7 ++++++- ostp-server/src/lib.rs | 11 ++++++----- ostp-server/src/relay.rs | 33 +++++++++++++++++++++++++++------ 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/ostp-flutter/lib/main.dart b/ostp-flutter/lib/main.dart index 59b6a4d..2ee2592 100644 --- a/ostp-flutter/lib/main.dart +++ b/ostp-flutter/lib/main.dart @@ -1096,8 +1096,13 @@ class _SettingsScreenState extends State { _buildTextField('Server Address', _serverCtrl, hint: 'host:port'), _buildTextField('Local Proxy Bind', _localBindCtrl, hint: '127.0.0.1:1088'), _buildTextField('Access Key', _keyCtrl, hint: 'Secure access key', isPassword: true), + _buildToggle('Built-in Server DNS', 'Route DNS queries to the VPN server', _owndns, (val) { + setState(() { + _owndns = val; + }); + }), if (!_owndns) ...[ - _buildTextField('DNS Server', _dnsCtrl, hint: '1.1.1.1'), + _buildTextField('Custom DNS Server', _dnsCtrl, hint: '1.1.1.1 (e.g. 8.8.8.8)'), ], _buildTextField('MTU (Packet Size)', _mtuCtrl, hint: '1350 (decrease if connection drops)'), diff --git a/ostp-server/src/lib.rs b/ostp-server/src/lib.rs index b0148e2..5f9d36a 100644 --- a/ostp-server/src/lib.rs +++ b/ostp-server/src/lib.rs @@ -552,6 +552,7 @@ async fn run_server_loop( outbound.clone(), dns_server.clone(), debug, + &tcp_map, ).await?; } } @@ -563,16 +564,16 @@ async fn run_server_loop( } Some((session_id, stream_id, data)) = stream_rx.recv() => { if data.is_empty() { - let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::Close, &mut dispatcher, &socket, &ui_event_tx).await; + let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::Close, &mut dispatcher, &socket, &ui_event_tx, &tcp_map).await; if let Some(state) = remotes.remove(&(session_id, stream_id)) { let _ = state.cancel_tx.try_send(()); } } else { - let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::Data(data), &mut dispatcher, &socket, &ui_event_tx).await; + let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::Data(data), &mut dispatcher, &socket, &ui_event_tx, &tcp_map).await; } } Some((session_id, stream_id, target, data)) = udp_reply_rx.recv() => { - let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::UdpData(target, data), &mut dispatcher, &socket, &ui_event_tx).await; + let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::UdpData(target, data), &mut dispatcher, &socket, &ui_event_tx, &tcp_map).await; } Some((session_id, stream_id, target, res)) = connect_rx.recv() => { match res { @@ -587,12 +588,12 @@ async fn run_server_loop( } }); remotes.insert((session_id, stream_id), RemoteState { data_tx, udp_tx: None, cancel_tx, is_dns: false }); - let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::ConnectOk, &mut dispatcher, &socket, &ui_event_tx).await; + let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::ConnectOk, &mut dispatcher, &socket, &ui_event_tx, &tcp_map).await; let _ = ui_event_tx.send(UiEvent::Log(format!("Relay CONNECT ok for [{session_id}:{stream_id}] -> {target}"))); } Err(err) => { let _ = ui_event_tx.send(UiEvent::Log(format!("Relay CONNECT failed for [{session_id}:{stream_id}] -> {target}: {err}"))); - let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::Error(format!("connect failed: {err}")), &mut dispatcher, &socket, &ui_event_tx).await; + let _ = relay::send_relay_to_stream(session_id, stream_id, RelayMessage::Error(format!("connect failed: {err}")), &mut dispatcher, &socket, &ui_event_tx, &tcp_map).await; } } } diff --git a/ostp-server/src/relay.rs b/ostp-server/src/relay.rs index c04d3e5..d2b2d34 100644 --- a/ostp-server/src/relay.rs +++ b/ostp-server/src/relay.rs @@ -26,6 +26,7 @@ pub async fn handle_relay_message( outbound_cfg: Option, dns_server: std::sync::Arc, debug: bool, + tcp_map: &std::sync::Arc>>>, ) -> Result<()> { match RelayMessage::decode(&payload)? { RelayMessage::Connect(target) => { @@ -58,11 +59,16 @@ pub async fn handle_relay_message( is_dns: true, }); - send_relay_to_stream(session_id, stream_id, RelayMessage::ConnectOk, dispatcher, socket, ui_event_tx).await?; + send_relay_to_stream(session_id, stream_id, RelayMessage::ConnectOk, dispatcher, socket, ui_event_tx, tcp_map).await?; return Ok(()); } - let target_clone = target.clone(); + let mut connect_target = target.clone(); + if connect_target.starts_with("10.1.0.1:") { + connect_target = connect_target.replace("10.1.0.1:", "127.0.0.1:"); + } + + let target_clone = connect_target.clone(); let connect_tx_clone = connect_tx.clone(); let stream_tx_clone = stream_tx.clone(); let outbound_clone = outbound_cfg.clone(); @@ -120,7 +126,7 @@ pub async fn handle_relay_message( let _ = ui_event_tx.send(UiEvent::Log(format!("Relay error from [{session_id}:{stream_id}]: {msg}"))); } RelayMessage::Ping(ts) => { - send_relay_to_stream(session_id, stream_id, RelayMessage::Pong(ts), dispatcher, socket, ui_event_tx).await?; + send_relay_to_stream(session_id, stream_id, RelayMessage::Pong(ts), dispatcher, socket, ui_event_tx, tcp_map).await?; } RelayMessage::Pong(_) => {} RelayMessage::UdpAssociate => { @@ -152,7 +158,11 @@ pub async fn handle_relay_message( let _ = udp_reply_clone_dns.send((session_id, stream_id, target, resp_bytes)); } } else { - let _ = tx_sock.send_to(&data, &target).await; + let mut forward_target = target.clone(); + if forward_target.starts_with("10.1.0.1:") { + forward_target = forward_target.replace("10.1.0.1:", "127.0.0.1:"); + } + let _ = tx_sock.send_to(&data, &forward_target).await; } } }); @@ -184,7 +194,7 @@ pub async fn handle_relay_message( is_dns: false, }); - send_relay_to_stream(session_id, stream_id, RelayMessage::ConnectOk, dispatcher, socket, ui_event_tx).await?; + send_relay_to_stream(session_id, stream_id, RelayMessage::ConnectOk, dispatcher, socket, ui_event_tx, tcp_map).await?; } RelayMessage::UdpData(target, data) => { if let Some(remote) = remotes.get_mut(&(session_id, stream_id)) { @@ -206,11 +216,22 @@ pub async fn send_relay_to_stream( dispatcher: &mut Dispatcher, socket: &UdpSocket, ui_event_tx: &mpsc::UnboundedSender, + tcp_map: &std::sync::Arc>>>, ) -> Result<()> { let payload = Bytes::from(msg.encode()); if let Some((frame, peer_addr)) = dispatcher.outbound_to_session(session_id, stream_id, payload)? { let response_len = frame.len(); - let _ = socket.send_to(&frame, peer_addr).await?; + let mut sent_tcp = false; + { + let map = tcp_map.read().await; + if let Some(tx) = map.get(&peer_addr) { + let _ = tx.try_send(frame.clone()); + sent_tcp = true; + } + } + if !sent_tcp { + let _ = socket.send_to(&frame, peer_addr).await?; + } let _ = ui_event_tx.send(UiEvent::Tx { peer: peer_addr.ip(), bytes: response_len,