[Linux用户空间编程-5]:用IPTable实现NAT功能

Posted 文火冰糖的硅基工坊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Linux用户空间编程-5]:用IPTable实现NAT功能相关的知识,希望对你有一定的参考价值。


作者主页(​​文火冰糖的硅基工坊​​​):​​文火冰糖(王文兵)的博客_文火冰糖的硅基工坊


目录

​前言:​

​第1章 NAT功能概述​

​1.1 什么是NAT​

​1.2 为什么要进行NAT​

​1.3 NAT的类型​

​第2章 IP Table概述​

​2.1 IP Table概述​

​2.2. Iptable的链和表结构​

​2.3 五个链(chain)​

​2.4  四个表(table)​

​2.5 详细的数据包流程​

​2.5 IP Table操作命令处理流程​

​第3章 IP Table对Nat的支持命令​

​3.1 IP Table对NAT的支持概述​

​3.1 对规则的操作​

​3.3 通过命令指定具体的源地址和目的地址​

​3.4 通过命令指定网络接口​

​3.5 指定协议及端口​

​3.6 内核开关与编译​

​第4章 实际操作案例解析​

​4.1 源NAT(SNAT)​

​4.2 目的SNAT(DNAT)​

​第5章 综合例子​

​5.1 案例1:使用拨号局域网上网​

​5.2 案例2:ip映射​

​附录:NAT、DNAT和MASQUERADE进一步比较​


前言:

5G DUT实现了私网IP的接入,internet服务,DUT就需要实现NAT功能,完成私网IP地址到公网IP地址的换。

第1章 NAT功能概述

1.1 什么是NAT

在传统的标准的TCP/IP通信过程中,所有的路由器仅仅是充当一个中间人的角色,也就是通常所说的存储发,路由器并不会对转发的数据包进行修改, 更为确切的说,除了将源MAC地址换成自己的MAC地址以外,路由器不会对转发的数据包做任何修改。

NAT(Network Address Translation网络地址翻译)恰恰是出于某种特殊需要而对数据包的源ip地址、目的ip地址、源端口、目的端口进行改写的操作。

1.2 为什么要进行NAT

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

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

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

因为只在应用层以下进行处理,不但可以获得很高的访问速度,而且可以无缝的支持任何新的服务或应用。

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

另一种情况就是4G/5G的DUT,需要在私网和公网之间进行换。

1.3 NAT的类型

源NAT(SNAT)和目的NAT(DNAT),顾名思义,所谓SNAT就是改变发数据包的源地址,所谓DNAT就是改变转发数据包的目的地址。

DNAT​:Destination Network Address Translation 目标网络地址换。 DNAT是一种改变数据包目的ip地址的技术,经常和SNAT联用,以使多台服务器能共享一个ip地址连入Internet,并且继续服务。通过对同一个ip地址分配不同的端口,来决定数据的流向。

SNAT​:Source Network Address Translation源网络地址换。这是一种改变数据包源ip地址的技术, 经常用来使多台计算机分享一个Internet地址。这只在IPv4中使用,因为IPv4的地址已快用完了,IPv6将解 决这个问题。

第2章 IP Table概述

2.1 IP Table概述

Lnux系统中,防火墙(Firewall),网址换(NAT),数据包(package)记录,流量统计,这些功能是由Netfilter子系统所提供的,而iptables是控制Netfilter的工具.

iptables将许多复杂的规则组织成成容易控制的方式,以便管理员可以进行分组测试,或关闭、启动某组规则。

iptable能够为Unix、Linux和BSD个人工作站创建一个防火墙,也可以为一个子网创建防火墙以保护其它的系统平台。iptable只读取数据包头,不会给信息流增加负担,也无需进行验证。


2.2. Iptable的链和表结构

[Linux用户空间编程-5]:用IPTable实现NAT功能_IP

2.3 五个链(chain)

[Linux用户空间编程-5]:用IPTable实现NAT功能_运维_02

[Linux用户空间编程-5]:用IPTable实现NAT功能_linux_03

PREROUTING​: 在数据包进入防火墙之后、路由判断之前对数据包进行修改

INPUT​: 在数据包被路由到本地之后,但在用户空间程序看到它之前对数据包进行修改

