-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
UDP packet bypassing routing #2991
Description
Packet connection (udp) only respect the first packet it received. For example if i set a rule to reject specific ip address or protocol it can be bypassed by sending a dummy packet to a valid address through UDP socket and then send a different packet to a different address through the same socket. Found out that bufio.copyPacketWaitWithPool blindly send any packets to any destination without applying routing rules.
if i set a breakpoint to the line inside bufio.copyPacketWaitWithPool with destinationConn.WritePacket(buffer, destination) i can clearly see that the sing-box itself is sending those packets. Also it's sad that it is not logged at all, even with trace level, the log contains only
INFO[0013] [3169077631 0ms] inbound/tun[tun-in]: inbound packet connection from 172.19.16.1:17852
INFO[0013] [3169077631 0ms] inbound/tun[tun-in]: inbound packet connection to 1.2.3.4:100
INFO[0013] [3169077631 0ms] outbound/direct[direct]: outbound packet connection
Example c# code to replicate, with having a remote udp listener on a 100.100.100.100:8585
using var udpClient = new UdpClient();
var legitEndpoint = new IPEndPoint(IPAddress.Parse("1.2.3.4"), 100);
var bannedEndpoint = new IPEndPoint(IPAddress.Parse("100.100.100.100"), 8585);
await udpClient.SendAsync(new byte[] { 100 }, fakeEndpoint);
await udpClient.SendAsync(new byte[] { 200 }, bannedEndpoint );
{
"log": {
"level": "trace"
},
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"interface_name": "tun0",
"address": "172.19.16.1/30",
"stack": "gvisor",
"mtu": 9000,
"auto_route": true
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
}
],
"route": {
"final": "direct",
"auto_detect_interface": true,
"rules": [
{
"ip_cidr": "100.100.100.100/32",
"action": "reject"
}
]
}
}