【原创】Linux实现路由转发功能开发总结

【原创】Linux实现路由转发功能开发总结

关键词:linux防火墙,iptables

Author: chad
Mail: [email protected]

本文可以自由转载,但转载请务必注明出处以及本声明信息。

一、准备知识

需要用到的知识有:
(1)路由工作原理,route命令.
(2)linux网络管理命令,ifconfig,iptables
(3)linux防火墙及内核配置,NAT(Network Address Translation网络地址翻译)功能实现。

二、linux移植、配置步骤。

linux内核配置,实现NAT(Network Address Translation网络地址翻译)功能。

1. 什么是NAT

在传统的标准的TCP/IP通信过程中,所有的路由器仅仅是充当一个中间人的角色,也就是通常所说的存储转发,路由器并不会对转发的数据包进行修改,更为确切的说,除了将源MAC地址换成自己的MAC地址以外,路由器不会对转发的数据包做任何修改。NAT(Network Address Translation网络地址翻译)恰恰是出于某种特殊需要而对数据包的源ip地址、目的ip地址、源端口、目的端口进行改写的操作。

2. 为什么要进行NAT

我们来看看再什么情况下我们需要做NAT。

假设有一家ISP提供园区Internet接入服务,为了方便管理,该ISP分配给园区用户的IP地址都是伪IP,但是部分用户要求建立自己的WWW服务器对外发布信息,这时候我们就可以通过NAT来提供这种服务了。我们可以在防火墙的外部网卡上绑定多个合法IP地址,然后通过NAT技术使发给其中某一个IP地址的包转发至内部某一用户的WWW服务器上,然后再将该内部WWW服务器响应包伪装成该合法IP发出的包。

再比如使用拨号上网的网吧,因为只有一个合法的IP地址,必须采用某种手段让其他机器也可以上网,通常是采用代理服务器的方式,但是代理服务器,尤其是应用层代理服务器,只能支持有限的协议,如果过了一段时间后又有新的服务出来,则只能等待代理服务器支持该新应用的升级版本。如果采用NAT来解决这个问题,因为是在应用层以下进行处理,NAT不但可以获得很高的访问速度,而且可以无缝的支持任何新的服务或应用。

还有一个方面的应用就是重定向,也就是当接收到一个包后,不是转发这个包,而是将其重定向到系统上的某一个应用程序。最常见的应用就是和squid配合使用成为透明代理,在对http流量进行缓存的同时,可以提供对Internet的无缝访问。

3. NAT的类型

在linux2.4的NAT-HOWTO中,作者从原理的角度将NAT分成了两种类型,即源NAT(SNAT)和目的NAT(DNAT),顾名思义,所谓SNAT就是改变转发数据包的源地址,所谓DNAT就是改变转发数据包的目的地址。

4. 原理

netfilter是Linux 核心中一个通用架构,它提供了一系列的”表”(tables),每个表由若干”链”(chains)组成,而每条链中可以有一条或数条规则(rule)组成。并且系统缺省的表是”filter”。但是在使用NAT的时候,我们所使用的表不再是”filter”,而是”nat”表,所以我们必须使用”-t nat”选项来显式地指明这一点。因为系统缺省的表是”filter”,所以在使用filter功能时,我们没有必要显式的指明”-t filter”。

同filter表一样,nat表也有三条缺省的”链”(chains),这三条链也是规则的容器,它们分别是:

PREROUTING:可以在这里定义进行目的NAT的规则,因为路由器进行路由时只检查数据包的目的ip地址,所以为了使数据包得以正确路由,我们必须在路由之前就进行目的NAT;

POSTROUTING:可以在这里定义进行源NAT的规则,系统在决定了数据包的路由以后在执行该链中的规则。

OUTPUT:定义对本地产生的数据包的目的NAT规则。

5. 操作语法

iptables的使用见《iptables 命令详解》,这里只说使用集中器进行路由测试时使用的几条命令:

现在用arm linux做了一个路由器,出口是用pppd拨号GPRS模块(MC52I),pppd拨号具体见《ppp拨号上网总结》,目前已经能够ping通外网了。
我用以下命令设置了路由转发功能:

echo 1 > /proc/sys/net/ipv4/ip_forward   #启动内核转发功能,详见linux内核源码目录下Documentation/networking/ip-sysctl.txt。
iptables -F
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.0.0/24  -o ppp0 -j MASQUERADE

接下来先看下效果图,这样比较有动力。
【原创】Linux实现路由转发功能开发总结_第1张图片

