iptables
一、防火墙工作原理
Framework:iptables/netfilter
Netfilter组件:扩展各种网络服务的结构化底层框架,集成在linux内核中
内核中选取五个位置放了五个hook(勾子) function(INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING),而这五个hook function向用户开放,用户可以通过一个命令工具(iptables或firewall-cmd、frewall-config)向其写入规则
由信息过滤表(table)组成,包含控制IP包处理的规则集(rules),规则被分组放在链(chain)上
1、四表五链
四表:table
- filter表:过滤规则表,根据预定义的规则过滤符合条件的数据包
- nat表:network address translation 地址转换规则表
- mangle:修改数据标记位规则表
- raw:关闭NAT表上启用的连接跟踪机制,加快封包穿越防火墙速度
五链:chain
-
PREROUTING
-
INPUT
-
OUTPUT
-
FORWARD
-
POSTROUTING
表和链对应关系:
优先级由高到低的顺序为:raw --> mangle --> nat --> filter
2、内核中数据包的传输过程
- 当一个数据包进入网卡时,数据包首先进入PREROUTING链,内核根据数据包目的IP判断是否需要转送出去
- 如果数据包就是进入本机的,数据包就会沿着图向下移动,到达INPUT链。数据包到达INPUT链后,任何进程都会收到它。本机上运行的程序可以发送数据包,这些数据包经过OUTPUT链,然后到达POSTROUTING链输出
- 如果数据包是要转发出去的,且内核允许转发,数据包就会向右移动,经过FORWARD链,然后到达POSTROUTING链输出
3、iptables规则
规则 rule:根据规则的匹配条件尝试匹配报文,对匹配成功的报文根据规则定义的处理动作作出处理
匹配条件:默认为与条件,同时满足
- 基本匹配:IP,Port,TCP的Flags(SYN,ACK等)
- 扩展匹配:通过复杂高级功能匹配
处理动作:target
- 内建处理动作:ACCEPT,DROP,REJECT,SNAT,DNAT,MASQUERADE,MARK,LOG...
- 自定义处理动作:自定义chain,利用分类管理复杂情形
规则要添加在链上,才生效;添加在自定义上不会自动生效
链:chain
- 内置链:每个内置链对应于一个钩子函数
- 自定义链:用于对内置链进行扩展或补充,可实现更灵活的规则组织管理机制;只有Hook钩子调用自定义链时才生效
二、iptables命令
用来编写规则,写好的规则被送往netfilter,告诉内核如何去处理信息包
用法:iptables [-t table] COMMAND chain 匹配条件 -j 处理动作
1、-t table :如果不写默认filter表
- filter
- nat
- mangle
- raw
2、COMMAND
2.1) 管理规则
- -A:附加一条规则,添加在链的尾部
- -I CHAIN [num]:插入一条规则,插入为对应链上的第num条,默认插入第一条
- -D CHAIN [num]:删除第num条规则
- -R CHAIN [num]:替换第num条规则
- -F [CHAIN]:清空指定规则链,如果省略CHAIN,则删除对应表中的所有链
- -Z:置零计数器
2.2)查看规则
- -L:list, 列出指定鏈上的所有规则,本选项须置后
- -n:numberic,以数字格式显示地址和端口号
- -v:verbose,详细信息,-vv 更详细
- -x:exactly,显示计数器结果的精确值,而非单位转换后的易读值
- --line-numbers:显示规则的序号
- -S:以iptables-save 命令格式显示链上规则
2.3)管理链
- -N:自定义一条新的规则链
- -X:删除自定义的空的规则链
- -P CHAIN {ACCEPT|DROP}:Policy,设置默认策略
- -E:重命名自定义链;引用计数不为0的自定义链不能够被重命名,也不能被删除
3、chain
- PREROUTING
- INPUT
- FORWARD
- OUTPUT
- POSTROUTING
4、匹配条件
匹配条件分为通用匹配和扩展匹配,扩展匹配又分为隐含扩展和显式扩展
4.1)通用匹配:无需加载模块,由iptables/netfilter自行提供
- [!] -s, --source address[/mask][,...]:源IP地址或范围
[root@centos7 ~]# iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT
[root@centos7 ~]# iptables -A INPUT -j DROP
- [!] -d, --destination address[/mask][,...]:目标IP地址或范围
[root@centos7 ~]# iptables -A OUTPUT -d 192.168.0.0/24 -j ACCEPT
[root@centos7 ~]# iptables -A OUTPUT -j DROP
- [!] -p, --protocol protocol:指定协议portocol:tcp、udp、icmp,参考
/etc/protocols
[root@centos7 ~]# iptables -A INPUT -p tcp -j ACCEPT
- [!] -i, --in-interface name:报文流入的接口;只能应用于数据报文流入环节,只应用于INPUT、FORWARD、PREROUTING链
[root@centos7 ~]# iptables -A INPUT -i lo -j ACCEPT
- [!] -o, --out-interface name:报文流出的接口;只能应用于数据报文流出的环节,只应用于FORWARD、OUTPUT、POSTROUTING链
[root@centos7 ~]# iptables -A OUTPUT -o lo -j ACCEPT
4.2) 扩展匹配条件:需要加载扩展模块/usr/lib64/xtables/*.so
,查看帮助man iptables-extensions
4.2.1)隐式扩展:在使用-p选项指明了特定的协议时,无需再用-m选项指明扩展模块的扩展机制,不需要手动加载扩展模块
tcp协议的扩展选项:
- [!] --source-port, --sport port[:port]:匹配报文源端口,可为端口范围
[root@centos7 ~]# iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
[root@centos7 ~]# iptables -A OUTPUT -j DROP
- [!] --destination-port,--dport port[:port]:匹配报文目标端口,可为范围
[root@centos7 ~]# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
[root@centos7 ~]# iptables -A INPUT -j DROP
- [!] --tcp-flags mask comp:mask 需检查的标志位列表,用,分隔,例如 SYN,ACK,FIN,RST;comp 在mask列表中必须为1的标志位列表,无指定则必须为0,用,分隔
[root@centos7 ~]# iptables -I INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -j ACCEPT
- [!] --syn:用于匹配第一次握手,相当于:
--tcp-flags SYN,ACK,FIN,RST SYN
[root@centos7 ~]# iptables -I INPUT -p tcp --syn -j ACCEPT
udp协议的扩展选项:
-
[!] --source-port, --sport port[:port]:匹配报文的源端口;可以是端口范围
-
[!] --destination-port,--dport port[:port]:匹配报文的目标端口;可以是端口范围
icmp协议的扩展选项:
- [!] --icmp-type {type[/code]|typename}:0:icmp应答;8:icmp请求
[root@centos7 ~]# iptables -A INPUT -p icmp --icmp-type 8 -j DROP #不接受ping请求
[root@centos7 ~]# iptables -A OUTPUT -p icmp --icmp-type 0 -j ACCEPT
4.2.2)显式扩展:必须使用 -m 选项指明要调用的扩展模块的扩展机制,要手动加载扩展模块
使用帮助:
CentOS 6: man iptables
CentOS 7: man iptables-extensions
multiport:以离散方式定义多端口匹配,最多指定15个端口
- [!] --source-ports,--sports port[,port|,port:port]...:指定多个源端口
- [!] --destination-ports,--dports port[,port|,port:port]...:指定多个目标端口
- [!] --ports port[,port|,port:port]...:多个源或目标端口
[root@centos7 ~]# iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT
iprange:指明连续的(但一般不是整个网络)ip地址范围
- [!] --src-range from[-to]:源IP地址范围
- [!] --dst-range from[-to]:目标IP地址范围
[root@centos7 ~]# iptables -A INPUT -m iprange --src-range 192.168.0.100-192.168.0.200 -j REJECT
mac:指明源MAC地址,适用于:PREROUTING,FORWARD,INPUT
- [!] --mac-source XX:XX:XX:XX:XX:XX
string:对报文中的应用层数据做字符串模式匹配检测
- --algo {bm|kmp}:字符串匹配检测算法
- --from offset 开始偏移
- --to offset 结束偏移
- [!] --string pattern:要检测的字符串模式
- [!] --hex-string pattern:要检测字符串模式,16进制格式
[root@centos7 ~]# echo "www.baidu.com" > /var/www/html/f1.txt
[root@centos7 ~]# echo "www.google.com" > /var/www/html/f2.txt
[root@centos7 ~]# systemctl start httpd
[root@centos6 ~]# curl 192.168.0.7/f1.txt
www.baidu.com
[root@centos6 ~]# curl 192.168.0.7/f2.txt #加规则之前正常访问
www.google.com
[root@centos7 ~]# iptables -A OUTPUT -m string --algo bm --string google -j REJECT #在OUTPUT链上加字符串匹配规则
[root@centos6 ~]# curl 192.168.0.7/f1.txt #baidu正常访问
www.baidu.com
[root@centos6 ~]# curl 192.168.0.7/f2.txt #google无法访问
time:根据将报文到达的时间与指定的时间范围进行匹配
- --datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
- --datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
- --timestart hh:mm[:ss]
- --timestop hh:mm[:ss]
- [!] --monthdays day[,day...]
- [!] --weekdays day[,day...]
- --kerneltz:内核时区,CentOS7系统默认为UTC;CentOS6不支持kerneltz,默认使用--localtz:指定本地时区
[root@centos7 ~]# iptables -A INPUT -d 192.168.0.7 -p tcp --dport 80 -m time --timestart 1:00 --timestop 4:00 --weekdays 1,3,5 --kerneltz -j DROP
connlimit:根据每客户端IP做并发连接数数量匹配,通常分别与默认的拒绝或允许策略配合使用
- --connlimit-upto n:连接的数量小于等于n时匹配
- --connlimit-above n:连接的数量大于n时匹配
[root@centos7 ~]# iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
limit:基于收发报文的速率做匹配,令牌桶过滤器
- --limit rate[/second|/minute|/hour|/day] 每多长时间接收rate个包
- --limit-burst number 第一次允许流入多少个包
[root@centos7 ~]# iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 10/minute --limit-burst 5 -j ACCEPT
[root@centos7 ~]# iptables -A INPUT -p icmp -j REJECT
state:根据”连接追踪机制“去检查连接的状态
conntrack机制:追踪本机上的请求和响应之间的关系;
modprobe nf_conntrack
状态有如下几种:
- NEW:新发出请求;连接追踪信息库中不存在此连接的相关信息条目,因此,将其识别为第一次发出的请求
- ESTABLISHED:NEW状态之后,连接追踪信息库中为其建立的条目失效之前期间内所进行的通信状态
- RELATED:新发起的但与已有连接相关联的连接,如:ftp协议中的数据连接与命令连接之间的关系
- INVALID:无效的连接,如flag标记不正确
- UNTRACKED:未进行追踪的连接,如raw表中关闭追踪
- [!] --state
[root@centos7 ~]# iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
[root@centos7 ~]# iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW -j ACCEPT[root@centos7 ~]# iptables -A INPUT -j DROP
已经追踪到的并记录下来的连接信息库/proc/net/nf_conntrack
调整连接追踪功能所能够容纳的最大连接数量/proc/sys/net/nf_conntrack_max
不同的协议的连接追踪时长/proc/sys/net/netfilter/
iptables的链接跟踪表最大容量为/proc/sys/net/nf_conntrack_max
,各种状态的超时链接会从表中删除;当模板满载时,后续连接可能会超时
解决方法两个:
(1) 加大 nf_conntrack_max 值
vi /etc/sysctl.conf
net.nf_conntrack_max = 393216
net.netfilter.nf_conntrack_max = 393216
(2) 降低 nf_conntrack timeout 时间
vi /etc/sysctl.conf
net.netfilter.nf_conntrack_tcp_timeout_established = 300
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
5、-j target:处理动作
5.1)简单:
- ACCEPT
- DROP
5.2)扩展:
- REJECT:--reject-with:icmp-port-unreachable默认
- RETURN:返回调用链
- REDIRECT:端口重定向
- MARK:做防火墙标记
- DNAT:目标地址转换
- SNAT:源地址转换
- MASQUERADE:地址伪装
- 自定义链
- LOG:记录日志
LOG:非中断target,本身不拒绝和允许,放在拒绝和允许规则前并将日志记录在/var/log/messages系统日志中
- --log-level level:日志级别: emerg, alert, crit, error, warning, notice, info or debug
- --log-prefix prefix:日志前缀,用于区别不同的日志,最多29个字符
[root@centos7 ~]# iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j LOG --log-prefix "new ssh connections"
[root@centos7 ~]# tail -f /var/log/messages
三、规则优化、保存与恢复
- 安全放行所有入站和出站的状态为ESTABLISHED状态连接
- 谨慎放行入站的新请求
- 有特殊目的限制访问功能,要在放行规则之前加以拒绝
- 同类规则(访问同一应用),匹配范围小的放在前面,用于特殊处理
- 不同类的规则(访问不同应用),匹配范围大的放在前面
- 应该将那些可由一条规则能够描述的多个规则合并为一条
- 设置默认策略,建议白名单(只放行特定连接) , 建议在规则的最后定义规则做为默认策略
保存规则:iptables-save > /PATH/TO/SOME_RULES_FILE
载入规则:iptables-restore < /PATH/FROM/SOME_RULES_FILE
- -n, --noflush:不清除原有规则
- -t, --test:仅分析生成规则集,但不提交
四、开放被动模式的ftp服务
1)装载ftp连接追踪的专用模块:
[root@centos7 ~]# vim /etc/sysconfig/iptables-config
IPTABLES_MODULES="nf_conntrack_ftp"
[root@centos7 ~]# modprobe nf_conntrack_ftp
2)放行请求/响应报文
命令连接:NEW, ESTABLISHED
数据连接:RELATED, ESTABLISHED
[root@centos7 ~]# iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@centos7 ~]# iptables -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
[root@centos7 ~]# iptables -A INPUT -j DROP
[root@centos7 ~]# iptables -A OUTPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
[root@centos7 ~]# iptables -A OUTPUT -j DROP
五、NAT:network address translation
1、SNAT
请求报文的源地址转换,让本地网络中的主机通过某一特定地址访问外部网络,实现地址伪装
route:
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 ! -d 192.168.0.0/24 -j SNAT --to-source 10.0.0.254
动态转换:
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 ! -d 192.168.0.0/24 -j MASQUERADE
2、DNAT
请求报文的目标地址转换,把本地网络中的主机上的某服务开放给外部网络访问,发布服务和端口映射,隐藏真实IP
route:
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
# iptables -t nat -A PREROUTING -d 10.0.0.254 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.6:80
3、PNAT
端口和IP都进行转换
六、端口转发
配置于NAT表的 PREROUTING OUTPUT 链,通过改变目标IP和端口,将接受的包转发至不同端口
# iptables -t nat -A PREROUTING -d 192.168.0.6 -p tcp --dport 80 -j REDIRECT --to-ports 8080