IPtables等防火墙可以选择通过ICMP消息(例如端口关闭)通知发送方(在阻止数据包之后)。此消息包含被拒绝数据包的标头(RFC要求),因此技术上可以将其与发送它的应用程序相关联。
有没有简单的方法在unix环境中以编程方式捕获与我的应用程序相关的ICMP消息?如果应用程序可以告诉用户目标可能位于防火墙后面,那将会很方便。它不必是POSIX指定的,但它不应仅限于一个平台(尽管我想知道它仍然如此:)。
实现这一目标的一种方法是使用原始套接字,另一种方法是使用pcap,但这两种方法都非常具有侵入性,我必须浏览所有ICMP消息并过滤属于其他应用程序的消息。
答案 0 :(得分:0)
技术上可以将它与发送它的应用程序相关联
我怀疑是否有 easy 方式来做你想要的事情。内核接收ICMP消息并处理它,然后告诉程序它不成功。例如,以下是对无法访问的主机执行ping操作的结果(使用strace
在Linux上运行以检查系统调用;粗体行是接收ICMP错误的结果):
sendmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.113.198")}, msg_iov(1)=[{"\10\0mQ\f\24\0\1~u\227U\0\0\0\0\250\373\1\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64}], msg_controllen=0, msg_flags=0}, 0) = 64 setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={10, 0}}, NULL) = 0 recvmsg(3, 0x7ffffd6ecbe0, 0) = -1 EAGAIN (Resource temporarily unavailable) recvmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.113.206")}, msg_iov(1)=[{"E\0\0008\5\316\0\0\200\1\366q\300\250q\316\n\0\2\17\3\0017\335\0\0\0\0E\0T\0"..., 192}], msg_controllen=32, {cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=0x1d /* SCM_??? */, ...}, msg_flags=0}, 0) = 56 recvmsg(3, 0x7ffffd6ecbe0, 0) = -1 EHOSTUNREACH (No route to host) recvmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.113.198")}, msg_iov(1)=[{"\10\0mQ\f\24\0\1", 8}], msg_controllen=80, {cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=0x1d /* SCM_??? */, ...}, msg_flags=MSG_ERRQUEUE}, MSG_DONTWAIT|MSG_ERRQUEUE) = 8 write(1, "From 192.168.113.206 icmp_seq=1 "..., 61) = 61 write(1, "\n", 1) = 1 write(1, "--- 192.168.113.198 ping statist"..., 40) = 40 write(1, "1 packets transmitted, 0 receive"..., 73) = 73 write(1, "\n", 1) = 1
您可以运行您的应用程序并监视strace
(或者您的系统上的类似内容),但是您必须注意并解码所有各种ICMP故障模式。这将是非常具有侵略性的。