计算机网络通信的本质就是IP
数据包的转发,而实现数据包转发的基础就是位于网络中各节点上的路由表(RouteTable)
,即使节点不具备数据包转发的功能,以其自身(Localhost)
作为收发终端的的数据包传递也要通过其上路由表实现,下图是对网络节点数据包收发机制的抽象框图,通常充当网络节点的设备会具备不只一个网络接口,接口可以是物理的也可以是虚拟的,接口必须要配置上IP
地址才能实现数据包的收发,接口上的IP
地址可以根据实现需要配置同网段或不同网段,抑或二者混合,而在数据交换领域相同网段的接口拓扑层级相同因此可以被视为同一接口,所以在此接口区分的依据为其上的IP
地址为不同网段。
数据包通过广播进入节点某个接口的缓冲区随后由内核即协议栈接收,检查数据包的下一跳地址如果是本机接口则发送给用户空间中的应用程序,如果不是本身接口则意味着需要进行数据包的转发,如果节点开启IP_FORWARD
功能则根据路由表将数据包的目标地址替换为能到下一跳地址网络的网关地址随后通过对应的接口发送出去;应用程序输出的数据包也依据路由表确定目标地址后由对应接口广播出去。由此可见网络通信的核心就是路由表,其与协议栈皆位为内核层级,而iptables
程序则拓展了内核功能,给使用者提供了接口可以自定义规则来实现特定的数据包收发,iptables
规则对应逻辑上的五个链条,由下图所示分别是PREROUTING
,POSTROUTING
,FORWARD
,INPUT
和OUTPUT
。
由上分析可知我们平时使用的PC
其实已经具备了路由器的除了IP
转发之外的所有底层功能,而这一点在Linux
系统上体现的更加明显,众所周知Linux/Unix
系统的网络功能非常强大,只要在配置有多网络接口的系统上开启默认关闭的IP
转发功能就可以简单的将一台Linux
服务器配置为Router
。而如果服务器连接的网段中有192.168
类似的小网IP
,则仅仅开启转发功能和配置路由表也无法实现大网和小网间通信,或者说能实现小网到大网的传递,但无法实现大网到小网的链路,这是因此默认网络节点中不会给小网网段如192.168
配置路由,因此大网发送的目标地址为小网的数据包无法实现路由,而计算机网络中的大部分通信需要数据包的双向互通,比如基于TCP
协议的通信如果没有双向互通连三次握手都无法实现,为了解决该问题就需要用到Iptables
的NAT
技术来实现网络地址转换。
Instance
实际生产网络中有服务器通过VLAN
在一块物理网卡上配置两个不同网段的IP
地址。
其路由表配置也符合网内做路由转发的要求,因此只要开启IP
转发的功能即可实现路由。
系统中通过命令cat /proc/sys/net/ipv4/ip_forward
查看转发功能开闭情况,1即开启,0为关闭。可以直接执行命令echo 1/0 > /proc/sys/net/ipv4/ip_forward
临时开闭该功能,也可以在系统文件/etc/sysctl.conf
中设置参数net.ipv4.ip_forward=1/0
实现开闭设置,然后通过sysctl -p
生效配置。
转发配置完成后最能说明问题的现象是大网网段内默认网关设置为上述服务器大网IP
的设备可以ping
通小网网段内的设备IP
,为了实现小网设备通过该服务器路由到更远端网段的数据包能在路由回来,就要通过NAT
技术做SNAT(Source Network Address Translation)
源地址转换,即将源地址为小网IP
数据包的源地址替换为服务器的大网出口地址,这样数据包接收节点就可以索引该大网IP
作为目标地址实现数据包的回传路由,对应的也有DNAT
即目标地址转换,因实现替换的地址类型不同因而SNAT
要在POSTROUTING
链路执行,DNAT
要在PREROUTING
链路执行,在实际中实现小网与大网的通信应用的都是SNAT
,但二者在本质上又是不可或缺的,SNAT
应用在发送端即POSTROUTING
链路,那么在接收端即PREROUTING
链路也必须有相应的DNAT
做地址逆变换,只不过该DNAT
是根据内核维护的NAT
表隐性触发。
服务器上配置SNAT
的iptables
命令很简单如下:
iptables -F -t nat
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -L -t nat
配置完成后即可实现小网对外部大网的全部访问,当然小网对除了服务器大网同网段的设备之外对远端的大网网络仍然是不可见的。
附:Linux
下路由配置命令
ifconfig eth0 192.168.1.2 netmask 255.255.255.0
1. route add -net xxx netmask xxx dev eth0 (auto-generated, On-link Network)
2. route add default gw xxx (configured by manual, Remote Network)
route add -net xxx netmask xxx gw xxx
route add -host xxx gw xxx
3. route add -net yyy netmask yyy dev pppoe0 (configured by manual, Remote sub-network)