在pc端将本机IP设置为192.168.0.*号段,网关设置为192.168.0.1(因为集中器ip已经设置为192.168.0.1)。关闭杀毒软件(因为我发现360会对集中器与电脑之间的数据进行拦截!),然后将集中器与pc通过网线直连,在pc端ping 192.168.0.1 ,可能会出错,我测试的时候发现这个时候都会出错,这个时候在集中器控制台中执行ping 192.168.0.202(pc的ip),如果网线没问题,就可以ping通,然后这时再回到pc端执行ping 192.168.0.1 ,这个时候应该可以正常ping通了,ping 通后再在pc端ping百度的主机 ping 119.75.218.77 如果可以ping通,恭喜你嵌入式linux路由已经建立成功了!!!

打开网页试试,我测试时使用的是GPRS模块+3G卡,打开网络失败,然后执行telnet bbs.newsmth.net 依然失败,显示无法打开23端口,这个应该跟防火墙设置有关,暂且不管。再打开qq试试,登录成功(如果超时,多试几次)!!!

6. 内核配置方法

网络上很多过时的方法,大都是同一篇文章的转载,内容如下:
首先重新编译内核编译,选择支持netfilter的所有选项。在宿主机上进入Linux内核目录,配置所需的内核模块:

cd /usr/src/linux
make menuconfig

选中如下内核选项:

General setup --->
[*] Sysctl support (在ROMFS文件系统中/proc/sys/net/ipv4/出现ip_forward,linux2.6.30版本中该项位于文件系统目录下)
Networking options --->
[*] Network packet filtering (replaces ipchains)
IP: Netfilter Configuration --->(全部选择即可)

按照上述方法配置完内核后,使用是执行iptables -t nat 命令时会出错,如下所示:

