diff --git a/net/neterror/neterror.go b/net/neterror/neterror.go
index e2387440d33d5..abdcf093fcf06 100644
--- a/net/neterror/neterror.go
+++ b/net/neterror/neterror.go
@@ -41,7 +41,10 @@ func TreatAsLostUDP(err error) bool {
 	return false
 }
 
-var packetWasTruncated func(error) bool // non-nil on Windows at least
+var (
+	packetWasTruncated func(error) bool // non-nil on Windows at least
+	socketWasReset     func(error) bool // non-nil on Windows at least
+)
 
 // PacketWasTruncated reports whether err indicates truncation but the RecvFrom
 // that generated err was otherwise successful. On Windows, Go's UDP RecvFrom
@@ -59,6 +62,17 @@ func PacketWasTruncated(err error) bool {
 	return packetWasTruncated(err)
 }
 
+// SocketWasReset reports whether err is an error from a TCP or UDP send/recv
+// operation that should be treated as a connection reset. On Windows,
+// WSARecvFrom can return WSAECONNRESET when the remote side sends an ICMP error
+// message.
+func SocketWasReset(err error) bool {
+	if socketWasReset == nil {
+		return false
+	}
+	return socketWasReset(err)
+}
+
 var shouldDisableUDPGSO func(error) bool // non-nil on Linux
 
 func ShouldDisableUDPGSO(err error) bool {
diff --git a/net/neterror/neterror_windows.go b/net/neterror/neterror_windows.go
index bf112f5ed7ab7..55eba260d24f9 100644
--- a/net/neterror/neterror_windows.go
+++ b/net/neterror/neterror_windows.go
@@ -13,4 +13,8 @@ func init() {
 	packetWasTruncated = func(err error) bool {
 		return errors.Is(err, windows.WSAEMSGSIZE)
 	}
+
+	socketWasReset = func(err error) bool {
+		return errors.Is(err, windows.WSAECONNRESET)
+	}
 }
diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go
index b27736822af30..72c356a3c6d38 100644
--- a/wgengine/magicsock/magicsock.go
+++ b/wgengine/magicsock/magicsock.go
@@ -1236,6 +1236,12 @@ func (c *Conn) mkReceiveFunc(ruc *RebindingUDPConn, healthItem *health.ReceiveFu
 				if neterror.PacketWasTruncated(err) {
 					continue
 				}
+				if neterror.SocketWasReset(err) {
+					c.logf("magicsock: receive: rebind required due to socket reset: %v", err)
+					c.Rebind()
+					c.ReSTUN("socket-reset")
+				}
+
 				return 0, err
 			}