特别是在golang中,有像net.ListenIP
和net.ListenTCP
这样的接口。
我想知道,如果进程 p1 ListenIP(192.168.1.1)
并处理 p2 ListenTCP(192.168.1.1:80)
,所有发送到 192.168.1.1(无论是 TCP 还是 UDP(的数据包都会被 p1 拦截,而 p2 永远不会接受 TCP 连接?
这是net.ListenIP()
的源代码:
// ListenIP listens for incoming IP packets addressed to the local
// address laddr. The returned connection's ReadFrom and WriteTo
// methods can be used to receive and send IP packets with per-packet
// addressing.
func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
net, proto, err := parseNetwork(netProto)
if err != nil {
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
}
switch net {
case "ip", "ip4", "ip6":
default:
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(netProto)}
}
fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", noCancel)
if err != nil {
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
}
return newIPConn(fd), nil
}
它创建一个原始套接字,在 Linux 上,一个IPPROTO_RAW
套接字只发送。TCP 和 UDP 数据包永远不会传递到原始套接字,它们始终由内核协议栈处理。ICMP 数据包的副本将传递到匹配的原始套接字。发往未由内核子系统处理的协议的所有其他数据包将传递到原始套接字。
您可能希望改用 TUN 设备。这实际上是拦截所有 IP 流量的唯一方法。
您可以使用像 https://github.com/songgao/water 这样的库。