OUTPUT​: 用户空间程序处理数据包后,由本地发出,再次被路由之前更改数据包

FORWARD​: 在最初的路由判断之后、最后一次更改包的源地址之前对数据包进行修改

POSTROUTING​: 在所有路由判断之后,对数据包进行修改

注意:​ 链 是每个数据包流需要经过的不同环节,你可以在不同的环节根据需要设置不同的过滤策略,​每个链的默认策略都是Accept

2.4  四个表(table)

Mangle表:​这个表主要用来mangle包,你可以使用mangle匹配来改变包的一些属性,比如 TOS(TYPE OF SERVICE),TTL (TIME TO LIVE),MARK(后续流量控制TC等)

Nat表​: 此表仅用于NAT,也就是换包的源或目标地址。注意,就象我们前面说过的,只有流的第一个 包会被这个链匹配,其后的包会自动被做相同的处理(DNAT,SNAT,MASQUERADE)

Filter表​:此表用来过滤数据包,我们可以在任何时候匹配包并过滤它们。 我们就是在这里根据包的内容对包做DROP或ACCEPT的. iptalbe中,要用 ​-t​ 参数指定要操作哪个表,如果没有 ​-t​ 参数,就默认对​filter表​操作.

Raw表​: 优先级最高,设置raw时一般是为了不再让iptables做数据包的链接跟踪处理,提高性能

注意:​ 表 是规则的集合组,​每个表中的规则条目是按顺序匹配的​,你可以在数据包经过的不同环节设置规则,表的处理优先级:​raw > mangle > nat > filter

2.5 详细的数据包流程

[Linux用户空间编程-5]:用IPTable实现NAT功能_NAT_04

在上图中,NAT的功能发生在三个地方:

(1)接收到来自公网网卡的数据包:在包的预处理阶段进行​目的IP地址的替换,换后进行路由由。

(2)接收到来自本地应用程序的输出数据包:在包的输出处理模块阶段进行​目的IP地址的替换。

(3)发送到公网网卡上输出的数据包:在包的​后处理阶段​,进行源IP地址换,转换成本地的公网IP地址。

2.5 IP Table操作命令处理流程

[Linux用户空间编程-5]:用IPTable实现NAT功能_NAT_05

在用户空间的IP table命令,会通过内核接口,操作内核的Ip_table规则表,并最终操作的是内核空间的Netfilter钩子函数。

第3章 IP Table对Nat的支持命令

3.1 IP Table对NAT的支持概述

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

但在使用NAT的时候,我们所使用的表不再是"filter",而是"nat"表,所以我们必须使用​"-t nat​"选项来显式地指明这一点。

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

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

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

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

3.1 对规则的操作

加入(append) 一个新规则到一个链 (-A)的最后。 

在链内某个位置插入(insert) 一个新规则(-I),通常是插在最前面。 

在链内某个位置替换(replace) 一条规则 (-R)。 

在链内某个位置删除(delete) 一条规则 (-D)。 

删除(delete) 链内第一条规则 (-D)。 

3.3 通过命令​指定具体的源地址和目的地址

通过--source/--src/-s来指定源地址(这里的/表示或者的意思,下同),通过--destination/--dst/-s来指定目的地址。可以使用以下四种方法来指定ip地址:

使用完整的域名,如“www.linuxaid.com.cn”; 

使用ip地址,如“192.168.1.1”; 

用x.x.x.x/x.x.x.x指定一个网络地址,如“192.168.1.0/255.255.255.0”; 

用x.x.x.x/x指定一个网络地址,如“192.168.1.0/24”这里的24表明了子网掩码的有效位数,这是UNIX环境中通常使用的表示方法。缺省的子网掩码数是32,也就是说指定192.168.1.1等效于192.168.1.1/32。 

3.4 通过命令指定网络接口

可以使用--in-interface/-i或--out-interface/-o来指定网络接口。

从NAT的原理可以看出,对于 PREROUTING链,需要修正目的IP地址,因此,通常情况下,我们用-i指定公网IP接口​​然后把目的IP地址换成内部的私网IP地址+端口号。

而对于POSTROUTING和OUTPUT我们只能用-o指定出去的网络接口,POSTROUTING是源IP地址,因此通常用于输出到公网前,进行源地址的替换。

