1. 网络数据包在内核的数据传输过程
- 基本流程
1.当一个数据包进入网卡,先进入PREROUTING链,内核根据数据包的IP判断是否需要转发
2.如果是到本机的,就会到INPUT链,然后本机的所有进程可收到这个包。
3.如果不是到本机的,且内核允许转发,就会到达FORWARD链,然后到POSRTROUTING链输出
4.本机发出一个数据,会通过OUTPUT链,再到POSRTROUTING链输出
- iptables的规则表和链(四表五链)
1. filter表: filter表用于过滤,内建INPUT(目的地是本地的包)、FORWARD(不是本地产生的并且目的地不是本地)和OUTPUT(本地生成的包)等三个链
2. nat表:网络地址转换,内建PREROUTING(在包刚刚到达防火墙时改变它的目的地址)、INPUT、OUTPUT和POSTROUTING(要离开防火墙之前改变其源地址)等链
3.mangle表:对报文进行修改,内建PREROUTING、INPUT、FORWARD、OUTPUT和POSTROUTING等链
4.raw表:决定数据包是否被状态跟踪机制处理,内建PREROUTING和OUTPUT两个链
2. 进入本机的包会经历如下的回调:
3. Linux网络 - iptables-netfilter - SDN 网络指南 - 开发文档 - 文江博客
netfilter是Linux内核的包过滤框架,它提供了一系列的钩子(Hook)供其他模块控制包的流动。这些钩子包括
NF_IP_PRE_ROUTING
:刚刚通过数据链路层解包进入网络层的数据包通过此钩子,它在路由之前处理NF_IP_LOCAL_IN
:经过路由查找后,送往本机(目的地址在本地)的包会通过此钩子NF_IP_FORWARD
:不是本地产生的并且目的地不是本地的包(即转发的包)会通过此钩子NF_IP_LOCAL_OUT
:所有本地生成的发往其他机器的包会通过该钩子NF_IP_POST_ROUTING
:在包就要离开本机之前会通过该钩子,它在路由之后处理
3. iptables的预备知识:对设备上网的流程有个基本理解
假设有如下的网络拓扑:
路由器----交换机---LAN内的电脑1(192.168.1.1),电脑2(192.168.1.2)
- 路由器(上面有两张网卡:公网+内网)
公网网卡:pppoe拨号,成功了路由器就拥有了上网的能力。
内网网卡:一般接到交换机上,交换机接上内部主机的网线(两台电脑+路由器的内网,共属一个LAN)
- 路由器从公网进来一个网络报文,内网需要转发到具体的主机。
这个时候,路由器发一个ARP广播(数据链路层的协议):谁的ip地址是192.168.1.1,请告诉我你的MAC地址。然后收到回复,就会写入ARP表(arp -a可以看到)
- 路由器插上网线:(路由器跑着DHCP Server的程序,电脑上要跑DHCP client的程序)
电脑1发布 DHCP广播--->路由器收到---->给电脑1回复ip地址--->电脑1拿到一个ip地址
没有ip地址前,只能用MAC层的报文。
- 静态ip: 电脑把一个ip地址写死。
- 电脑1访问百度(假设ip地址为 10.10.10.10)这个网站
电脑1发出 src ip = 192.168.1.1 des ip = 10.10.10.10这样的报文--->
- 先在路由表(route -n可见)去匹配最优的Destination,并通过Gateway发出去
1.1 默认网关:Destination 0.0.0.0 Gateway 192.168.1.3 Genmask 0.0.0.0(任何ip地址都可以和这个地址匹配上)
1.2 每一个主机发出去的报文都会与默认路由匹配上。因为电脑1的路由表没有办法可以直接发到百度的路由,所以只能走默认路由,发给GateWay(路由器)。
这个时候src mac是电脑1的mac地址,Dst mac就是路由器的MAC地址
路由器收到电脑1的包之后:发现mac地址是路由器(必须)
ip地址不是路由器。于是会查看路由器自己的路由表。
于是通过路由器的默认网关(路由器的公网网口)把报文发出去。 (dst mac就变为了运行商的网络节点, src ip 需要变为路由器公网的ip地址,这个操作叫SNAT:源地址映射)
百度收到的报文: src ip = wan口的ip地址 dst ip: 10.10.10.10
路由器收到百度回的报文:src ip :10.10.10.10 , dst ip : wan口的ip地址。路由器会做还原,dst ip转为电脑1的ip地址,这个操作叫做DNAT:目的地址转换。
百度回的报文是发给路由器的wan口的,需要通过端口映射才可以把报文给到电脑1
电脑1收到src ip为百度的响应报文
- 需要使用路由功能,需要打开路由转发
/proc/sys/net/ipv4/ip_forward 需要设置为1
4. iptables的简单例子
- iptables对目标IP地址改写
原始请求地址: 192.168.2.101: 55 希望转发给 192.168.2.100:53 (通过telnet验证)
iptables -t nat -nvL //查看现有的iptables规则
iptables -t nat -A OUTPUT -p tcp -d 192.168.2.101 --dport 55 -j DNAT --to-destination 192.168.2.100:53 // 实现把192.168.2.101的55端口的报文,转发到192.168.2.100:53
- 丢掉发到114.114.114.114的udp报文
iptables -t filter -A OUTPUT -p udp 114.114.114.114 -j DROP