我有两台设置为使用Ip-Security的机器和机器A(让我们称之为A和B)有一个套接字,它绑定到本地机器上的特定UDP端口,并经常轮询它以查看是否收到任何东西。
当我禁用Ip-security时,两台机器之间的数据运行良好,我发送和接收数据包正常。但是当启用Ip-Security时,数据包不会到达机器B发送的机器A上的那个套接字。
我在两台机器上都做tcpdump
,我可以看到从机器B发出并在机器A上接收的(加密)数据包。但之后,数据包进入内核,在某处在解密数据包或在某个其他阶段,数据包被丢弃。
我希望能够在数据包通过内核时跟踪数据包并查看它被丢弃的位置。我可以为此目的使用一些/proc
吗?我能想到的另一种方法是在整个内核中插入调试语句并重新编译它,然后再次尝试发送数据包并进行调试。
感谢和抱歉这条长信息,但这是必要的。
答案 0 :(得分:12)
是的,正如丹所说,SystemTap很有用。但我最喜欢的是ftrace。
供参考:
Path of UDP packet in linux kernel
因此,为了跟踪网络流量,请将以下内容放在bash shell中并以root身份运行:
mkdir /debug
mount -t debugfs nodev /debug
mount -t debugfs nodev /sys/kernel/debug
echo '*' >/debug/tracing/set_ftrace_filter
echo function_graph >/debug/tracing/current_tracer
echo 1 >/debug/tracing/tracing_on
sleep 20
echo 0 >/debug/tracing/tracing_on
cat /debug/tracing/trace > /tmp/tracing.out$$
接收入口路径等等:
5) | tcp_recvmsg() {
5) | lock_sock_nested() {
5) 0.042 us | _cond_resched();
5) | _raw_spin_lock_bh() {
5) 0.040 us | local_bh_disable();
5) 0.414 us | }
5) 0.040 us | _raw_spin_unlock();
5) 0.040 us | local_bh_enable();
5) 1.814 us | }
5) | skb_copy_datagram_iovec() {
5) 0.042 us | _cond_resched();
5) 0.588 us | }
5) 0.042 us | tcp_rcv_space_adjust();
5) | __kfree_skb() {
5) | skb_release_all() {
5) | skb_release_head_state() {
5) 0.044 us | sock_rfree();
5) 0.670 us | }
5) | skb_release_data() {
5) | put_page() {
5) 0.049 us | put_compound_page();
5) 0.449 us | }
和此:
Netlink处理:
6) | rtnetlink_rcv() {
6) | mutex_lock() {
6) 0.090 us | _cond_resched();
6) 1.455 us | }
6) | netlink_rcv_skb() {
6) | rtnetlink_rcv_msg() {
6) 0.150 us | mutex_unlock();
6) | __netlink_dump_start() {
6) | netlink_lookup() {
6) 0.091 us | _raw_read_lock();
6) 0.100 us | netlink_compare();
6) 1.791 us | }
6) | mutex_lock() {
6) 0.095 us | _cond_resched();
6) 0.913 us | }
6) 0.100 us | try_module_get();
6) 0.090 us | mutex_unlock();
这也是入口:
3) | tcp_v4_rcv() {
3) | sk_filter() {
3) | security_sock_rcv_skb() {
3) 0.076 us | cap_socket_sock_rcv_skb();
3) 0.867 us | }
3) 1.630 us | }
3) 0.076 us | _raw_spin_lock();
3) 0.477 us | tcp_prequeue();
3) | tcp_v4_do_rcv() {
3) 0.088 us | tcp_md5_do_lookup();
3) 0.109 us | tcp_parse_md5sig_option();
3) 0.072 us | ipv4_dst_check();
3) | tcp_rcv_established() {
3) 0.076 us | tcp_parse_aligned_timestamp.part.34();
3) | tcp_queue_rcv() {
3) | tcp_try_coalesce.part.41() {
3) 0.835 us | skb_try_coalesce();
3) 1.722 us | }
3) 2.637 us | }
这是出口(从系统调用“sendmsg()”开始):
5) | SyS_sendmsg() {
5) | __sys_sendmsg() {
5) | sockfd_lookup_light() {
5) 0.080 us | fget_light();
5) 0.502 us | }
5) | ___sys_sendmsg() {
5) 0.117 us | copy_msghdr_from_user();
5) 0.101 us | verify_iovec();
5) | sock_sendmsg() {
5) | security_socket_sendmsg() {
5) | apparmor_socket_sendmsg() {
5) 0.092 us | aa_revalidate_sk();
5) 0.580 us | }
5) 1.044 us | }
5) | unix_stream_sendmsg() {
5) 0.113 us | wait_for_unix_gc();
5) | security_socket_getpeersec_dgram() {
5) 0.044 us | apparmor_socket_getpeersec_dgram();
5) 0.479 us | }
5) | sock_alloc_send_pskb() {
5) | __alloc_skb() {
5) | kmem_cache_alloc_node() {
5) 0.042 us | _cond_resched();
5) 0.648 us | }
5) | __kmalloc_reserve.isra.27() {
5) | __kmalloc_node_track_caller() {
5) 0.074 us | kmalloc_slab();
5) 0.040 us | _cond_resched();
5) 0.504 us | __slab_alloc();
5) 1.878 us | }
5) 2.276 us | }
5) 0.175 us | ksize();
5) 4.217 us | }
希望你喜欢....
答案 1 :(得分:11)
请参阅名为SystemTap的项目。它允许您插入用户友好的脚本挂钩到任何内核代码,而无需重新编译内核。例如:
probe function("ip_rcv").call {
printf("%d: ->ip_rcv()\n", gettimeofday_ms())
}
它将为网络层中的每个接收数据包发出内核打印。当然,您需要从更深入的网络堆栈中读取要遵循的源。
SystemTap非常强大,并且已经记录了可以插入的各种钩子。