首页 > 代码库 > IPtables/NetFilter

IPtables/NetFilter

前提知识

  • 任何主机若要与非同网络中的主机通信,则必须将报文发送到默认网关;

  • 对Linux而言,IP地址是属于主机(内核中)的,不属于网卡,只要属于当前主机的IP地址间,都可直接响应,不称为转发

  • 私有地址在路由器上是不允许被路由的

 

防火墙的类型与作用的链

  • 主机防火墙:一般使用INPUT,OUTPUT链来过滤进入和发出的报文

  • 网络防火墙:一般使用PREROUTING,FORWARD,POSTROUTING链来转发经过的报文

 

命令参数 : 

iptables [-t 表] -命令 匹配   操作
说明
(1) -t 表
表选项用于指定命令应用于哪个iptables内置表。
(2)命令
命令选项用于指定iptables的执行方式,包括插入规则,删除规则和添加规则,如下表所示

                                                                         命令                                                                                                          说明

    -P  
              --policy  链名>                 定义默认策略
    -L
--list  链名>
查看iptables规则列表
    -A
--append  链名> 在规则列表的最后增加1条规则
    -I  
--insert  链名>  
在指定的位置插入1条规则
    -D --delete  链名>  
从规则列表中删除1条规则
    -R
--replace  链名>  
替换规则列表中的某条规则
    -F
--flush  链名>
删除表中所有规则
    -Z --zero  链名>
将表中数据包计数器和流量计数器归零
    -X --delete-chain  链名>
删除自定义链
    -v  
--verbose  链名> 与-L它命令一起使用显示更多更详细的信息

(3) 匹配规则

匹配选项指定数据包与规则匹配所具有的特征,包括源地址,目的地址,传输协议和端口号,如下表所示
匹配                              说明
-i     --in-interface  网络接口名>        指定数据包从哪个网络接口进入,
-o    --out-interface  网络接口名>      指定数据包从哪个网络接口输出
-p    ---proto协议类型                     指定数据包匹配的协议,如TCP、UDP和ICMP等
-s     --source  源地址或子网>           指定数据包匹配的源地址
--sport 源端口号>                           指定数据包匹配的源端口号
--dport 目的端口号>                        指定数据包匹配的目的端口号
-m  --match 匹配的模块                   指定数据包

规则所使用的过滤模块

 

不同网络间主机通信的方式

路由

对于Linux主机,设定/proc/sys/net/ipv4/ip_forward的值为1,即开启了路由功能,可以作为模拟路由器使用

wKioL1M2qJDgtWVJAAGspjiVuW0909.jpg

注:但真实的路由器还应该存在生成路由表的机制,一般是基于路由协议(如RIP2,OSPF)动态学习的,在此不作讨论

NAT

工作于网络层和传输层,也可分为静态NAT和动态NAT

  • Basic NAT:静态NAT;NAT服务器上有一个外网地址池,内网连接时直接分配一个外网IP使用,很不灵活

  • NAPT:动态NAT,Network Address Port Translation,即网络端口地址转换,也可分为SNAT和DNAT

    • SNAT:源地址转换;适用于内网主机访问互联网,原理图如下:

      wKioL1M2qQjDPBwNAAS9qCPdMFQ935.jpg

    • DNAT:目标地址转换;适用于让互联网主机访问本地内网中的某主机上的服务,原理图如下:

      wKiom1M2qVPD1SQIAAVaGmF2b-Y863.jpg

 

iptables/netfilter基于SNAT和DNAT原理实现报文转发

  • -j SNAT --to-source SIP

    • 规则添加:在POSTROUTING链上

  • -j MASQUERADE

    • 用于外网IP是ADSL拨号上网时生成的动态IP,MASQUERADE模式能自行查找能访问互联网的外网IP,并完成SNAT

  • -j DNAT --to-destination DIP[:Port]

    • 支持端口映射

    • 规则添加:在PREROUTING链上

实例:

