Fix UDP over XHTTP and intercept 10.1.0.1 for panel.ostp

This commit is contained in:
ospab 2026-05-28 19:13:39 +03:00
parent 283885244b
commit cbb0093dd5
3 changed files with 39 additions and 12 deletions

View File

@ -1096,8 +1096,13 @@ class _SettingsScreenState extends State<SettingsScreen> {
_buildTextField('Server Address', _serverCtrl, hint: 'host:port'), _buildTextField('Server Address', _serverCtrl, hint: 'host:port'),
_buildTextField('Local Proxy Bind', _localBindCtrl, hint: '127.0.0.1:1088'), _buildTextField('Local Proxy Bind', _localBindCtrl, hint: '127.0.0.1:1088'),
_buildTextField('Access Key', _keyCtrl, hint: 'Secure access key', isPassword: true), _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) ...[ 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)'), _buildTextField('MTU (Packet Size)', _mtuCtrl, hint: '1350 (decrease if connection drops)'),

View File

@ -552,6 +552,7 @@ async fn run_server_loop(
outbound.clone(), outbound.clone(),
dns_server.clone(), dns_server.clone(),
debug, debug,
&tcp_map,
).await?; ).await?;
} }
} }
@ -563,16 +564,16 @@ async fn run_server_loop(
} }
Some((session_id, stream_id, data)) = stream_rx.recv() => { Some((session_id, stream_id, data)) = stream_rx.recv() => {
if data.is_empty() { 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)) { if let Some(state) = remotes.remove(&(session_id, stream_id)) {
let _ = state.cancel_tx.try_send(()); let _ = state.cancel_tx.try_send(());
} }
} else { } 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() => { 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() => { Some((session_id, stream_id, target, res)) = connect_rx.recv() => {
match res { 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 }); 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}"))); let _ = ui_event_tx.send(UiEvent::Log(format!("Relay CONNECT ok for [{session_id}:{stream_id}] -> {target}")));
} }
Err(err) => { Err(err) => {
let _ = ui_event_tx.send(UiEvent::Log(format!("Relay CONNECT failed for [{session_id}:{stream_id}] -> {target}: {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;
} }
} }
} }

View File

@ -26,6 +26,7 @@ pub async fn handle_relay_message(
outbound_cfg: Option<OutboundConfig>, outbound_cfg: Option<OutboundConfig>,
dns_server: std::sync::Arc<crate::dns::DnsServer>, dns_server: std::sync::Arc<crate::dns::DnsServer>,
debug: bool, debug: bool,
tcp_map: &std::sync::Arc<tokio::sync::RwLock<HashMap<std::net::SocketAddr, tokio::sync::mpsc::Sender<Bytes>>>>,
) -> Result<()> { ) -> Result<()> {
match RelayMessage::decode(&payload)? { match RelayMessage::decode(&payload)? {
RelayMessage::Connect(target) => { RelayMessage::Connect(target) => {
@ -58,11 +59,16 @@ pub async fn handle_relay_message(
is_dns: true, 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(()); 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 connect_tx_clone = connect_tx.clone();
let stream_tx_clone = stream_tx.clone(); let stream_tx_clone = stream_tx.clone();
let outbound_clone = outbound_cfg.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}"))); let _ = ui_event_tx.send(UiEvent::Log(format!("Relay error from [{session_id}:{stream_id}]: {msg}")));
} }
RelayMessage::Ping(ts) => { 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::Pong(_) => {}
RelayMessage::UdpAssociate => { 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)); let _ = udp_reply_clone_dns.send((session_id, stream_id, target, resp_bytes));
} }
} else { } 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, 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) => { RelayMessage::UdpData(target, data) => {
if let Some(remote) = remotes.get_mut(&(session_id, stream_id)) { 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, dispatcher: &mut Dispatcher,
socket: &UdpSocket, socket: &UdpSocket,
ui_event_tx: &mpsc::UnboundedSender<UiEvent>, ui_event_tx: &mpsc::UnboundedSender<UiEvent>,
tcp_map: &std::sync::Arc<tokio::sync::RwLock<HashMap<std::net::SocketAddr, tokio::sync::mpsc::Sender<Bytes>>>>,
) -> Result<()> { ) -> Result<()> {
let payload = Bytes::from(msg.encode()); let payload = Bytes::from(msg.encode());
if let Some((frame, peer_addr)) = dispatcher.outbound_to_session(session_id, stream_id, payload)? { if let Some((frame, peer_addr)) = dispatcher.outbound_to_session(session_id, stream_id, payload)? {
let response_len = frame.len(); 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 { let _ = ui_event_tx.send(UiEvent::Tx {
peer: peer_addr.ip(), peer: peer_addr.ip(),
bytes: response_len, bytes: response_len,