From 7736b014314faa4e69b3b9d5f887755c84cda36d Mon Sep 17 00:00:00 2001 From: zonyitoo Date: Wed, 18 Oct 2023 21:31:56 +0800 Subject: [PATCH] feat(local): local-tun ignore non-unicast packets --- .../shadowsocks-service/src/local/tun/mod.rs | 35 +++++++++++++++---- .../shadowsocks-service/src/local/tun/tcp.rs | 4 +-- .../shadowsocks-service/src/local/tun/udp.rs | 4 +-- src/service/local.rs | 10 ++++-- src/service/manager.rs | 3 +- src/service/server.rs | 3 +- 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/crates/shadowsocks-service/src/local/tun/mod.rs b/crates/shadowsocks-service/src/local/tun/mod.rs index aa18581d4ab4..d14057fd7165 100644 --- a/crates/shadowsocks-service/src/local/tun/mod.rs +++ b/crates/shadowsocks-service/src/local/tun/mod.rs @@ -4,7 +4,7 @@ use std::os::unix::io::RawFd; use std::{ io::{self, ErrorKind}, - net::SocketAddr, + net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, }; @@ -279,14 +279,37 @@ impl Tun { let src_port = udp_packet.src_port(); let dst_port = udp_packet.dst_port(); - let src_addr = SocketAddr::new(packet.src_addr(), src_port); + let src_ip_addr = packet.src_addr(); + let dst_ip_addr = packet.dst_addr(); + // Throw away non-unicast but allow unspecified + let src_non_unicast = match src_ip_addr { + IpAddr::V4(v4) => v4.is_broadcast() || v4.is_multicast() || v4.is_unspecified(), + IpAddr::V6(v6) => v6.is_multicast() || v6.is_unspecified(), + }; + let dst_non_unicast = match dst_ip_addr { + IpAddr::V4(v4) => v4.is_broadcast() || v4.is_multicast() || v4.is_unspecified(), + IpAddr::V6(v6) => v6.is_multicast() || v6.is_unspecified(), + }; + + let src_addr = SocketAddr::new(src_ip_addr, src_port); let dst_addr = SocketAddr::new(packet.dst_addr(), dst_port); let payload = udp_packet.payload(); - trace!("[TUN] UDP packet {} -> {} {}", src_addr, dst_addr, udp_packet); - - if let Err(err) = self.udp.handle_packet(src_addr, dst_addr, payload).await { - error!("handle UDP packet failed, err: {}, packet: {:?}", err, udp_packet); + trace!( + "[TUN] UDP packet {} (unicast? {}) -> {} (unicast? {}) {}", + src_addr, + !src_non_unicast, + dst_addr, + !dst_non_unicast, + udp_packet + ); + + if src_non_unicast || dst_non_unicast { + trace!("[TUN] UDP non-unicast packet thrown away"); + } else { + if let Err(err) = self.udp.handle_packet(src_addr, dst_addr, payload).await { + error!("handle UDP packet failed, err: {}, packet: {:?}", err, udp_packet); + } } } IpProtocol::Icmp | IpProtocol::Icmpv6 => { diff --git a/crates/shadowsocks-service/src/local/tun/tcp.rs b/crates/shadowsocks-service/src/local/tun/tcp.rs index 35b63e531726..cf2a68feac0c 100644 --- a/crates/shadowsocks-service/src/local/tun/tcp.rs +++ b/crates/shadowsocks-service/src/local/tun/tcp.rs @@ -13,7 +13,7 @@ use std::{ time::Duration, }; -use log::{error, trace}; +use log::{debug, error, trace}; use shadowsocks::{net::TcpSocketOpts, relay::socks5::Address}; use smoltcp::{ iface::{Config as InterfaceConfig, Interface, SocketHandle, SocketSet}, @@ -501,7 +501,7 @@ impl TcpTun { return Err(io::Error::new(ErrorKind::Other, format!("listen error: {:?}", err))); } - trace!("created TCP connection for {} <-> {}", src_addr, dst_addr); + debug!("created TCP connection for {} <-> {}", src_addr, dst_addr); let connection = TcpConnection::new( socket, diff --git a/crates/shadowsocks-service/src/local/tun/udp.rs b/crates/shadowsocks-service/src/local/tun/udp.rs index 0edc2f7b5faf..924f22a49625 100644 --- a/crates/shadowsocks-service/src/local/tun/udp.rs +++ b/crates/shadowsocks-service/src/local/tun/udp.rs @@ -8,7 +8,7 @@ use std::{ use async_trait::async_trait; use bytes::{BufMut, BytesMut}; use etherparse::PacketBuilder; -use log::{debug, trace}; +use log::debug; use shadowsocks::relay::socks5::Address; use tokio::sync::mpsc; @@ -51,7 +51,7 @@ impl UdpTun { dst_addr: SocketAddr, payload: &[u8], ) -> io::Result<()> { - trace!("UDP {} -> {} payload.size: {} bytes", src_addr, dst_addr, payload.len()); + debug!("UDP {} -> {} payload.size: {} bytes", src_addr, dst_addr, payload.len()); if let Err(err) = self.manager.send_to(src_addr, dst_addr.into(), payload).await { debug!( "UDP {} -> {} payload.size: {} bytes failed, error: {}", diff --git a/src/service/local.rs b/src/service/local.rs index e3b4dea740ba..64cad9b2a98f 100644 --- a/src/service/local.rs +++ b/src/service/local.rs @@ -17,7 +17,12 @@ use shadowsocks_service::shadowsocks::relay::socks5::Address; use shadowsocks_service::{ acl::AccessControl, config::{ - read_variable_field_value, Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, + read_variable_field_value, + Config, + ConfigType, + LocalConfig, + LocalInstanceConfig, + ProtocolType, ServerInstanceConfig, }, local::{loadbalancing::PingBalancer, Server}, @@ -32,7 +37,8 @@ use shadowsocks_service::{ use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, - monitor, vparser, + monitor, + vparser, }; #[cfg(feature = "local-dns")] diff --git a/src/service/manager.rs b/src/service/manager.rs index 4039577da8ba..ebf7a2ff8eae 100644 --- a/src/service/manager.rs +++ b/src/service/manager.rs @@ -27,7 +27,8 @@ use shadowsocks_service::{ use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, - monitor, vparser, + monitor, + vparser, }; /// Defines command line options diff --git a/src/service/server.rs b/src/service/server.rs index 9d30fbfc32bb..6f1fa842f878 100644 --- a/src/service/server.rs +++ b/src/service/server.rs @@ -25,7 +25,8 @@ use shadowsocks_service::{ use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, - monitor, vparser, + monitor, + vparser, }; /// Defines command line options