Kubernetes,  Operation,  Other

使用 pwru 追踪 linux kernel 网络包

1. 编译构建

git clone git@github.com:cilium/pwru.git
cd pwru

# 原生编译
make

# 或构建 docker 镜像
docker build -t pwru .
#docker build - < Dockerfile

2. 应用示例

sudo iptables -t filter -I OUTPUT 1 -m tcp --proto tcp --dst 1.1.1.1/32 -j DROP

curl 1.1.1.1

docker run --rm --privileged pwru --filter-dst-ip=1.1.1.1 --filter-dst-port=80 --filter-proto=tcp --output-tuple

[2022-01-26 05:14:27]                SKB          PROCESS                     FUNC        TIMESTAMP

[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]             ip_local_out  161391938235954 192.168.110.130:33248->1.1.1.1:80(tcp) # 因为是从本地发出数据到公网
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]           __ip_local_out  161391938266384 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]             nf_hook_slow  161391938281657 192.168.110.130:33248->1.1.1.1:80(tcp) # 调用IPtables中的Chains判别数据包
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]                kfree_skb  161391938297492 192.168.110.130:33248->1.1.1.1:80(tcp) # 回收skb 拒绝 consume_skb 表示 skb是正常释放。 kfree_skb 表示因为某种错误报文被丢弃。
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]   skb_release_head_state  161391938311827 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]                tcp_wfree  161391938345431 192.168.110.130:33248->1.1.1.1:80(tcp) # 针对TCP回收
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]         skb_release_data  161391938359294 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:35] 0xffff89fb5768f0e0           [curl]             kfree_skbmem  161391938374122 192.168.110.130:33248->1.1.1.1:80(tcp)

# 重试
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]              __skb_clone  161392965281794 192.168.110.130:33248->1.1.1.1:80(tcp) # 单单克隆下sk_buff结构体,对sk_buff结构的数据区、分片结构体skb_shared_info、分片结构体数据区等结果进行共享。
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]        __copy_skb_header  161392965336975 192.168.110.130:33248->1.1.1.1:80(tcp) # 复用之前的构造好的数据结构
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]             ip_local_out  161392965394428 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]           __ip_local_out  161392965423078 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]             nf_hook_slow  161392965464020 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]                kfree_skb  161392965480966 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]   skb_release_head_state  161392965535446 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]                tcp_wfree  161392965577236 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]         skb_release_data  161392965590979 192.168.110.130:33248->1.1.1.1:80(tcp)
[2022-01-26 05:14:36] 0xffff89fb5768f0e0          [EMT-1]             kfree_skbmem  161392965605683 192.168.110.130:33248->1.1.1.1:80(tcp)

# 清理现场(删 OUTPUT 链第一条规则)
iptables -D OUTPUT 1

3. iptables 相关指令

iptables是linux系统自带的防火墙,功能强大,学习起来需要一段时间,下面是一些习iptables的时候的记录。如果iptables不熟悉的话可以用apf,是一款基于iptables的防火墙,挺好用的。请参考:linux apf 防火墙 安装 配置

  • 3.1 添加 filter 表
# 开放21端口(出口一般都是开放的 iptables -P OUTPUT ACCEPT,所以出口就没必要在去开放端口了)
iptables -A INPUT -p tcp -m tcp --dport 21 -j ACCEPT
  • 3.2 添加 nat 表
# 将源地址是 192.168.10.0/24 的数据包进行地址伪装
# -A默认是插入到尾部的,可以-I来插入到指定位置
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE

iptables -I INPUT 3 -p tcp -m tcp --dport 20 -j ACCEPT

iptables -L -n --line-number
Chain INPUT (policy DROP)  
num  target     prot opt source               destination
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0  
2    DROP       icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 8
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:20                # -I 指定位置插的
4    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
5    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80
6    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
7    DROP       all  --  0.0.0.0/0            0.0.0.0/0           state INVALID,NEW  
8    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:21                # -A 默认插到最后

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
  • 3.3 查看 filter 表
# --line-number可以显示规则序号,在删除的时候比较方便
# 如果不加-t的话,默认就是filter表,查看,添加,删除都是的
iptables -L -n --line-number | grep 21
5    ACCEPT     tcp  --  192.168.1.0/24       0.0.0.0/0           tcp dpt:21
  • 3.4 查看 nat 表
iptables -t nat -vnL POSTROUTING --line-number

Chain POSTROUTING (policy ACCEPT 38 packets, 2297 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 MASQUERADE  all  --  *      *       192.168.10.0/24      0.0.0.0/0
  • 3.5 修改规则
# 将规则3改成DROP
iptables -R INPUT 3 -j DROP
  • 3.6 删除规则
# 删除 INPUT 的第3条规则
iptables -D INPUT 3

# 删除 nat 表中 POSTROUTING 的第一条规则
iptables -t nat -D POSTROUTING 1

# 清空 filter 表 INPUT 所有规则
iptables -F INPUT

# 清空所有规则
iptables -F

# 清空 nat 表 POSTROUTING 所有规则
iptables -t nat -F POSTROUTING
  • 3.6 设置默认规则
# 设置filter表INPUT默认规则是 DROP
iptables -P INPUT DROP

如上增删改后都需使用 /etc/init.d/iptables save 导出外部保存起来,上面只是一些最基本的操作,要想灵活运用,还要一定时间的实际操作。

4. 原理资料

核心搞明白这张图:
核心搞明白这张图

5 FAQ

TODO

留言

您的电子邮箱地址不会被公开。