netlink 的跟踪

  以前分析了netlink的原理,可以知道:内核和用户态相互消息传递,最好的方法就是使用 netlink,比较可以双向传递消息,不像 proc sys 只能单向;

但是netlink有个缺点就是使用tcpdump抓不到!!

  目前为了解决他,采取了以前dpdk抓包的方法,直接copy&&mirror到虚拟接口上即可!(主要是内核太老了!!)这是本人之前的一个改动,需要修改内核代码;

目前稍微新内核有个nlmon模块, 其原理和本人修改类似;都是copy&&mirror

insmod nlmon.ko
ip link add netdbg type nlmon
ip link set dev netdbg  up
root@COMPILE:~# ifconfig netdbg
netdbg    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          UP RUNNING NOARP  MTU:3776  Metric:1
          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:3588 (3.5 KB)  TX bytes:0 (0.0 B)

 

kernel--->user:

 netlink消息从内核态传递给用户态时:在发送之前会检查是否有netlink tap 设备,如果有且符合条件,则copy 一份到netdbg tap接口上

  |netlink_sendskb
  |---->netlink_deliver_tap
  |---->---->__netlink_deliver_tap
  |---->---->---->netlink_filter_tap(skb)  
  |---->---->---->__netlink_deliver_tap_skb(skb, tmp->dev);
static void __netlink_deliver_tap(struct sk_buff *skb)
{
    int ret;
    struct netlink_tap *tmp;

    if (!netlink_filter_tap(skb))
        return;

    list_for_each_entry_rcu(tmp, &netlink_tap_all, list) {
        ret = __netlink_deliver_tap_skb(skb, tmp->dev);
        if (unlikely(ret))
            break;
    }
}
static bool netlink_filter_tap(const struct sk_buff *skb)
{
    struct sock *sk = skb->sk;

    /* We take the more conservative approach and
     * whitelist socket protocols that may pass.
     */
    switch (sk->sk_protocol) {
    case NETLINK_ROUTE:
    case NETLINK_USERSOCK:
    case NETLINK_SOCK_DIAG:
    case NETLINK_NFLOG:
    case NETLINK_XFRM:
    case NETLINK_FIB_LOOKUP:
    case NETLINK_NETFILTER:
    case NETLINK_GENERIC:
        return true;
    }

    return false;
}

可以看到 只有ROUTE USERSOCK  SOCK_DIAG XFRM NETFILTER 等类型的netlink消息才会被传递给netlink tap 接口!!也就是这些类似的消息才能被tcpdump 抓到

 

执行:strace ip link add netlinkdee  type ipvlan  mode l3

结果如下:

execve("/sbin/ip", ["ip", "link", "add", "netlinkdede", "type", "ipvlan", "mode", "l2"], [/* 23 vars */]) = 0
socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE) = 3
setsockopt(3, SOL_SOCKET, SO_SNDBUF, [32768], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [1048576], 4) = 0
bind(3, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, pid=25920, groups=00000000}, [12]) = 0
sendto(3, " \0\0\0\20\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 32, 0, NULL, 0) = 32
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"4\0\0\0\2\0\0\0\0\0\0\0@e\0\0\355\377\377\377 \0\0\0\20\0\5\0\0\0\0\0"..., 16384}], msg_controllen=0, msg_flags=0}, 0) = 52
access("/proc/net", R_OK)               = 0
access("/proc/net/unix", R_OK)          = 0
socket(PF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 4
ioctl(4, SIOCGIFINDEX, {ifr_name="netlinkdede"}) = -1 ENODEV (No such device)
close(4)                                = 0
sendmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"L\0\0\0\20\0\5\6\360\3\270b\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 76}], msg_controllen=0, msg_flags=0}, 0) = 76
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"`\0\0\0\2\0\0\0\360\3\270b@e\0\0\352\377\377\377L\0\0\0\20\0\5\6\360\3\270b"..., 32768}], msg_controllen=0, msg_flags=0}, 0) = 96
write(2, "RTNETLINK answers: Invalid argum"..., 36RTNETLINK answers: Invalid argument

 

 这是对netdbg 接口抓包接口

 

posted @ 2022-06-25 17:41  codestacklinuxer  阅读(89)  评论(0)    收藏  举报