iptables v1.4.2: can’t initialize iptables table `filter’: Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.

这是因为该方法配置不全,但是内核缺少依赖项所致,正确完整的配置应该如下所示:

Networking —->
  Networking options —->
  [*] Network packet filtering (replaces ipchains)  —>
    Core Netfilter Configuration  —>
      <*> Netfilter Xtables support (required for ip_tables)
    IP: Netfilter Configuration —>
      <*> Connection tracking (required for masq/NAT)
      <*> IP tables support (required for filtering/masq/NAT)
      <*>   IP range match support
      <*>   Packet filtering
      <*>     REJECT target support
      <*>   Full NAT

安装上面的配置配置好内核,基本保证没有问题。

7. 交叉编译iptables-1.4.12

下载iptables-1.4.12 源码包,编译方法如下:

(1)将iptables-1.4.12解压到/home目录下,然后在解压后的iptables-1.4.12目录下创建安装文件夹,如mkdir /home/iptables-1.4.12.1/install_bin,首先进行配置,生成makefile文件,具体配置方法可以执行./configure –help查看。

我的配着如下:

#./configure --prefix=/home/iptables-1.4.12.1/install_bin --exec-prefix=/home/iptables-1.4.12.1/install_bin --host=arm --with-kernel=/home/linux-2.6.30 --disable-shared CC=arm-linux-gcc

查看Makefile 文件,在Makefile中做如下修改:

CC=arm-linux-gcc

然后进行编译:

make
make install

安装文件在/home/iptables-1.4.12.1/install_bin,如上所示:
这里写图片描述

最后,将bin、lib、sbin 目录下的文件全部复制到文件系统对应的目录,生成后连同内核烧写到开发板进行测试,如下所示:
【原创】Linux实现路由转发功能开发总结_第2张图片
没有报错,说明移植成功!

三、联合测试

ppp拨号部分请参考我的另一篇博文《ppp拨号上网总结》,现在假设你应经ppp拨号成功,开发板能够正常ping通外网,同时,参考上文“5. 操作语法”部分的说明,编写如下脚本:

/etc/init.d/rcS部分内容如下:
这里写图片描述
/home/iptables.sh脚本内容如下所示:
【原创】Linux实现路由转发功能开发总结_第3张图片
重启开发板,等待拨号成功后,在pc端测试吧!

四、iptables说明

假设你还不了解iptables,可看这里的信息。下文来自网络。

iptables是基于内核的防火墙,功能非常强大,iptables的前身叫ipfirewall (内核1.x时代),这是一个作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。iptables的功能是由两部分组成的:netfilter和iptables。netfilter部分在内核空间(参见术语表)运行,它是一组保存着一系列规则的表,内核利用这些规则控制网络分组过滤。iptables在用户空间运行,它用来设置、维护和显示netfilter保存的规则。

iptables内置了filter,nat和mangle三张表:
filter负责过滤数据包,包括的规则链有,input,output和forward;

nat则涉及到网络地址转换,包括的规则链有,prerouting,postrouting和output;

mangle表则主要应用在修改数据包内容上,用来做流量整形的,默认的规则链有:INPUT,OUTPUT,NAT,POSTROUTING,PREROUTING;

input匹配目的IP是本机的数据包,forward匹配流经本机的数据包,prerouting用来修改目的地址用来做DNAT,postrouting用来修改源地址用来做SNAT。

工作原理如下:

图片来自:http://www.tuicool.com/articles/Vr2aaqv ,这篇博文不错,大家可以看看。

iptables 指令详解:

iptables [-t table] command [match] [-j target/jump]
[-t table] 指定规则表
-t 参数用来,内建的规则表有三个,分别是:nat、mangle 和 filter,当未指定规则表时,则一律视为是 filter。规则表的功能如下:

nat:此规则表拥有 PREROUTING 和 POSTROUTING 两个规则链,主要功能为进行一对一、一对多、多对多等网址转换工作(SNAT、DNAT),这个规则表除了作网址转换外,请不要做其它用途。

mangle:此规则表拥有 PREROUTING、FORWARD 和 POSTROUTING 三个规则链。除了进行网址转换工作会改写封包外,在某些特殊应用可能也必须去改写封包(TTL、TOS)或者是设定 MARK(将封包作记号,以进行后续的过滤),这时就必须将这些工作定义在 mangle 规则表中,由于使用率不高,我们不打算在这里讨论 mangle 的用法。

filter: 这个规则表是默认规则表,拥有 INPUT、FORWARD 和 OUTPUT 三个规则链,这个规则表顾名思义是用来进行封包过滤的处理动作(例如:DROP、 LOG、 ACCEPT 或 REJECT),我们会将基本规则都建立在此规则表中。

command 常用命令列表:
命令 -A, –append
范例

iptables -A INPUT …

说明 新增规则到某个规则链中,该规则将会成为规则链中的最后一条规则。

命令 -D, –delete
范例

iptables -D INPUT –dport 80 -j DROP
iptables -D INPUT 1

说明 从某个规则链中删除一条规则,可以输入完整规则,或直接指定规则编号加以删除。

命令 -R, –replace
范例

iptables -R INPUT 1 -s 192.168.0.1 -j DROP

说明 取代现行规则,规则被取代后并不会改变顺序。

命令 -I, –insert
范例

iptables -I INPUT 1 –dport 80 -j ACCEPT

说明 插入一条规则,原本该位置上的规则将会往后移动一个顺位。

命令 -L, –list
范例

iptables -L INPUT

说明 列出某规则链中的所有规则。
范例

iptables -t nat -L

说明 列出nat表所有链中的所有规则。

命令 -F, –flush
范例

iptables -F INPUT

说明 删除filter表中INPUT链的所有规则。

命令 -Z, –zero
范例

iptables -Z INPUT

说明 将封包计数器归零。封包计数器是用来计算同一封包出现次数,是过滤阻断式攻击不可或缺的工具。

命令 -N, –new-chain
范例

iptables -N allowed

说明 定义新的规则链。

命令 -X, –delete-chain
范例

iptables -X allowed

说明 删除某个规则链。

命令 -P, –policy
范例

iptables -P INPUT DROP

说明 定义过滤政策。 也就是未符合过滤条件之封包, 默认的处理方式。

命令 -E, –rename-chain
范例

iptables -E allowed disallowed

说明 修改某 自定义规则链的名称。

[match] 常用封包匹配参数
参数 -p, –protocol
范例

iptables -A INPUT -p tcp

说明 匹配通讯协议类型是否相符,可以使用 ! 运算符进行反向匹配,例如:

-p !tcp

意思是指除 tcp 以外的其它类型,如udp、icmp …等。
如果要匹配所有类型,则可以使用 all 关键词,例如:

-p all

参数 -s, –src, –source
范例

iptables -A INPUT -s 192.168.1.1

说明 用来匹配封包的来源 IP,可以匹配单机或网络,匹配网络时请用数字来表示 子网掩码,例如:

-s 192.168.0.0/24

匹配 IP 时可以使用 ! 运算符进行反向匹配,例如:

-s !192.168.0.0/24。

参数 -d, –dst, –destination
范例

iptables -A INPUT -d 192.168.1.1

说明 用来匹配封包的目的地 IP,设定方式同上。

参数 -i, –in-interface
范例

iptables -A INPUT -i eth0

说明 用来匹配封包是从哪块网卡进入,可以使用通配字符 + 来做大范围匹配,例如:
-i eth+
表示所有的 ethernet 网卡
也可以使用 ! 运算符进行反向匹配,例如:
-i !eth0
参数 -o, –out-interface
范例

iptables -A FORWARD -o eth0

说明 用来匹配封包要从哪 块网卡送出,设定方式同上。

参数 –sport, –source-port
范例

iptables -A INPUT -p tcp –sport 22

说明 用来匹配封包的源端口,可以匹配单一端口,或是一个范围,例如:
–sport 22:80
表示从 22 到 80 端口之间都算是符合条件,如果要匹配不连续的多个端口,则必须使用 –multiport 参数,详见后文。匹配端口号时,可以使用 ! 运算符进行反向匹配。

参数 –dport, –destination-port
范例

iptables -A INPUT -p tcp –dport 22

说明 用来匹配封包的目的地端口号,设定方式同上

参数 –tcp-flags
范例

iptables -p tcp –tcp-flags SYN,FIN,ACK SYN

说明匹配 TCP 封包的状态标志,参数分为两个部分,第一个部分列举出想匹配的标志,第二部分则列举前述标志中哪些有被设置,未被列举的标志必须是空的。TCP 状态标志包括:SYN(同步)、ACK(应答)、FIN(结束)、RST(重设)、URG(紧急) 、PSH(强迫推送)等均可使用于参数中,除此之外还可以使用关键词 ALL 和 NONE 进行匹配。匹配标志时,可以使用 ! 运算符行反向匹配。

参数 –syn
范例

iptables -p tcp –syn

说明 用来表示TCP通信协议中,SYN位被打开,而ACK与FIN位关闭的分组,即TCP的初始连接,与 iptables -p tcp –tcp-flags SYN,FIN,ACK SYN 的作用完全相同,如果使用 !运算符,可用来 匹配非要求连接封包。

参数 -m multiport –source-port
范例

iptables -A INPUT -p tcp -m multiport –source-port 22,53,80,110

说明用来匹配不连续的多个源端口,一次最多可以匹配 15 个端口,可以使用 ! 运算符进行反向匹配。

参数 -m multiport –destination-port
范例

iptables -A INPUT -p tcp -m multiport –destination-port 22,53,80,110

说明用来 匹配不连续的多个目的地端口号,设定方式同上

参数 -m multiport –port
范例

iptables -A INPUT -p tcp -m multiport –port 22,53,80,110

说明 这个参数比较特殊,用来匹配源端口和目的端口号相同的封包,设定方式同上。注意:在本范例中,如果来源端口号为 80目的地端口号为 110,这种封包并不算符合条件。

参数 –icmp-type
范例

iptables -A INPUT -p icmp –icmp-type 8

说明用来匹配 ICMP 的类型编号,可以使用代码或数字编号来进行 匹配。请打 iptables -p icmp –help 来查看有哪些代码可用。

参数 -m limit –limit
范例

iptables -A INPUT -m limit –limit 3/hour

说明 用来匹配某段时间内封包的平均流量,上面的例子是用来 匹配:每小时平均流量是否超过一次 3 个封包。除了每小时平均次外,也可以每秒钟、每分钟或每天平均一次,默认值为每小时平均一次,参数如后: /second、 /minute、/day。 除了进行封包数量的匹配外,设定这个参数也会在条件达成时,暂停封包的匹配动作,以避免因骇客使用洪水攻击法,导致服务被阻断。

参数 –limit-burst
范例

iptables -A INPUT -m limit –limit-burst 5

说明 用来匹配瞬间大量封包的数量,上面的例子是用来匹配一次同时涌入的封包是否超过 5 个(这是默认值),超过此上限的封包将被直接丢弃。使用效果同上。
参数 -m mac –mac-source
范例

iptables -A INPUT -m mac –mac-source 00:00:00:00:00:01

说明 用来匹配封包来源网络接口的硬件地址,这个参数不能用在 OUTPUT 和 POSTROUTING 规则链上,这是因为封包要送到网卡后,才能由网卡驱动程序透过 ARP 通讯协议查出目的地的 MAC 地址,所以 iptables 在进行封包匹配时,并不知道封包会送到哪个网络接口去。

参数 –mark
范例

iptables -t mangle -A INPUT -m mark –mark 1

说明 用来匹配封包是否被表示某个号码,当封包被 匹配成功时,我们可以透过 MARK 处理动作,将该封包标示一个号码,号码最大不可以超过 4294967296。

参数 -m owner –uid-owner
范例

iptables -A OUTPUT -m owner –uid-owner 500

说明 用来匹配来自本机的封包,是否为某特定使用者所产生的,这样可以避免服务器使用 root 或其它身分将敏感数据传送出,可以降低系统被骇的损失。可惜这个功能无法 匹配出来自其它主机的封包。

参数 -m owner –gid-owner
范例 iptables -A OUTPUT -m owner –gid-owner 0
说明 用来匹配来自本机的封包,是否为某特定使用者群组所产生的,使用时机同上。

参数 -m owner –pid-owner
范例

iptables -A OUTPUT -m owner –pid-owner 78

说明 用来匹配来自本机的封包,是否为某特定进程所产生的,使用时机同上。

参数 -m owner –sid-owner
范例

iptables -A OUTPUT -m owner –sid-owner 100

说明 用来匹配来自本机的封包,是否为某特定 连接(Session ID)的响应封包,使用时机同上。

参数 -m state –state
范例

iptables -A INPUT -m state –state RELATED,ESTABLISHED

说明 用来匹配连接状态, 连接状态共有四种:INVALID、ESTABLISHED、NEW 和 RELATED。

INVALID 表示该封包的连接编号(Session ID)无法辨识或编号不正确。

ESTABLISHED 表示该封包属于某个已经建立的连接。

NEW 表示该封包想要起始一个连接(重设连接或将连接重导向)。

RELATED 表示该封包是属于某个已经建立的连接,所建立的新连接。例如:FTP-DATA 连接必定是源自某个 FTP 连接。

[-j target/jump] 常用的处理动作:
-j 参数用来指定要进行的处理动作,常用的处理动作包括:ACCEPT、REJECT、DROP、REDIRECT、MASQUERADE、LOG、DNAT、SNAT、MIRROR、QUEUE、RETURN、MARK,分别说明如下:

ACCEPT: 将封包放行,进行完此处理动作后,将不再匹配其它规则,直接跳往下一个规则链(natostrouting)。

REJECT: 拦阻该封包,并传送封包通知对方,可以传送的封包有几个选择:ICMP port-unreachable、ICMP echo-reply 或是tcp-reset(这个封包会要求对方关闭连接),进行完此处理动作后,将不再匹配其它规则,直接中断过滤程序。 范例如下:

iptables -A FORWARD -p TCP –dport 22 -j REJECT –reject-with tcp-reset

DROP: 丢弃封包不予处理,进行完此处理动作后,将不再匹配其它规则,直接中断过滤程序。

REDIRECT: 将封包重新导向到另一个端口(PNAT),进行完此处理动作后,将会继续匹配其它规则。这个功能可以用来实现透明代理或用来保护 web 服务器。例如:

iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-ports 8080

MASQUERADE: 改写封包来源 IP 为防火墙 NIC IP,可以指定 port 对应的范围,进行完此处理动作后,直接跳往下一个规则 链(manglepostrouting)。这个功能与SNAT 略有不同,当进行 IP 伪装时,不需指定要伪装成哪个 IP,IP会从网卡直接读取,当使用拨 号接连时,IP通常是由ISP公司的DHCP 服务器指派的,这个时候 MASQUERADE 特别有用。范例如下:

iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE –to-ports 1024-31000

LOG: 将封包相关讯息纪录在 /var/log 中,详细位置请查阅 /etc/syslog.conf 配置文件,进行完此处理动作后,将会继续匹配其规则。例如:

iptables -A INPUT -p tcp -j LOG –log-prefix “INPUT packets”

SNAT: 改写封包来源 IP 为某特定 IP 或 IP 范围,可以指定 port 对应的范围,进行完此处理动作后,将直接跳往下一个规则(mangleostrouting)。范例如下:

iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT –to-source?194.236.50.155-194.236.50.160:1024-32000 

DNAT: 改写封包目的地 IP 为某特定 IP 或 IP 范围,可以指定 port 对应的范围,进行完此处理动作后,将会直接跳往下一个规则链(filter:input 或 filter:forward)。范例如下:

iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 –dport 80 -j DNAT –to-destination 192.168.1.1-192.168.1.10:80-100

MIRROR: 镜射封包,也就是将来源 IP 与目的地 IP 对调后,将封包送回,进行完此处理动作后,将会中断过滤程序。

QUEUE:中断过滤程序,将封包放入队列,交给其它程序处理。通过自行开发的处理程序,可以进行其它应用,例如:计算连接费用等。

RETURN:结束在目前规则链中的过滤程序,返回主规则链继续过滤,如果把自定义规则链看成是一个子程序,那么这个动作,就相当于提前结束子程序并返回到主程序中。

MARK: 将封包标上某个代号,以便提供作为后续过滤的条件判断依据,进行完此处理动作后,将会继续匹配其它规则。范例如下:

iptables -t mangle -A PREROUTING -p tcp –dport 22 -j MARK –set-mark 2

你可能感兴趣的:(linux,嵌入式)