nxtrace / NTrace-core

NextTrace, an open source visual route tracking CLI tool
https://www.nxtrace.org
GNU General Public License v3.0
5.7k stars 335 forks source link

macOS15 tun模式下使用--dev 未正常工作 #260

Open tsosunchia opened 3 weeks ago

tsosunchia commented 3 weeks ago

如果是tun形式,推荐在代理软件开启时设置--dev参数指定网卡接口

Darwin 24.0.0 arm64 / macOS 15.0 NextTrace 1.3.4 2024-09-10T03:19:06Z brew --dev 参数不起作用,即使指定 --dev en0 追踪依然从 TUN 发出:

image

如果使用-s指定源ip呢,因为我手头没有最新预览版的机器所以没法排查

使用 --source 参数以后第一跳依旧是 TUN:

image

Originally posted by @SukkaW in https://github.com/nxtrace/NTrace-core/issues/251#issuecomment-2352245976

sjlleo commented 2 weeks ago

路过\~ 以下内容仅供参考...

by dev 不行的话,感觉可能得先看一下 net.InterfaceByName(*srcDev) 获得到的 dev dev.Addrs() 的返回值是什么 我记得当时写的时候,无论是 by dev 还是 by sourceIP 实际上最后应该都是以 bind laddr 送给 ListenICMP

说不准可以在 ListenICMP 中对 ifaces, err := net.Interfaces() 这一步先额外排除所有的 tun interface 试试看 - - 如果还不行的话可以 netstat -rn 看看路由表,使用 route 临时把去测试 ip 的网关指向 en0 试试看(逃

tsosunchia commented 2 weeks ago

~路过~ 以下内容仅供参考...~

by dev 不行的话,感觉可能得先看一下 net.InterfaceByName(*srcDev) 获得到的 dev dev.Addrs() 的返回值是什么 我记得当时写的时候,无论是 by dev 还是 by sourceIP 实际上最后应该都是以 bind laddr 送给 ListenICMP

说不准可以在 ListenICMP 中对 ifaces, err := net.Interfaces() 这一步先额外排除所有的 tun interface 试试看 - - 如果还不行的话可以 netstat -rn 看看路由表,使用 route 临时把去测试 ip 的网关指向 en0 试试看(逃

等待有 Surge 的大佬尝试一下了,

提到的代码: https://github.com/nxtrace/NTrace-core/blob/main/trace/internal/icmp_darwin.go#L45

SukkaW commented 2 weeks ago
int idx = if_nametoindex(bsd_name);
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))

Try this?

The example code is provided by the creator of the Surge.

tsosunchia commented 2 weeks ago
int idx = if_nametoindex(bsd_name);
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))

Try this?

The example code is provided by the creator of the Surge.

感觉是修改这俩地方:

tsosunchia commented 2 weeks ago

int idx = if_nametoindex(bsd_name);

但是这个是C的

SukkaW commented 2 weeks ago
  • NTrace-core/trace/internal/icmp_darwin.go

It seems that nexttrace is iterating net.Interfaces() manually. Why not use net.InterfaceByName provided by Go directly?

missuo commented 1 week ago

等待有 Surge 的大佬尝试一下了,

func main() {
    iface, _ := net.Interfaces()
    // fmt.Println(iface)
    iface_tun, _ := net.InterfaceByName("utun17")
    fmt.Println(iface_tun)
    fmt.Println(iface_tun.Addrs())
}

Output:

&{36 4000 utun17  up|pointtopoint|multicast|running}

[198.18.0.1/8] <nil>

utun17 is the interface when Surge is running.

tsosunchia commented 1 week ago
int idx = if_nametoindex(bsd_name);
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))

Try this?

The example code is provided by the creator of the Surge.

我大概看了一下,目前的代码实现方式与Surge creator提到的是一样的

tsosunchia commented 1 week ago

https://github.com/nxtrace/NTrace-V1/commit/b0c0f8d3ce7ed9e7f588f7748b2a79cba1e513b5

此commit大概解决此issue了,这几天先进行测试