3.5 指定协议及端口

可以通过--protocol/-p选项来指定协议,如果是udp和tcp协议,还可--source-port/--sport和 --destination-port/--dport来指明端口。

3.6 内核开关与编译

(1)编译

Linux内核对Nat的支持,是需要打开内核选项的。

编译内核,编译时选中以下选项:

Full NAT

 MASQUERADE target support

 REDIRECT target support

(2)加载ko

要使用NAT表时,必须首先载入相关模块:

modprobe ip_tables

modprobe ip_nat_ftp

iptable_nat 模块会在运行时自动载入。

第4章 实际操作案例解析

需要注意的时,大多数情况下,

私网到公网的源地址换是多对1.

而公网到私网的换是1对多

因此,NAT的换是基于端口的转换,NAT内部需要维护一个私网IP地址和端口号的对应关系的表。

4.1 源NAT(SNAT)

比如,更改所有来自192.168.1.0/24的数据包的源ip地址为1.2.3.4:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 1.2.3.4


这里需要注意的是,系统在路由及过虑等处理直到数据包要被送出时才进行SNAT。


有一种SNAT的特殊情况是ip欺骗,也就是所谓的Masquerading,通常建议在使用拨号上网的时候使用,或者说在合法ip地址不固定的情况下使用。比如

# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE


可以看出,这时候我们没有必要显式的指定源ip地址等信息。

4.2 目的SNAT(DNAT)

比如,更改所有来自192.168.1.0/24的数据包的目的ip地址为1.2.3.4:

iptables -t nat -A PREROUTING -s 192.168.1.0/24 -i eth1 -j DNAT --to 1.2.3.4


这里需要注意的是,系统是先进行DNAT,然后才进行路由及过虑等操作。


有一种DNAT的特殊情况是重定向,也就是所谓的Redirection,这时候就相当于将符合条件的数据包的目的ip地址改为数据包进入系统时的网 络接口的ip地址。通常是在与squid配置形成透明代理时使用,假设squid的监听端口是3128,我们可以通过以下语句来将来自 192.168.1.0/24,目的端口为80的数据包重定向到squid监听端口:

iptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.1.0/24 --dport 80 -j REDIRECT --to-port 3128

第5章 综合例子

5.1 案例1:使用拨号局域网上网

小型企业、网吧等多使用拨号网络上网,通常可能使用代理,但是考虑到成本、对协议的支持等因素,建议使用ip欺骗方式带动区域网上网。


成功升级内核后安装iptables,然后执行以下脚本:


#载入相关模块

modprobe ip_tables

modprobe ip_nat_ftp

#进行ip伪装

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

5.2 案例2:ip映射

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


我们假设以下情景:


该ISP分配给A单位www服务器的ip为:


伪ip:192.168.1.100


真实ip:202.110.123.100


该ISP分配给B单位www服务器的ip为:


伪ip:192.168.1.200


真实ip:202.110.123.200


linux防火墙的ip地址分别为:


内网接口eth1:192.168.1.1


外网接口eth0:202.110.123.1


然后我们将分配给A、B单位的真实ip绑定到防火墙的外网接口,以root权限执行以下命令:


ifconfig eth0 add 202.110.123.100 netmask 255.255.255.0

ifconfig eth0 add 202.110.123.200 netmask 255.255.255.0


成功升级内核后安装iptables,然后执行以下脚本:


#载入相关模块

modprobe ip_tables

modprobe ip_nat_ftp


首先,对防火墙接收到的目的ip为202.110.123.100和202.110.123.200的所有数据包进行目的NAT(DNAT):


iptables -A PREROUTING -i eth0 -d 202.110.123.100 -j DNAT --to 192.168.1.100

iptables -A PREROUTING -i eth0 -d 202.110.123.200 -j DNAT --to 192.168.1.200


其次,对防火墙接收到的源ip地址为192.168.1.100和192.168.1.200的数据包进行源NAT(SNAT):


iptables -A POSTROUTING -o eth0 -s 192.168.1.100 -j SNAT --to 202.110.123.100

iptables -A POSTROUTING -o eth0 -s 192.168.1.200 -j SNAT --to 202.110.123.200