# 将外网对172.16.100.7:22022的访问转发至内网的192.168.20.12.22
iptables -t nat -A PREROUTING -d 172.16.100.7 -p tcp --dport 22022 -j DNAT --to-destination 192.168.20.12.22

 

iptables/netfilter实战解析

需求分析

wKiom1M26zqSprGfAAMmc447Atg647.jpg

架构设计

wKioL1M26y_ASnyuAALkUgZwIyc755.jpg

配置部署

DNS Server配置

网络配置

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
IPADDR=172.16.251.178
NETMASK=255.255.0.0
GATEWAY=172.16.251.236

DNS主配置文件:/etc/named.conf

# named.conf中需修改的部分
listen-on port 53 { 127.0.0.1; 172.16.251.178;};
allow-query     { any; };
recursion no;
#zone "." IN {
#   type hint;
#   file "named.ca";
#};

DNS辅助配置文件:/etc/named.rfc1912.zones

acl inter_net {
172.16.251.0/24;
};
view inter_net {
match-clients { inter_net; };
        zone "." IN {
                type hint;
                file "named.ca";
        };
zone "jason.com" IN {
type master;
file "jason.com.inter_net";
};
};
view outer_net {
match-clients { any; };
zone "jason.com" IN {
type master;
file "jason.com.outer_net";
};
};

区域数据文件

# vi /var/named/jason.com.inter_net
$TTL 1D
jason.com. IN SOA dns.jason.com. admin.jason.com (
2014032920 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
@ NS dns
dns A 172.16.251.178
www A 172.16.251.182
# vi /var/named/jason.com.outer_net
$TTL 1D
jason.com. IN SOA dns.jason.com. admin.jason.com (
2014032920 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
@ NS dns
dns A 172.16.251.178
www A 3.3.3.1

 

 

启动named服务

chown root.named jason.com.inter_net
chown root.named jason.com.outer_net
service named restart
Web Server配置
配置一个虚拟主机,监听端口8080
在DocumentRoot目录下创建一简单的测试文件test.html,内容随意,如
“Hello Mageedu”
启动httpd服务即可

Firewall配置

网络配置

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
IPADDR=172.16.251.236
NETMASK=255.255.0.0
GATEWAY=172.16.0.1
# vi /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE="eth1"
BOOTPROTO="static"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
IPADDR=3.3.3.1
NETMASK=255.255.255.0
DNS1=3.3.3.1

注:因为3.3.3.1和3.3.3.3都是模拟的外网IP地址,故对应的网卡应处于同一信道内,且不能和内网的通信信道一致,故在用虚拟机测试时,可将对应内网IP的网卡的网络方式改为桥接,而对应外网IP的网卡的网络方式改为自定义,如vmnet2

添加iptables规则

iptables -t nat -A PREROUTING -d 3.3.3.1/32 -p udp --dport 53 -j DNAT --to-destination 172.16.251.178
iptables -t nat -A PREROUTING -d 3.3.3.1/32 -p tcp --dport 8080 -j DNAT --to-destination 172.16.251.182

Inter Client配置

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
IPADDR=172.16.251.176
NETMASK=255.255.255.0
GATEWAY=172.16.251.236
DNS1=172.16.251.178
# vi /etc/resolv.conf
nameserver 172.16.251.178

Outer Client配置

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
IPADDR=3.3.3.3
NETMASK=255.255.255.0
GATEWAY=3.3.3.1
DNS1=3.3.3.1
# vi /etc/resolv.conf
nameserver 3.3.3.1
 

DNS解析测试

wKioL1M27yeguPY3AAEmn_6VUto674.jpg

HTTP访问测试

wKiom1M273CAf5rlAAQtUHrZog8122.jpg

大功告成,哦也!

 


 

  iptables实现7层访问过滤 :

 

1、实验所需要的相关包

内核源码包:kernel-2.6.32-431.11.2.el6.src.rpm 下载地址
iptables:iptables-1.4.7-11.el6.src.rpm 下载地址

l7-protocols协议包:l7-protocols-2009-05-28.tar.gz 下载地址

   为了方便,我们把需要的包都放到/root/app下

wKiom1M-nTLzmFu3AAAYXUiLtz4591.png

三、经验分享,血淋淋的教训(2天错误总结)

1、要同步系统时间到当前日期

   同步时间后,编译内核可能还会报错:warning: Clock skew detected. Your build may be incomplete.

 此时需要执行:

find . -type f | xargs -n 5 touch
    make clean
    make

2、保证磁盘空间要足够大

3、IPv4连接追踪功能要编译成模块,而非编入内核

四、实现过程
1、获取并编译内核
1)安装内核源码包需新建一个mockbuild用户,否则会报错
2)# rpm -ivh kernel-2.6.32-431.5.1.x86_64.el6.src.rpm
   安装内核rpm包后会在/root下生成一rpmbuild目录,在/root/rpmbuild/SOURCES下就会有内核源码包和一堆config

