19.1 前言
开发中,遇到一个跨多个网段访问设备内部局域网的问题。刚开始对这个跨网段的问题无从下手,但后面想了又想,难道不能让一个网口直接桥接到另外一个网口吗?顺着这个想法,于是就想到了IP映射,后面又深入到Linux中的netfilter机制。我们可以使用Linux中netfilter的机制将数据包源地址、目标地址进行“如假包换”,改变数据包的流向,从而实现跨网段的访问。该机制其实就是将Linux当做防火墙,局域网内部的IP为服务器IP,外网通过访问Linux,Linux作为中间组件再访问内部服务器,再将服务器的数据给到外网的客户端,从而避免服务器直接与外网相连带来的安全隐患。
如上图示,Linux Device跟PC机是在同一网段,我们要PC机直接访问server,但是server和PC机是在不同网段的,因此不能直接访问。解决这种访问的方法有两个:
第一:将PC的网关配成设备的IP=192.168.36.28,然后开启Linux Device的网络转发功能:(echo 1 > /proc/sys/net/ipv4/ip_forward),让Linux Device作为PC与server之间的网关,这样便PC就可以直接访问server了。(注:此方式只支持一个两个网段不同设备之间的访问,如果中间经过了很多路由,此方法失效。另外此方法需要更改PC的IP比较麻烦)。
第二:使用Linux的netfilter机制,利用Linux进行IP映射。(该方式克服了跨越多网段访问的问题,另外无需更改PC端的IP网关也能实现跨网段访问)。
19.2 IP映射过程简介
如果开启了IP映射功能,那么其数据的转发流程将如下示:
第一:当PC发起到服务器的连接请求时,数据包从192.168.36.59发出,到达linux主机192.168.36.28,经过Linux防火墙时将数据包重新构造,把数据包的目的地址由192.168.36.28改为192.168.168.168。
第二:经过第一步处理的数据包进入192.168.168.100,数据包从192.168.168.100发向192.168.168.168时,将数据包的源地址192.168.36.59改为192.168.168.100。
第三:server接收到请求数据包之后响应,响应数据包从192.168.168.168发送到192.168.168.100,在接收到src为192.168.168.168的数据包时,将其目的地址192.168.168.100改为192.168.36.59.
第四:数据包第三步处理后流向192.168.36.28,当数据包流出192.168.36.28时,将其源地址192.168.168.168改为192.168.36.28。
经过上述四个步骤,Linux Device相当于一个透明设备,只是作为中间桥梁。
19.3 Iptables移植
第一步:从网上下载iptables源码、Linux2.6以上Linux3.1以下 kernel源码。
第二步:配置内核支持netfilter,相关自行网上查阅。
第三步:编译iptables,编译时一定要加上--enable-static --disable-shared,否则运行命令时会出现一些问题。
./configure --host=arm-linux --prefix=/home/veryarm/iptables/install --enable-static --disable-shared --with-ksource=/home/veryarm/board/kernel
备注:Linux内核3.10版本以上源码存在头文件包含问题,因此我选择了Linux内核3.0版本跟iptables一起编译。
附:编译参考博客:https://blog.csdn.net/zhang_danf/article/details/50461350
19.4 Linux netfilter简介
对于网络数据包转发,IP映射其涉及的是计算机网络知识。Linux内核包含几个模块,其中一大模块就是网络相关部分,里面涉及很多的网络协议栈,其中包含现在要讲述的Linux 防火墙。
当主机收到一个数据包后,数据包先在内核空间中处理,若发现目的地址是自身,则传到用户空间中交给对应的应用程序处理,若发现目的不是自身,则会将包丢弃或进行转发。而iptables实现防火墙功能的原理是:在数据包经过Linux内核的过程中有五处关键地方(PREROUTING、INPUT、OUTPUT、FORWARD、POSTROUTING)时,数据包会经过由iptables在用户空间在这5处设置规则关卡,对经过的数据包进行处理,规则一般的定义为“如果数据包头符合这样的条件,就这样处理数据包”。
由图可知,当一个数据包进入计算机时,首先进入POSTROUTING链,然后内核根据路由表决定数据包的方向。若数据包的目的地址是本机,则将数据包送往INPUT链进行规则检查,当数据包进入INPUT链后,系统的任何进程都会收到它,本机上运行的程序可以发送该数据包,这些数据包会经过OUTPUT链,再POSTROUTING链发出;若数据包的目的地址不是本机,则检查内核是否允许转发,若允许,则将数据包送FORWARD链进行规则检查,若不允许,则丢弃该数据包。若是防火墙主机本地进程产生并准备发出的包,则数据包被送往OUTPUT链进行规则检查。
附:具体学习iptables相关网站链接:http://www.zsythink.net/archives/1199
19.5 iptables介绍
首先,iptables是用户层可直接修改内核网络协议栈配置的命令。iptables中定义有表,分别表示提供的功能,有filter表(实现包过滤)、nat表(实现网络地址转换)、mangle表(实现包修改)、raw表(实现数据跟踪),这些表具有一定的优先级:raw-->mangle-->nat-->filter。还定义了链,5个链(PREROUTING、INPUT、OUTPUT、FORWARD、POSTROUTING)其实就是每个链都会有自己的规则,那把这些规则挂起来的变成一条规则链,这就是链的由来。
filter表: 负责过滤功能,防火墙;内核模块:iptables_filter
nat表: network address translation,网络地址转换功能;内核模块:iptable_nat
mangle表: 拆解报文,做出修改,并重新封装 的功能;iptable_mangle
raw表: 关闭nat表上启用的连接追踪机制;iptable_raw
PREROUTING 的规则可以存在于:raw表,mangle表,nat表。
INPUT 的规则可以存在于:mangle表,filter表,(centos7中还有nat表,centos6中没有)。
FORWARD 的规则可以存在于:mangle表,filter表。
OUTPUT 的规则可以存在于:raw表mangle表,nat表,filter表。
POSTROUTING 的规则可以存在于:mangle表,nat表。
Iptables匹配规则之后的动作参数。
DNAT: 目标地址转换
ACCEPT: 允许数据包通过
DROP: 丢弃数据包,不做任何回复
EWJECT: 拒绝数据包通过
SNAT: 源地址转换、解决内网用户同一个公网地址上网问题。
MASQUERADE: 是SNAT特殊模式,用于动态的、临时的ip上
iptables -t filter -A INPUT -s 192.168.36.28 -j DROP |
-t 指定要操作的表,后接表名 |
-A 后面添加规则到哪个链,后接chains |
-s 指明匹配条件的“源地址”,后接IP地址 |
-j 表示条件满足时所对应的动作,后接上述动作 |
-L 表示list |
#!/bin/sh
SOURCE_CLIENT_IP_ADDR="192.168.36.59"
ETH_OUTER_IP_ADDR="192.168.12.60"
TARGET_SERVER_IP_ADDR="192.168.168.168"
ETH_INTER_IP_ADDR="192.168.168.100"
help()
{
echo "[inform] visit through multi-networks script";
echo "1:your system must support netfilter";
echo "2:your system have two ethx at least";
echo "3:you must have ipptables tools";
echo "4:ifconfig eth0:1 xxx for telnet";
echo ">>after you finish operation please shutdown eth:1<<";
}
# message
help;
echo ">>>> config start!";
# clear nat tables first(it's selectable)
iptables -t nat -F;
# Start Network Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
sleep 2;
iptables -t nat -I PREROUTING -d $ETH_OUTER_IP_ADDR -i eth0 -j DNAT --to-destination $TARGET_SERVER_IP_ADDR
iptables -t nat -I POSTROUTING -d $TARGET_SERVER_IP_ADDR -o eth1 -j SNAT --to-source $ETH_INTER_IP_ADDR
iptables -t nat -I PREROUTING -d $ETH_INTER_IP_ADDR -i eth1 -j DNAT --to-destination $SOURCE_CLIENT_IP_ADDR
iptables -t nat -I POSTROUTING -s $TARGET_SERVER_IP_ADDR -o eth0 -j SNAT --to-source $ETH_OUTER_IP_ADDR
echo ">>>> config finished!";