diff --git a/stack.go b/stack.go index f6affa0..7014c6d 100644 --- a/stack.go +++ b/stack.go @@ -12,7 +12,10 @@ import ( "github.com/sagernet/sing/common/logger" ) -var ErrDrop = E.New("drop connections by rule") +var ( + ErrDrop = E.New("drop by rule") + ErrReset = E.New("reset by rule") +) type Stack interface { Start() error diff --git a/stack_gvisor_icmp.go b/stack_gvisor_icmp.go index cb46405..78177d7 100644 --- a/stack_gvisor_icmp.go +++ b/stack_gvisor_icmp.go @@ -4,6 +4,7 @@ package tun import ( "context" + "errors" "net/netip" "sync" "time" @@ -73,7 +74,10 @@ func (f *ICMPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pa timeout, ) }) - if err != nil { + if errors.Is(err, ErrReset) { + gWriteUnreachable(f.stack, pkt) + return true + } else if errors.Is(err, ErrDrop) { return true } if action != nil { @@ -132,7 +136,10 @@ func (f *ICMPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.Pa timeout, ) }) - if err != nil { + if errors.Is(err, ErrReset) { + gWriteUnreachable(f.stack, pkt) + return true + } else if errors.Is(err, ErrDrop) { return true } if action != nil { diff --git a/stack_system.go b/stack_system.go index d09e754..c262c5d 100644 --- a/stack_system.go +++ b/stack_system.go @@ -668,7 +668,11 @@ func (s *System) processIPv4ICMP(ipHdr header.IPv4, icmpHdr header.ICMPv4) (bool ) }) if err != nil { - return false, nil + if errors.Is(err, ErrReset) { + return false, s.rejectIPv4WithICMP(ipHdr, header.ICMPv4PortUnreachable) + } else if errors.Is(err, ErrDrop) { + return false, nil + } } if action != nil { return false, action.WritePacket(buf.As(ipHdr).ToOwned()) @@ -739,7 +743,9 @@ func (s *System) processIPv6ICMP(ipHdr header.IPv6, icmpHdr header.ICMPv6) (bool timeout, ) }) - if err != nil { + if errors.Is(err, ErrReset) { + return false, s.rejectIPv6WithICMP(ipHdr, header.ICMPv6PortUnreachable) + } else if errors.Is(err, ErrDrop) { return false, nil } if action != nil {