为啥使用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