feat: add disable-icmp-forwarding option to tun (#2248)

When enabled, the TUN listener will use fake ping echo. This can be useful to prevent potential ICMP routing loops in certain network configurations.
This commit is contained in:
NuoFang
2025-09-07 19:40:30 +08:00
committed by GitHub
parent fed4b369a3
commit 9a124a390f
7 changed files with 16 additions and 4 deletions

View File

@@ -292,6 +292,7 @@ type RawTun struct {
ExcludePackage []string `yaml:"exclude-package" json:"exclude-package,omitempty"`
EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"`
UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"`
DisableICMPForwarding bool `yaml:"disable-icmp-forwarding" json:"disable-icmp-forwarding,omitempty"`
FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"`
Inet4RouteAddress []netip.Prefix `yaml:"inet4-route-address" json:"inet4-route-address,omitempty"`
@@ -1552,6 +1553,7 @@ func parseTun(rawTun RawTun, general *General) error {
ExcludePackage: rawTun.ExcludePackage,
EndpointIndependentNat: rawTun.EndpointIndependentNat,
UDPTimeout: rawTun.UDPTimeout,
DisableICMPForwarding: rawTun.DisableICMPForwarding,
FileDescriptor: rawTun.FileDescriptor,
Inet4RouteAddress: rawTun.Inet4RouteAddress,

View File

@@ -142,6 +142,7 @@ tun:
# gso-max-size: 65536 # 通用分段卸载包的最大大小
auto-redirect: false # 自动配置 iptables 以重定向 TCP 连接。仅支持 Linux。带有 auto-redirect 的 auto-route 现在可以在路由器上按预期工作,无需干预。
# strict-route: true # 将所有连接路由到 tun 来防止泄漏,但你的设备将无法其他设备被访问
# disable-icmp-forwarding: true # 禁用 ICMP 转发,防止某些情况下的 ICMP 环回问题ping 将不会显示真实的延迟
route-address-set: # 将指定规则集中的目标 IP CIDR 规则添加到防火墙, 不匹配的流量将绕过路由, 仅支持 Linux且需要 nftables`auto-route` 和 `auto-redirect` 已启用。
- ruleset-1
- ruleset-2
@@ -1554,6 +1555,7 @@ listeners:
# - com.android.chrome
# exclude-package: # 排除被路由的 Android 应用包名
# - com.android.captiveportallogin
# disable-icmp-forwarding: true # 禁用 ICMP 转发,防止某些情况下的 ICMP 环回问题ping 将不会显示真实的延迟
# 入口配置与 Listener 等价,传入流量将和 socks,mixed 等入口一样按照 mode 所指定的方式进行匹配处理
# shadowsocks,vmess 入口配置(传入流量将和 socks,mixed 等入口一样按照 mode 所指定的方式进行匹配处理)
# ss-config: ss://2022-blake3-aes-256-gcm:vlmpIPSyHH6f4S8WVPdRIHIlzmB+GIRfoH3aNJ/t9Gg=@:23456

View File

@@ -48,6 +48,7 @@ type Tun struct {
ExcludePackage []string `yaml:"exclude-package" json:"exclude-package,omitempty"`
EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"`
UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"`
DisableICMPForwarding bool `yaml:"disable-icmp-forwarding" json:"disable-icmp-forwarding,omitempty"`
FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"`
Inet4RouteAddress []netip.Prefix `yaml:"inet4-route-address" json:"inet4-route-address,omitempty"`
@@ -186,6 +187,9 @@ func (t *Tun) Equal(other Tun) bool {
if t.UDPTimeout != other.UDPTimeout {
return false
}
if t.DisableICMPForwarding != other.DisableICMPForwarding {
return false
}
if t.FileDescriptor != other.FileDescriptor {
return false
}

View File

@@ -49,6 +49,7 @@ type TunOption struct {
ExcludePackage []string `inbound:"exclude-package,omitempty"`
EndpointIndependentNat bool `inbound:"endpoint-independent-nat,omitempty"`
UDPTimeout int64 `inbound:"udp-timeout,omitempty"`
DisableICMPForwarding bool `inbound:"disable-icmp-forwarding,omitempty"`
FileDescriptor int `inbound:"file-descriptor,omitempty"`
Inet4RouteAddress []netip.Prefix `inbound:"inet4-route-address,omitempty"`
@@ -122,6 +123,7 @@ func NewTun(options *TunOption) (*Tun, error) {
ExcludePackage: options.ExcludePackage,
EndpointIndependentNat: options.EndpointIndependentNat,
UDPTimeout: options.UDPTimeout,
DisableICMPForwarding: options.DisableICMPForwarding,
FileDescriptor: options.FileDescriptor,
Inet4RouteAddress: options.Inet4RouteAddress,

View File

@@ -20,7 +20,8 @@ import (
type ListenerHandler struct {
*sing.ListenerHandler
DnsAdds []netip.AddrPort
DnsAdds []netip.AddrPort
DisableICMPForwarding bool
}
func (h *ListenerHandler) ShouldHijackDns(targetAddr netip.AddrPort) bool {

View File

@@ -17,7 +17,7 @@ import (
func (h *ListenerHandler) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) {
switch network {
case N.NetworkICMP: // our fork only send those type to PrepareConnection now
if resolver.IsFakeIP(destination.Addr) { // skip fakeip
if h.DisableICMPForwarding || resolver.IsFakeIP(destination.Addr) { // skip fakeip and if ICMP handling is disabled
log.Infoln("[ICMP] %s %s --> %s using fake ping echo", network, source, destination)
return nil, nil
}

View File

@@ -267,8 +267,9 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
}
handler := &ListenerHandler{
ListenerHandler: h,
DnsAdds: dnsAdds,
ListenerHandler: h,
DnsAdds: dnsAdds,
DisableICMPForwarding: options.DisableICMPForwarding,
}
l = &Listener{
closed: false,