这样,所有目的ip为202.110.123.100和202.110.123.200的数据包都将分别被发给192.168.1.100和 192.168.1.200;而所有来自192.168.1.100和192.168.1.200的数据包都将分别被伪装成由 202.110.123.100和202.110.123.200,从而也就实现了ip映射.

附录:NAT、DNAT和MASQUERADE进一步比较

IP Tables中可以灵活的做各种网络地址换(NAT),网络地址转换主要有两种:SNAT和DNAT。

SNAT​是source networkaddress translation的缩写,即源地址目标换。比如,多个PC机使用ADSL路由器共享上网,每个PC机都配置了内网IP。

PC机访问外部网络的时候,路由器将数据包的报头中的源地址替换成路由器的ip,当外部网络的服务器比如网站web服务器接到访问请求的时候,他的日志记录下来的是路由器的ip地址,而不是pc机的内网ip,这是因为,这个服务器收到的数据包的报头里边的“源地址”,已经被替换了,所以叫做SNAT,基于源地址的地址换。

DNAT​是destination networkaddress translation的缩写,即目标网络地址换,典型的应用是,有个web服务器放在内网配置内网ip,前端有个防火墙配置公网ip,互联网上的访问者使用公网ip来访问这个网站,当访问的时候,客户端发出一个数据包,这个数据包的报头里边,目标地址写的是防火墙的公网ip,防火墙会把这个数据包的报头改写一次,将目标地址改写成web服务器的内网ip,然后再把这个数据包发送到内网的web服务器上,这样,数据包就穿透了防火墙,并从公网ip变成了一个对内网地址的访问了,即DNAT,基于目标的网络地址转换。

MASQUERADE​,地址伪装,算是snat中的一种特例,可以实现自动化的snat。

在iptables中有着和SNAT相近的效果,但也有一些区别,但使用SNAT的时候,出口ip的地址范围可以是一个,也可以是多个,例如:

如下命令表示把所有10.8.0.0网段的数据包SNAT成192.168.5.3的ip然后发出去,

iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source192.168.5.3

如下命令表示把所有10.8.0.0网段的数据包SNAT成192.168.5.3/192.168.5.4/192.168.5.5等几个ip然后发出去

iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source192.168.5.3-192.168.5.5

这就是SNAT的使用方法,即可以NAT成一个地址,也可以NAT成多个地址,但是,对于SNAT,不管是几个地址,必须明确的指定要SNAT的ip,假如当前系统用的是ADSL动态拨号方式,那么每次拨号,出口ip192.168.5.3都会改变,而且改变的幅度很大,不一定是192.168.5.3到192.168.5.5范围内的地址,这个时候如果按照现在的方式来配置iptables就会出现问题了,因为每次拨号后,服务器地址都会变化,而iptables规则内的ip是不会随着自动变化的,每次地址变化后都必须手工修改一次iptables,把规则里边的固定ip改成新的ip,这样是非常不好用的。

MASQUERADE​:就是针对这种场景而设计的,他的作用是,从服务器的网卡上,自动获取当前ip地址来做NAT。

比如下边的命令:

iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o​ eth0 -j MASQUERADE

如此配置的话,​不用指定SNAT的目标ip了​,不管现在​eth0的出口获得了怎样的动态ip​,​MASQUERADE会自动读取eth0现在的ip地址然后做SNAT出去,这样就实现了很好的动态SNAT地址换。


作者主页(​​文火冰糖的硅基工坊​​​):​​文火冰糖(王文兵)的博客_文火冰糖的硅基工坊


以上是关于[Linux用户空间编程-5]:用IPTable实现NAT功能的主要内容,如果未能解决你的问题,请参考以下文章

Linux网络基础设定selinux/iptable/firewall

#私藏项目实操分享# 使用iptable实现: 放行telnet, ftp, web服务,放行samba服务,其他端口服务全部拒绝

#私藏项目实操分享# 使用iptable实现: 放行telnet, ftp, web服务,放行samba服务,其他端口服务全部拒绝

Linux进程5——实模式和保护模式

[Linux用户空间编程-3]:Linux定时机制的几种实现方法

linux用户空间 - 多进程编程(三)