3)进入~/rpmbuild/SOURCES目录,解压tar包

wKioL1M-nSfCdB53AACcsjvUlY8024.png

为解压后的目录创建软链接,方便以后使用

wKiom1M-nYvjAkWbAAAr7W7QZ78808.png

2、解压补丁包,拿到etfilter-layer7补丁

 wKioL1M-naTiopFZAABPl9jba0I286.png

3、进入内核源码目录,为其打上layer7补丁

wKiom1M-nfDjSAwhAACM6A35nVE569.png

4、以本地内核配置文件为模板,编译内核
[root@nmshuishui linux]# cp /boot/config-2.6.32-358.el6.x86_64 .config
[root@nmshuishui linux]# make menuconfig
(1)装载核心配置模块layer7

Networking support--->Networking options--->Network packet filtering framework(Netfilter)--->core Netfilter Configuration--->"layer7" match support

wKiom1M-nhLy9xPbAACETnoX1hE197.png

(2)开启连接追踪
Networking support--->Networking options--->Network packet filtering framework(Netfilter)--->core Netfilter Configuration--->Netfilter connection tracking support

wKiom1M-niiDSwBHAACAAJsqOJE306.png

(3)开启IPv4的NAT连接追踪功能
Networking support--->Networking options--->Network packet filtering framework(Netfilter)--->IP:Netfilter Configuration--->IPv4 connection tracking support (required for NAT)

wKiom1M-nmyBTTA8AACBfwN2bKk960.png

(4)取消模块签名认证
   redhat的签名认证,是一种反盗版机制,如果不取消,则拒绝编译

Enable loadable module support--->Module signature verification(EXPERIMENTAL)

wKioL1M-nmKR_aXfAABh6oyZUPQ500.png

(5)关闭内核签名检查

Cryptographic API--->In-kernel signature checker(EXPERIMENTAL)

wKiom1M-nqfSysxEAABcSI-7M9I031.png

(6)保存退出

wKioL1M-npDRcYHwAAATwN9PZu8931.png

5、编译并安装内核
# make -j 4
# make modules_install
# make install

经过漫长的两个小时的编译,居然还没有编译完事,端起来电脑看,屏幕一直在滚动,终于发现了它好像一直就在那一个页面循环啊!

wKioL1M-nq7g6U5qAAB54EnNGu0158.png

又经过了漫长的一夜的等待,回头一看,居然又报错了,真是天理难容啊!

wKiom1M-nu_imc0nAAA0LFZm5v4572.png

貌似是在说磁盘空间不足的问题,那就使用df -h查查看吧

wKioL1M-ntbSJlOlAAAZk2WffXA442.png

   果然是100%了,哎,又没做LVM,看来只能重做个系统了,给根分大点,再重新来一次。
又经过漫长的一上午的艰苦等待,还是没有成功,居然又给报了一个错,说是找不到IPv4连接追踪模块?(气的忘截图了)突然想起来那我会编译的时候是直接编译到内核了,看来不行,那就改成模块方式(上面步骤中已经改正),再来!……又过了好久好久 终于OK了!
6、重启系统,启用新内核

