修复空载荷包越界 panic 杀死数据面任务

对端构造的零载荷包(头部长度恰好等于 HEAD_LENGTH)会使
TunDataInbound/InternalNatInbound 的 data[0] 索引越界 panic,
tokio 任务终止后连接永久静默死亡。两处 send 均增加空切片检查,
畸形包静默丢弃。补充空包/短包不 panic 的测试。
This commit is contained in:
lbl
2026-08-20 21:48:24 +08:00
parent b0db6c9659
commit 6489237233
2 changed files with 38 additions and 2 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ impl InternalNatInbound {
})
}
pub async fn send(&self, data: &[u8], net: &NetworkAddr) -> anyhow::Result<()> {
if data[0] >> 4 != 4 {
if data.is_empty() || data[0] >> 4 != 4 {
return Ok(());
}
let Some(ipv4) = Ipv4Packet::new(data) else {
+37 -1
View File
@@ -20,7 +20,7 @@ impl TunDataInbound {
impl TunDataInbound {
pub async fn send(&self, data: TransmissionBytes, net: &NetworkAddr) -> anyhow::Result<()> {
if data[0] >> 4 != 4 {
if data.is_empty() || data[0] >> 4 != 4 {
return Ok(());
}
let Some(ipv4) = Ipv4Packet::new(data.as_ref()) else {
@@ -38,3 +38,39 @@ impl TunDataInbound {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::nat::AllowSubnetExternalRoute;
use crate::tun::tun_channel;
use std::net::Ipv4Addr;
fn test_net() -> NetworkAddr {
NetworkAddr {
gateway: Ipv4Addr::new(10, 26, 0, 1),
broadcast: Ipv4Addr::new(10, 26, 0, 255),
ip: Ipv4Addr::new(10, 26, 0, 2),
prefix_len: 24,
}
}
/// 对端构造的零载荷/畸形包必须被静默丢弃,不能 panic 杀死数据面任务
#[tokio::test]
async fn test_send_empty_or_short_packet_does_not_panic() {
let (tun_inbound, _receiver) = tun_channel();
let inbound = TunDataInbound::new(tun_inbound, AllowSubnetExternalRoute::new(vec![]));
// 零载荷包(头部被剥离后为空)
inbound
.send(TransmissionBytes::zeroed(0), &test_net())
.await
.unwrap();
// 过短的包(不足 IPv4 头)
inbound
.send(TransmissionBytes::zeroed(3), &test_net())
.await
.unwrap();
}
}