Browse Source

Add reject support for ICMP echo supports

世界 3 months ago
parent
commit
24e15d36ce

+ 1 - 0
constant/rule.go

@@ -40,4 +40,5 @@ const (
 const (
 	RuleActionRejectMethodDefault = "default"
 	RuleActionRejectMethodDrop    = "drop"
+	RuleActionRejectMethodReply   = "reply"
 )

+ 16 - 0
docs/configuration/route/rule_action.md

@@ -2,6 +2,10 @@
 icon: material/new-box
 ---
 
+!!! quote "Changes in sing-box 1.13.0"
+
+    :material-alert: [reject](#reject)
+
 !!! quote "Changes in sing-box 1.12.0"
 
     :material-plus: [tls_fragment](#tls_fragment)  
@@ -42,6 +46,10 @@ See `route-options` fields below.
 
 ### reject
 
+!!! quote "Changes in sing-box 1.13.0"
+
+    Since sing-box 1.13.0, you can reject (or directly reply to) ICMP echo (ping) requests using `reject` action.
+
 ```json
 {
   "action": "reject",
@@ -58,9 +66,17 @@ For non-tun connections and already established connections, will just be closed
 
 #### method
 
+For TCP and UDP connections:
+
 - `default`: Reply with TCP RST for TCP connections, and ICMP port unreachable for UDP packets.
 - `drop`: Drop packets.
 
+For ICMP echo requests:
+
+- `default`: Reply with ICMP host unreachable.
+- `drop`: Drop packets.
+- `reply`: Reply with ICMP echo reply.
+
 #### no_drop
 
 If not enabled, `method` will be temporarily overwritten to `drop` after 50 triggers in 30s.

+ 16 - 0
docs/configuration/route/rule_action.zh.md

@@ -2,6 +2,10 @@
 icon: material/new-box
 ---
 
+!!! quote "sing-box 1.13.0 中的更改"
+
+    :material-alert: [reject](#reject)
+
 !!! quote "sing-box 1.12.0 中的更改"
 
     :material-plus: [tls_fragment](#tls_fragment)  
@@ -38,6 +42,10 @@ icon: material/new-box
 
 ### reject
 
+!!! quote "sing-box 1.13.0 中的更改"
+
+    自 sing-box 1.13.0 起,您可以通过 `reject` 动作拒绝(或直接回复)ICMP 回显(ping)请求。
+
 ```json
 {
   "action": "reject",
@@ -54,9 +62,17 @@ icon: material/new-box
 
 #### method
 
+对于 TCP 和 UDP 连接:
+
 - `default`: 对于 TCP 连接回复 RST,对于 UDP 包回复 ICMP 端口不可达。
 - `drop`: 丢弃数据包。
 
+对于 ICMP 回显请求:
+
+- `default`: 回复 ICMP 主机不可达。
+- `drop`: 丢弃数据包。
+- `reply`: 回复以 ICMP 回显应答。
+
 #### no_drop
 
 如果未启用,则 30 秒内触发 50 次后,`method` 将被暂时覆盖为 `drop`。

+ 1 - 1
go.mod

@@ -33,7 +33,7 @@ require (
 	github.com/sagernet/sing-shadowsocks v0.2.8
 	github.com/sagernet/sing-shadowsocks2 v0.2.1
 	github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
-	github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250826163040-4c43f4af12bf
+	github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250827122908-b76e852f59b0
 	github.com/sagernet/sing-vmess v0.2.7
 	github.com/sagernet/smux v1.5.34-mod.2
 	github.com/sagernet/tailscale v1.80.3-mod.6

+ 2 - 2
go.sum

@@ -179,8 +179,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
 github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
-github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250826163040-4c43f4af12bf h1:KpV65GHomgqrhyKGbXFFQZZ5ZegGJKO/tdlY6K+QIgQ=
-github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250826163040-4c43f4af12bf/go.mod h1:LokZYuEV3crByjQc/XRohLgfNvybtXdx5qe/I4W6S7k=
+github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250827122908-b76e852f59b0 h1:Usid4HU1TKrtao2fv/wyubdOkBHpbHdwgU9KUzWXQMM=
+github.com/sagernet/sing-tun v0.7.0-beta.1.0.20250827122908-b76e852f59b0/go.mod h1:LokZYuEV3crByjQc/XRohLgfNvybtXdx5qe/I4W6S7k=
 github.com/sagernet/sing-vmess v0.2.7 h1:2ee+9kO0xW5P4mfe6TYVWf9VtY8k1JhNysBqsiYj0sk=
 github.com/sagernet/sing-vmess v0.2.7/go.mod h1:5aYoOtYksAyS0NXDm0qKeTYW1yoE1bJVcv+XLcVoyJs=
 github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=

+ 1 - 0
option/rule_action.go

@@ -282,6 +282,7 @@ func (r *RejectActionOptions) UnmarshalJSON(bytes []byte) error {
 	case "", C.RuleActionRejectMethodDefault:
 		r.Method = C.RuleActionRejectMethodDefault
 	case C.RuleActionRejectMethodDrop:
+	case C.RuleActionRejectMethodReply:
 	default:
 		return E.New("unknown reject method: " + r.Method)
 	}

+ 16 - 0
route/route.go

@@ -113,6 +113,9 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad
 			}
 		case *R.RuleActionReject:
 			buf.ReleaseMulti(buffers)
+			if action.Method == C.RuleActionRejectMethodReply {
+				return E.New("reject method `reply` is not supported for TCP connections")
+			}
 			return action.Error(ctx)
 		case *R.RuleActionHijackDNS:
 			for _, buffer := range buffers {
@@ -228,6 +231,9 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m
 			}
 		case *R.RuleActionReject:
 			N.ReleaseMultiPacketBuffer(packetBuffers)
+			if action.Method == C.RuleActionRejectMethodReply {
+				return E.New("reject method `reply` is not supported for UDP connections")
+			}
 			return action.Error(ctx)
 		case *R.RuleActionHijackDNS:
 			return r.hijackDNSPacket(ctx, conn, packetBuffers, metadata, onClose)
@@ -267,6 +273,16 @@ func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.Dire
 	if selectedRule != nil {
 		switch action := selectedRule.Action().(type) {
 		case *R.RuleActionReject:
+			switch metadata.Network {
+			case N.NetworkTCP:
+				if action.Method == C.RuleActionRejectMethodReply {
+					return nil, E.New("reject method `reply` is not supported for TCP connections")
+				}
+			case N.NetworkUDP:
+				if action.Method == C.RuleActionRejectMethodReply {
+					return nil, E.New("reject method `reply` is not supported for UDP connections")
+				}
+			}
 			return nil, action.Error(context.Background())
 		case *R.RuleActionRoute:
 			if routeContext == nil {

+ 2 - 0
route/rule/rule_action.go

@@ -327,6 +327,8 @@ func (r *RuleActionReject) Error(ctx context.Context) error {
 		returnErr = &RejectedError{tun.ErrReset}
 	case C.RuleActionRejectMethodDrop:
 		return &RejectedError{tun.ErrDrop}
+	case C.RuleActionRejectMethodReply:
+		return nil
 	default:
 		panic(F.ToString("unknown reject method: ", r.Method))
 	}