目录:
一、理论部分.
二、实验部分.
**********************************理论部分**********************************
1. 前提知识
任何主机若要与非同网络中的主机通信,则必须将报文发送到默认网关;对Linux而言,IP地址是属于主机(内核中)的,不属于网卡,只要属于当前主机的IP地址间,都可直接响应,不能称为转发;私有地址在路由器上是不允许被路由的
2. iptables简介:
netfilter/iptables(简称为iptables)是Linux平台下的基于内核的包过滤型防火墙,工作于主机或网络的边缘, 能够对于进出本主机或网络的报文根据和实现定义好的检查规则作匹配检测,对于能够被规则所匹配的报文做出相应处理的组件;与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能。
3. 防火墙的类型和作用的链:
主机防火墙:一般使用INPUT,OUTPUT链来过滤进入和发出的报文。
网络防火墙:一般使用PREROUTING,FORWARD,POSTROUTING链来转发经过的报文。
4. iptables和netfilter的关系:
其实iptables只是Linux防火墙的管理工具而已,位于/sbin/iptables。真正实现防火墙功能的是netfilter,它是Linux内核中实现包过滤的内部结构。
5. iptables的功能:
iptables内置了filter,nat,mangle和raw这四张表,由于raw几乎用不到,因此很多地方会说三张表。
filter: 过滤, 防火墙;
nat: network address translation, 网络地址转换;
mangle: 拆解报文, 作出修改, 封装报文;
raw: 关闭nat表上启用的连接追踪机制;
注:连接追踪功能在承载大量连接并发的情况下不允许开启,如果不得不开启,需要有足够大的内存空间,并且将连接追踪功能的值调到足够大.
6. 各功能的分别实现:
filter: INPUT, FORWARD, OUTPUT
nat: PREROUTING(DNAT), OUTPUT, POSTROUTING(SNAT)
mangle: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING
raw: PREROUTING, OUTPUT
图示:
7. 对5条链的说明:
PREROUTING 路由前完成
INPUT 进入本机内部
FORWARD 由本机转发
OUTPUT 本机出口
POSTROUTING 第二次路由之后做出处理
注:链是内置的.
8.规则表之间的优先顺序:
raw——mangle——nat——filter
规则链之间的优先顺序(分三种情况):
第一种情况:入站数据流向
从外界到达防火墙的数据包,先被PREROUTING规则链处理(是否修改数据包地址等),之后会进行路由选择(判断该数据包应该发往何处),如果数据包的目标主机是防火墙本机(比如说Internet用户访问防火墙主机中的web服务器的数据包),那么内核将其传给INPUT链进行处理(决定是否允许通过等),通过以后再交给系统上层的应用程序(比如Apache服务器)进行响应。
第二冲情况:转发数据流向
来自外界的数据包到达防火墙后,首先被PREROUTING规则链处理,之后会进行路由选择,如果数据包的目标地址是其它外部地址(比如局域网用户通过网关访问公网站点的数据包),则内核将其传递给FORWARD链进行处理(是否转发或拦截),然后再交给POSTROUTING规则链(是否修改数据包的地址等)进行处理。
第三种情况:出站数据流向
防火墙本机向外部地址发送的数据包(比如在防火墙主机中测试公网DNS服务器时),首先被OUTPUT规则链处理,之后进行路由选择,然后传递给POSTROUTING规则链(是否修改数据包的地址等)进行处理。
9. 添加规则时的考量点:
(1) 要实现哪种功能: 判断添加在哪张表上;
(2) 报文流经的路径: 判断添加在哪个链上;
10. 对于链: 链上规则的次序, 即为检查的次序,因此隐含一定的法则:
(1) 同类规则(访问同一应用), 匹配范围小的放上面;
(2) 不同类规则(访问不同应用), 匹配到报文频率较大的放上面;
(3) 将那些可由一条规则描述的多个规则合并为一个;
(4) 设置默认策略;
11. iptables命令:
iptables [-t table] {-A|-C|-D} chain rule-specification iptables [-t table] -I chain [rulenum] rule-specification //rulenum可省,省略时表示第一条. iptables [-t table] -R chain rulenum rule-specification iptables [-t table] -D chain rulenum iptables [-t table] -S [chain [rulenum]] iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...] iptables [-t table] -N chain iptables [-t table] -X [chain] iptables [-t table] -P chain target iptables [-t table] -E old-chain-name new-chain-name iptables [-t table] SUBCOMMAND CHAIN CRETERIA -j TARGET
注:
[-t table]省略的话默认是filter表
SUBCOMMAND: 子命令
CRETERIA: 链的匹配标准
TARGET: 处理动作
SUBCOMMAND:
12. 链管理:
-F: flush, 清空规则链; 省略链, 表示清空指定表上的所有的链;
-N: new, 创建新的自定义规则连;
-X: delete/drop, 删除用户自定义的空的规则链;
-Z: zero, 清零, 置零规则计数器
-P: Policy, 为指定链设置默认策略;
对filter表中的链而言, 默认策略通常有ACCEPT(允许,放行), DROP(丢弃), REJECT(拒绝);
-E: rEname, 重命名自定义链; 引用计数不为0的自定义链, 无法改名, 也无法删除;
-L, --list:列出某规则链中的所有规则。
规则管理:
-A: append, 将新规则追加于指定链的尾部;
-I: insert, 将新规则插入至指定链的指定位置; //不指明插入的行数时默认插入到第一行.
-D: delete, 删除指定链上的指定规则;
有两种指定方式:
(1) 指定匹配条件;
(2) 指定规则编号;
-R: replace, 替换指定链上的指定规则;
示例:
# iptables -R INPUT 2 -d 172.16.100.9 -p tcp -m multiport --dports 21,22,80 -m state NEW -j REJECT
查看:
-L: list, 列出指定链上的所有规则;
-n: numberic, 以数字格式显示地址和端口号;
-v: verbose, 显示详细信息;
-vv, -vvv:详细更详细信息.
--line-numbers: 显示规则编号;
-x: exactly, 显示计数器计数结果的精确值;
13. 匹配条件:
[!] -s IP|Netaddr: 检查报文中的源IP地址是否符合此处指定的地址范围;
[!] -d IP|Netaddr: 检查报文中的目标IP地址是否符合此处指定的地址范围;
-p {tcp|udp|icmp}: 检查报文中的协议, 即ip首部中的protocols所标识的协议;
-i IFACE: 数据报文的流入接口; 仅能用于PREROUTING, INPUT及FORWARD链上;
-o IFACE: 数据报文的流出接口; 仅能用于FORWARD, OUTPUT及POSTROUTING链上;
扩展匹配:
-m match_name --spec_options
例: -m tcp --dport 22
隐式扩展:
对 -p protocol指明的协议进行的扩展,可省略-m选项;
-p tcp
--dport PORT[-PORT]: 目标端口, 可以是单个端口或连续多个端口;
--sport PORT[-PORT]
--tcp-flags LIST1 LIST2: 检查LIST1所指明的所有标志位, 且这其中, LIST2所表示出的所有标记位必须为1,而余下的必须为0; 没有LIST1中指明的, 不做检查;
(SYN, ACK, FIN, RST, PSH, URG)
--tcp-flags SYN,ACK,FIN,RST, SYN
--syn
-p udp
--dport
--sport
-p icmp
--icmp-type
可用数字表示其类型
0: echo-reply
8: echo-request
-j TARGET:
ACCEPT: 接收
DROP: 丢弃
REJECT: 拒绝
LOG: 记录日志
MARK: 做防火墙标记
DNAT: 目标地址转换
SNAT: 原地址转换
MASQUERADE: 地址伪装
...
14. 显式扩展:
必须显式指明使用的扩展模块;
# rpm -ql iptables|grep "\.so$"
查看显示扩展的帮助信息:
CentOS6:#man iptables
CentOS7:#man iptables-extensions
1. multiport扩展:
以离散方式定义多端口匹配,最多指定15个端口;
[!] --source-ports, --sports PORT : 指明多个源端口;
[!] --destination-ports, --dports PORT: 指明多个离散的目标端口;
[!] --ports port
例: 同时放行ssh服务的22号端口和www服务的80号端口:
# iptables -I INPUT -s 10.68.7.0/24 -d 10.68.7.107 -p tcp -m multiport --dports 22,80 -j ACCEPT # iptables -I OUTPUT -d 10.68.7.0/24 -s 10.68.7.107 -p tcp -m multiport --sports 22,80 -j ACCEPT
2. iprange扩展:
指明连续的但一般不能扩展为整个网络的IP地址范围时使用;
[!] --src-range from[-to]: 指明连续的源ip地址范围;
[!] --dst-range from[-to]: 指明连续的目标IP地址范围;
例:
# iptables -I INPUT -d 172.16.100.9 -p tcp -m multiport --dports 22:23,80 -m iprange --src-range 172.16.100.1-172.16.100.120 -j ACCEPT # iptables -I OUTPUT -s 172.16.100.9 -p tcp -m multiport --sports 22:23,80 -m iprange --dst-range 172.16.100.1-172.16.100.120 -j ACCEPT
3. string扩展:
通过字符匹配检测报文单元中出现的字符串;
--algo {bm|kmp}
bm = Boyer-Moore
kmp = Knuth-Pratt-Morris
[!] --string pattern
例: 搭建http服务,匹配网页中出现的字符串
编辑如下内容,并确保浏览器访问正常:
# vim /var/www/html/bad.html ...增加如下内容: This is the movie page!
编写防火墙规则,组织含有字符串"movie"的报文通过:
# iptables -I OUTPUT -m string --algo bm --string ‘movie‘ -j REJECT
此时,浏览器刷新该页面已无法显式,即被匹配到的规则所阻止。
4. time扩展:
根据报文到达的时间与指定的时间范围进行匹配;
--datestart
--datestop
--timestart
--timestop
--monthdays
--weekdays
例:
# iptables -I INPUT -d 172.16.100.9 -p tcp --dport 80 -m time --timestart 14:00 --timestop 16:00 -j REJECT
5. connlimit扩展:
根据每客户端IP做并发连接数量匹配;
--connlimit-above n: 连接的数量大于n
--connlimit-upto n: 连接的数量小于等于n
例:SSH新建立的连接大于3个即被拒绝:
# iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j REJECT
6. limit扩展:
基于收发报文的速率做检查:
--limit rate[/second|/minute|/hour|/day]
--limit-burst number
例:
~]# iptables -I INPUT -d 172.16.100.67 -p icmp --icmp-type 8 -mlimit --limit 3/minute --limit-burst 5 -j ACCEPT
7. state扩展:
根据”连接追踪机制“去检查连接的状态,内核中的netfilter记录实现:
[!] --state STATE1,STATE2,...
调整连接追踪功能能够容纳的最大连接数量;
/proc/sys/net/nf_conntrack_max
已经追踪到并记录下的连接:
/proc/net/nf_conntrack
不同协议或连接类型追踪时长:
/proc/sys/net/netfilter/
conntrack机制:追踪本机上的请求和响应之间的关系;状态有如下几种
可追踪的连接状态:
NEW: 新发出的请求; 连接追踪模板中不存在此连接相关的信息条目; 因此,将其识别为第一次发出的请求;
ESTABLISHED: NEW状态之后,连接追踪模板中为其建立的条目失效之前期间内所进行的通信的状态;
RELATED: 相关的连接;如ftp协议的命令连接与数据连接之间的关系;
INVALIED: 无法识别的连接;
NEW:
NEW状态的数据包说明这个数据包是收到的第一个数据包。比如收到一个SYN数据包,它是连接的第一个数据包,就会匹配NEW状态。第一个包也可能不是SYN包,但它仍会被认为是NEW状态。
ESTABLISHED:
只要发送并接到应答,一个数据连接就从NEW变为ESTABLISHED,而且该状态会继续匹配这个连接后继数据包。
RELATED:
当一个连接和某个已处于ESTABLISHED状态的连接有关系时,就被认为是RELATED,也就是说,一个连接想要是RELATED的,首先要有个ESTABLISHED的连接,这个ESTABLISHED连接再产生一个主连接之外的连接,这个新的连接就是RELATED。
INVALID:
INVALID状态说明数据包不能被识别属于哪个连接或没有任何状态。
例:
# iptables -I INPUT -d 172.16.100.9 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT # iptables -I ONPUT -s 172.16.100.9 -p tcp --dport 22 -m state --state ESTABLISHED -j ACCEPT
8. MAC扩展:
根据目标计算机的MAC地址进行匹配,比较精确:
--mac-source MAC地址
例:将目标计算机的MAC设为ACCEPT
# iptables -A INPUT -i eth0 -m MAC --mac-source 00-C0-9F-79-E1-8A -j ACCEPT
15. 保存及重载规则:
保存规则至指定文件 :
iptables-save > /PATH/TO/SOMEFILE
从指定文件重载规则:
iptables-restore < /PATH/TO/SOMEFILE
CentOS 6:
service iptables save
# iptables-save > /etc/sysconfig/iptables
service iptables restart
# iptables-restore < /etc/sysconfig/iptables
CentOS 7:
引入了新的iptables前端管理服务工具:firewalld
firewalld-cmd
firewalld-config
关于firewalld:
http://www.ibm.com/developerworks/cn/linux/1507_caojh/index.html
16. NAT表:
nat:
SNAT:只修改请求报文的源地址;
DNAT: 只修改请求报文的目标地址
nat表:
PREROUTING: DNAT
OUTPUT
POSTROUTING: SNAT //原地址转换在POSTROUTING进行.
源地址转换:
iptables -t nat -A POSTROUTING -s LocalNet ! -d LocalNet -j SNAT --to-source ExtIP iptables -t nat -A POSTROUTING -s LocalNet ! -d LocalNet -j MASQUERADE
MASQUERADE(地址伪装):能自动将原地址转换成适用的原地址
例:
[[email protected] ~]# iptables -t nat -A POSTROUTING -s 10.68.7.234 -j MASQUERADE //把原地址自动转换成适用的"原地址".
例:
[[email protected] ~]# iptables -t nat -A POSTROUTING -s 10.68.7.234 ! -d 10.68.7.0/24 -j SNAT --to-source 192.168.1.200 //把所有源地址为10.68.7.234到目标主机为非10.68.7.0网段的ip都转换为源地址为192.168.1.200的ip.
目标地址转换:
# iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport POST -j DNAT --to-destination InerServerIP[:PORT]
例:
[[email protected] ~]# iptables -t nat -A PREROUTING -d 10.68.7.107 -p tcp --dport 22 -j DNAT --to-destination 192.168.1.20 //源地址为任意地址,通过ssh访问10.68.7.107时,会自动被DNAT成192.168.1.20的主机地址.
17. tcp_wrapper实现访问控制
tcp_wrapper的原理:
Telnet、SSH、FTP、POP3和SMTP等很多网络服务都会用到TCP Wrapper,它被设计为一个介于外来服务请求和系统服务回应的中间处理软件。
基本处理过程:
当系统接收到一个外来服务请求的时候 ,先由TCP Wrapper处理这个请求;TCP Wrapper根据这个请求所请求的服务和针对这个服务所定制的存取控制规则来判断对方是否有使用这个服务的权限,如果有,TCP
Wrapper 将该请求按照配置文件定义的规则转交给相应的守护进程去处理同时记录这个请求动作,然后自己就等待下一个请求的处理。
tcp_wrapper是基于主机与服务的
使用简单的配置文件来设置访问限制:
/etc/hosts.allow
/etc/hosts.deny
要想利用tcp_wrappers的集中验证功能,要服务的模块支持tcp_wrapper,查看一个服务是否支持tcp_wrapper可以用一下命令 ,看某个服务的执行文件是否调用tcp_wrapper用命令:
# ldd `which sshd` |grep wrap //which sshd是找到服务的可执行文件路径
如果下面这个命令有结果,也表明支持tcp_wrapper
# strings `which sshd` |grep wrap
注:基于xinetd的服务都支持tcp_wrapper
访问控制判断顺序:
访问是否被明确许可?否则,访问是否被明确禁止?如果都没有,默认许可。
通常tcp_wrapper没有配置,就是第三条,如果都没有,默认许可的
注: 由于allow比deny优先级高,可以在allow中定义允许访问的IP,而在deny拒绝所有,这样就只有明确 允许的用户才能访问。
基本语法
后台进程列表: 客户端列表 //参数:allow,deny
# vim /etc/hosts.allow sshd:192.168.1. /etc/hosts.deny sshd:ALL
格式是
后台进程: client描述
解释
后台进程列表应该是:
服务的可执行工具名( in.telnetd NO telnetd)
允许指定多项服务
允许使用ALL来匹配所有服务
允许可执行工具名后添加IP或主机名,如果本机有多个网络界面
客户端描述可以包含:
IP 地址(192.168.1.254 )
域名或主机名(.example.com, www.irusadmin.cn )
子网掩码(192.168.1.0/255.255.255.0 或192.1681. )
网络名(@irusadmin.cn )
client描述的高级语法
客户端描述通配符
ALL:所有
LOCAL:所有主机名中不包含.的主机
UNKNOWN:无法被解析的主机
KNOWN:可以双向解析的主机
PARANOID:正向解析成功但无法反向解析的主机
EXCEPT
可用于服务列表与客户端列表, 可以层层套用
例:
# vim /etc/hosts.deny ALL:ALL EXCEPT 192.168.0.0/255.255.255.0 EXCEPT server1.example.com
注:hosts.allow和hosts.deny的更改都是立刻见效,无须重启xinetd服务
补充:
1. 对于forward链用到的路由转发的详细说明,我在上一篇博客《ip_forward与路由转发》中有写;
2. 对于iptables的代码层次的原理分析,详见这篇博客:
http://blog.chinaunix.net/uid-23069658-id-3160506.html
3. 我在网上搜集的iptables练习题,加深印象:
运维人员20道必会iptables面试题:
http://www.tuicool.com/articles/AneEZje
iptables练习题:
https://www.centos.bz/2012/08/iptables-exercises/
*************************实验部分**************************************
实验环境:
此处沿用我在上一篇博客《ip_forward与路由转发》中的环境不变。
实验要求:
1.内网架设ftp服务,放行让外网主机访问;
2.内网架设DNS服务,放行让外网主机访问,放行查询和区域传送请求;
1.1 yum安装ftp服务:
[[email protected]_host ~]# yum install -y vsftpd [[email protected]_host ~]# service vsftpd start Starting vsftpd for vsftpd: [ OK ] [[email protected]_host ~]#
1.2装载FTP模块:
[[email protected]_host ~]# modprobe nf_conntrack_ftp [[email protected]_host ~]# lsmod |grep ftp nf_conntrack_ftp 11953 0 nf_conntrack 79206 6 nf_conntrack_ftp,iptable_nat,nf_nat,nf_conntrack_ipv4,nf_conntrack_ipv6,xt_state [[email protected]_host ~]#
1.3 编写规则:
[[email protected]_host ~]# iptables -P FORWARD DROP [[email protected]_host ~]# iptables -L -n -v Chain INPUT (policy ACCEPT 6102 packets, 579K bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 4320 packets, 482K bytes) pkts bytes target prot opt in out source destination [[email protected]_host ~]# iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
1.4 外网主机访问:
[[email protected]_host ~]# lftp 10.68.7.234 lftp 10.68.7.234:~> ls drwxr-xr-x 2 0 0 4096 Jul 24 2015 pub lftp 10.68.7.234:/>
OK.
2.1 安装DNS服务:
DNS服务的安装详见我之前的博客《【详解】DNS服务工作原理、正反向解析和主从同步 》
此处,正向解析和区域传送已配置完成.
2.2
递归查询请求的是UDP的53号端口;区域传送请求的是TCP的53号端口.
对于递归查询需要考虑的情况:
当local_host作为主服务器,pub_host作为从服务器发起查询请求时,local_host需要开放DPORT的UDP/53号端口;local_host响应pub_host的查询请求时,需开放SPORT的UDP/53号端口;
当local_host作为主服务器对于pub_host的查询请求解析不了时,local_host就需要自己扮演客户端,向互联网上的DNS服务器发起递归查询请求,此时需要请求互联网上的DNS服务器的UDP/53号端口,因此需开放DPORT的UDP/53号端口,然后互联网上的DNS服务器向local_host服务器发起相应,此时需开放SPORT的UDP/53号端口。
对于区域传送需考虑的情况:
当local_host作为主服务器,等待pub_host这台从服务器来同步时,需开放DPORT的TCP/53号端口,local_host响应pub_host的查询请求时,需开放SPORT的TCP/53号端口;;如果local_host是台从服务器,向别的主服务器请求同步时,需开放DPORT的TCP/53号端口;还有可能local_host是另一台从服务器的从服务器,需要从多个方面进行考虑。
此处只进行简单考虑:
递归查询前:
[[email protected] ~]# iptables -A INPUT -d 10.68.7.234 -p udp --dport 53 -j ACCEPT [[email protected] ~]# iptables -A OUTPUT -s 10.68.7.234 -p udp --sport 53 -j ACCEPT
开始递归查询时:
[[email protected] ~]# iptables -A OUTPUT -s 10.68.7.234 -p udp --dport 53 -j ACCEPT [[email protected] ~]# iptables -A INPUT -d 10.68.7.234 -p udp --sport 53 -j ACCEPT
区域传送:
[[email protected] ~]# iptables -A INPUT -d 192.168.1.201 -p tcp --dport 53 -j ACCEPT [[email protected] ~]# iptables -A OUTPUT -s 10.68.7.234 -p tcp --sport 53 -j ACCEPT
完成!