wKioL1M-nv2CABYBAAAjrwWap5Y812.png

7、编译iptables
(1)为iptables打补丁
现在虽然内核支持layer7了,但是iptables并不支持layer7命令,所以我们还需要编译iptables,为iptables打补丁,让其能够支持layer7命令
# tar xf iptables-1.4.20.tar.gz

wKiom1M-n1KB592vAACBi6kTKTk996.png

(2)备份iptables的服务脚本及配置文件

wKiom1M-n2Lw5o_RAAA4GRDRDkQ003.png

(3)卸载iptables
rpm -e iptables iptables-ipv6 --nodeps
(4)编译安装iptables
./configure  --prefix=/usr  --with-ksource=/usr/src/linux

wKioL1M-n1_wZJ2kAAAwnNyjj6E488.png

   编译时可能会出现这样一个界面,直接略过

wKioL1M-4Qjij1YGAABZe-XfCMk850.png

(5)make && make install
(6)为编译安装的iptables提供脚本及配置文件
# tar zxvf l7-protocols-2009-05-28.tar.gz
# cd l7-protocols-2009-05-28
# make install
8、为layer7模块提供其所识别的协议的特征码
# tar zxvf l7-protocols-2009-05-28.tar.gz
# cd l7-protocols-2009-05-28
# make install

wKioL1M-n3ihvxxhAABYFuy5kDo253.png

9、如何使用layer7模块
(1)查看iptables的版本

wKiom1M-n7XCdp_9AAAWZBs0YOw494.png

(2)修改iptables的脚本
因为我们在编译安装的时候修改了脚本的安装路径,所以我们复制前的那个脚本中的会有一些问题需要改改
1
vim /etc/rc.d/init.d/iptables

wKioL1M-n7Gg9b6xAAAgx8m9pqw736.png

(3)ACCT的功能已经可以在内核参数中按需启用或禁用。此参数需要装载nf_conntrack模块后方能生效。

wKiom1M-n_yBG7Y5AAA2ka0uZX4540.png

(4)启用连接追踪功能
这里需要在/etc/sysctl.conf中添加一条

wKioL1M-n-3AAKRmAAATP073Lts704.png

(5)iptables应用层过滤语法
因为我们为iptables打了补丁,使其能够支持应用层的过滤,所以就支持了新的语法格式
1
# iptables [specify table & chain] -m layer7 --l7proto [protocol name] -j [action]
五、应用层过滤测试(基于iptables实现应用层QQ协议过滤)
1、内网客户端环境

内网客户端win7一台,处于VMnet5段中

wKiom1M-p0iwM1qzAAB1JbqWlhg940.png

2、服务器端配置
(1)网卡分配

服务器配置两块网卡,一块用于外网(eth0:172.16.251.93),一块用于外网(eth1:192.168.1.104)

wKiom1M-p5CBnmLXAABuVIecSMY018.png

 
(2)开启转发功能

为了使内网客户端能够通过此服务器上网,需开启转发功能

wKioL1M-p5CRe9X_AAAaHlrGXjM441.png

这只是临时设置,重启失效,如果想永久生效,请修改配置文件/etc/sysctl.conf
(3)设置iptables规则,使内网客户端可以外网

方法一:设置源地址转换

wKiom1M-p-fwLngyAAA--_atdFE784.png

方法二:设置内网源地址伪装

wKioL1M-p9uyYCUAAABIkjLsBB4067.png

(4)l7规则前,内网客户端可正常登录QQ

wKiom1M-qDqS8HdyAAVXPjeiI-s801.png

(5)基于iptables规则过滤QQ协议

wKioL1M-qC_DvqihAAAlJV6Sduc903.png

(6)查看过滤结果

wKioL1M-xNyDii20AAP95fcBvjs074.png

效果不言而喻,当然是完美的,不过要想结果完美,还要经过一段痛苦的折磨期!!!