为啥使用SNAT设置了数据包的源地址之后,使用抓包工具没抓到源地址

虚机中的地址:192.168.0.110

PC机的地址是: 192.168.0.1

设置PC机的sudo iptables -t nat -I POSTROUTING -s 192.168.0.1 -d 192.168.0.110 -j SNAT --to-source 192.168.1.1

然后从虚机中: ping 192.168.0.1,发现PC返回的应答包中根本就没有换成我期望的192.168.1.1,大跌眼镜,

但是从宿主机: ping 192.168.0.110 ,此时抓的包中就有192.168.0.1的源地址就换成了192.168.1.1了

课件ICMP的回复包根本就不走路由,而是直接返回,课件iCMP协议的脆弱;

我过激地这样处理:sudo iptables -t nat -I POSTROUTING -s 192.168.0.1  -d 192.168.0.110 -j SNAT --to-source 192.168.1.2

然后从宿主机中:ping 192.168.0.110 , 此时抓的包中有192.168.0.1的源地址确实是换成了192.168.1.2了,返回的数据包的目的地址也是192.168.1.2

此时这个数据包应该被丢弃才对啊, 为啥没有丢弃呢?应该收不到这个包才对呢

此时 tap0网卡应该广播谁有192.168.0.2才对呀,为啥没有呢?为啥这里icmp会收到这个数据包呢?我从虚拟机上ping 192.168.1.2,此时并ping不通,所以说并不是有什么NAT的规则,如果有的话,那么我从虚拟机上的ping应该也能通过的呀,所以这里肯定是做了什么标记的,到底是啥标记呢?

http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=1921013&page=1

接收到数据包的函数是:__netif_receive_skb函数,发现发送给gw的数据包,gw还是收到了数据包,但是不知道是在哪里做的转换?

看下抓包的信息就知道咯:

From Skb:
 S 192.168.0.110   D: 192.168.1.2
ip_rcv From Skb:
 S 192.168.0.110   D: 192.168.1.2
ip_rcv_finish From Skb:
 S 192.168.0.110   D: 192.168.0.1
发现啊,在ip_rcv的时候目的地址还是192.168.1.2,但是经过了NF_HOOK(NFPROTO_IPV, NF_INET_PRE_ROUTEINT....)的时候,目的IP地址就变成了192.168.0.1,所以转变就是在netfilter框架中!

但是我们明明是在postrouting中增加的规则啊,为啥在prerouting中体现出来了,代码之后了无秘密哈!

nf_iterator函数中遍历所有的规则

规则是如何增加的呢?用strace看iptables -t

注册proto反转的函数:nf_ct_l4proto_register,相应的反转协议:tcp/udp/icmp都是在这里注册:

332     rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
333                l4proto);

nf_hook_thresh函数中上来就是:struct list_head *hook_list = &net->nf.hooks[pf][hook];

hook=PREROUTING pf=nat

所有的钩子都定义在函数 iptable_ipv4_in函数中,nf_nat_ipv4_in,在这个函数中处理处理PRETABLE函数呢,

nf_ct_get得到, skb->nfctinfo中有这个否是:IP_CT_RELATED_REPLY,

真正在起过滤作用的是:iptable_nat_do_chain。在过滤的情况下是不应该有这个函数的。

真正的使用bpf写的那些那些规则都是在哪里处理的呢?xt_table->private->entries,这些过滤是真的通过iptables设置的,而不是为反转准备的,反转的地方是在函数

发现了,是在函数tcp_manip_pkt中反转了!

所以在postrouting中把源地址和端口号转化了之后,会在prerouting中设置相应的反转项,所以postrouting和prerouting是互为兄弟关系的,那么output和input也是互为兄弟关系啦?啥时候设置output?

 67 static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
 68     /* Before packet filtering, change destination */
 69     {
 70         .hook       = iptable_nat_ipv4_in,
 71         .pf     = NFPROTO_IPV4,
 72         .hooknum    = NF_INET_PRE_ROUTING,
 73         .priority   = NF_IP_PRI_NAT_DST,
 74     },
 75     /* After packet filtering, change source */
 76     {
 77         .hook       = iptable_nat_ipv4_out,
 78         .pf     = NFPROTO_IPV4,
 79         .hooknum    = NF_INET_POST_ROUTING,
 80         .priority   = NF_IP_PRI_NAT_SRC,
 81     },
 82     /* Before packet filtering, change destination */
 83     {
 84         .hook       = iptable_nat_ipv4_local_fn,
 85         .pf     = NFPROTO_IPV4,
 86         .hooknum    = NF_INET_LOCAL_OUT,
 87         .priority   = NF_IP_PRI_NAT_DST,
 88     },
 89     /* After packet filtering, change source */
 90     {
 91         .hook       = iptable_nat_ipv4_fn,
 92         .pf     = NFPROTO_IPV4,
 93         .hooknum    = NF_INET_LOCAL_IN,
 94         .priority   = NF_IP_PRI_NAT_SRC,
 95     },
 96 };
 97 

 output是数据包已经产生了,在进入路由之前,我如果改变了目的地址,这个时候要是

192.168.0.110的数据包我要是把目的地址换成了192.168.1.110,这个时候shubjushubju

sudo iptables -t nat -I OUTPUT -d 192.168.1.110 -j DNAT 192.168.0.110

DNAT       all  --  anywhere             192.168.1.110        to:192.168.0.110

output规则链也不是啊,在做output规则链之前,源地址已经确定好了,

恩 这里就又有一个问题了,数据包的源地址是什么时候确定的?其实在output规则链之前就已经确定好了,  

奇怪啊,为啥发送的数据包是192.168.1.1

说明数据包在进入路由之前,就设置好了源地址,看下数据包的发送过程

数据包接收是ip_rcv,数据包的发送是ip

posted @ 2018-05-21 11:53  honpey  阅读(1117)  评论(0编辑  收藏  举报