我正在用我的一个玩具数据包嗅探器拦截数据包,它只是将所有流量从设备上拉下来TUN
。我在我的 Mac 上通过以下方式设置了到 TUN 的默认路由:
sudo route -n add default 10.1.0.10
10.1.0.10
设备的 IP 在哪里utun5
。虽然我可以看到数据包通过我的程序,但我只想打印它们然后将它们转发到路由器。例如,如果我要curl google.com
或ping yahoo.com
我会看到数据包,但客户端仍会像往常一样获得预期的响应。
我觉得在 Linux 上,通过 IP 转发、NAT 以及通过 iproute2 实现这一点并不太难iptables
。在 Mac 上,我就是搞不清楚这应该如何工作。任何帮助或阅读都非常感谢。
从编码方面来看,我使用 Go 和water
库来简化 tun 设备的创建。
这是一个基本的实现:
package main
import (
"log"
"net"
"github.com/songgao/water"
"golang.org/x/net/ipv4"
)
func main() {
ifce, err := water.New(water.Config{
DeviceType: water.TUN,
})
if err != nil {
log.Fatal(err)
}
log.Printf("Interface Name: %s\n", ifce.Name())
packet := make([]byte, 2000)
// Replace "en0" with your internet-facing network interface name
internetInterface, err := net.InterfaceByName("en0")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenPacket("ip4:4", "0.0.0.0") // Listen for IPv4 packets
if err != nil {
log.Fatal(err)
}
defer conn.Close()
rawConn, err := ipv4.NewRawConn(conn)
if err != nil {
log.Fatal(err)
}
for {
n, err := ifce.Read(packet)
if err != nil {
log.Fatal(err)
}
header, err := ipv4.ParseHeader(packet[:n])
if err != nil {
log.Printf("Error parsing IPv4 header: %v", err)
continue
}
cm := &ipv4.ControlMessage{
IfIndex: internetInterface.Index,
}
err = rawConn.WriteTo(header, packet[header.Len:n], cm)
if err != nil {
log.Printf("Error writing packet to raw socket: %v", err)
}
}
}