在UNIX

时间:2015-04-22 14:23:06

标签: linux unix packet-capture icmp

IPtables等防火墙可以选择通过ICMP消息(例如端口关闭)通知发送方(在阻止数据包之后)。此消息包含被拒绝数据包的标头(RFC要求),因此技术上可以将其与发送它的应用程序相关联。

有没有简单的方法在unix环境中以编程方式捕获与我的应用程序相关的ICMP消息?如果应用程序可以告诉用户目标可能位于防火墙后面,那将会很方便。它不必是POSIX指定的,但它不应仅限于一个平台(尽管我想知道它仍然如此:)。

实现这一目标的一种方法是使用原始套接字,另一种方法是使用pcap,但这两种方法都非常具有侵入性,我必须浏览所有ICMP消息并过滤属于其他应用程序的消息。

1 个答案:

答案 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故障模式。这将是非常具有侵略性的。