Linux系统中,防火墙(Firewall)主要工作于网络层,它基于内核实现,网址转换(NAT),数据包(package)记录,流量统计,这些功能是由Netfilter子系统所提供的,而iptables是控制Netfilter的工具,将控制规则记录到netfilter中。iptables将许多复杂的规则组织成成容易控制的方式,以便管理员可以进行分组测试,或关闭、启动某组规则。
iptable能够为Unix、Linux和BSD创建一个防火墙(数据包进入用户空间),也可以为一个子网创建防火墙以保护其它的系统平台。
Netfilter与iptable
iptable:工作在用户空间,防火墙规则(创建,删除)管理软件,非必需的。
netfilter框架
netfilter:对流入流出数据包进行处理,工作在内核空间(内核态Kernel),不以任何文件或者程序存在,编译内核时已经静态编译不可取消(netfilter);netfilter就是在数据包进入网卡后在各个关键点设置关卡(钩子函数HOOK),钩子函数决定数据包的命运下一个动作是什么,经过钩子函数处理后返回5种值
NF_DROP: discarded the packet丢弃数据包
NF_ACCEPT :the packet passes,continue iterations数据包已经通过此“关卡”,但还要往下遍历其他钩子函数(迭代)
NF_STOLEN :gone away
NF_QUEUE :inject thepacket into a different queue (the target queue number is in the high 16 bitsof the verdict)
NF_REPEAT :iterate thesame cycle once more再次调用此函数
NF_STOP :accept, butdon't continue iterations接收数据包不需要进一步处理
防火墙一般由四表五链组成
以下为表和链的关系
各表放在不同的链上实现不同的功能
filter: 过滤数据包,不能修改数据包,防火墙;
nat: 网络地址转换,修改源地址或者目标地址;
放在不同链上的效果:PREROUTING(目标地址转换),OUTPUT(目标地址转换) ,INPUT(? 2.6.43kernel版本之后新添加),POSTROUTING(源地址转换)
mangle:拆解报文,做出修改,封装报文;
raw:关闭nat表上启用的连接追踪机制;
报文流入受到表约束的顺序为:
raw--> mangle --> nat --> filter
iptables 经常用到命令概览:
iptables [-t table]{-A|-D} chain rule-specification
iptables [-t table]-I chain [rulenum] rule-specification
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
table 选项有
-table
filter, nat, mangle,raw
未指定规则表时,默认为filter
经常匹配到的规则(例如网站的80端口)应该将其放在最前面,iptables匹配规则为自上而下逐一匹配,直到匹配到规则为止。
链管理的选项
-F:flush,清空规则链;省略链,表示清空指定表上的所有的链;
~]#iptables -F
-N:new, 创建新的自定义规则链;
-X:drop, 删除用户自定义的空的规则链;
-Z:zero,清零,置零规则计数器;
-P:Policy,为指定链设置默认策略;对filter表中的链而言,默认策略通常有ACCEPT, DROP, REJECT;
~]#iptables -P FORWARD DROP #默认为允许所有数据包都可以转发,修改默认设定为拒绝
-E: rEname,重命令自定义链;引用计数不为0的自定义链,无法改名,也无法删除;
规则管理选项
-A:append,将新规则追加于指定链的尾部;
~]# iptables-A INPUT -p tcp -j ACCEPT #tcp 协议全部放行
-I:insert, 将新规则插入至指定链的指定位置;
~]#iptables -I OUTPUT -p icmp -j ACCEPT#默认插入为第一编号
-D:delete, 删除指定链上的指定规则;
有两种指定方式:
(1) 指定匹配条件;
~]# iptables -DOUTPUT -p icmp -j ACCEPT
(2) 指定规则编号;
先查看编号
~]# iptables -L OUTPUT --line-numbers Chain OUTPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT udp -- anywhere anywhere 2 ACCEPT icmp -- anywhere anywhere |
~]#iptables -D OUTPUT 2 #删除第2条规则
-R:replace,替换指定链上的指定规则;
查看
-L:list,列出指定链上的所有规则;
-n: numberic,以数字格式显示地址和端口号;
-v: verbose,显示详细信息;
-vv,-vvv
~]# iptables -L -vvv
--line-numbers:显示规则编号;
~]#iptables -L --line-numbers #可以简写--line
-x: exactly, 显示计数器计数结果的精确值;
~]# iptables -L OUTPUT -v -x
匹配条件:
基本匹配:
[!] -s, --src, --source IP|Netaddr:检查报文中源IP地址是否符合此处指定的地址范围; #"!"意思取反
[!] -d, --dst, --destination IP|Netaddr:检查报文中源IP地址是否符合此处指定的地址范围;
-p, --protocol {tcp|udp|icmp}:检查报文中的协议,即ip首部中的protocols所标识的协议;
-i, --in-interface IFACE:数据报文的流入接口;仅能用于PREROUTING, INPUT及FORWARD链上;
~]#iptables -A INPUT -p tcp -i eno16777736 -j ACCEPT #从eno16777736网卡流入tcp协议的报文都允许通过
-o, --out-interface IFACE:数据报文的流出接口;仅能用于FORWARD, OUTPUT及POSTROUTING链上;
~]# iptables -AOUTPUT -p tcp -o eno16777736 -j ACCEPT
目标:
对匹配到报文所做的动作
-j TARGET:jump至指定的TARGET
ACCEPT: 接受
DROP: 丢弃
REJECT: 拒绝
RETURN: 返回调用链
REDIRECT:端口重定向
LOG: 记录日志
MARK:做防火墙标记
DNAT:目标地址转换
SNAT:源地址转换
MASQUERADE:地址伪装
扩展匹配
1.隐含扩展:
-ptcp: --dport, --sport, --tcp-flags, --syn (--tcp-flags SYN,ACK,FIN,RST SYN)
-pudp: --dport, --sport
-picmp: --icmp-type
显式扩展: -m
1.显式扩展: 必须使用-m选项指定使用的扩展
2.必须显式指明使用的扩展模块rpm -ql iptables | grep "\.so"
1、multiport扩展
一条规则多端口配置以离散方式定义多端口匹配;最多指定15个端口;
[!] --source-ports,--sports port[,port|,port:port]...:指明多个源端口;
[!] --destination-ports,--dports port[,port|,port:port]...:指明多个离散的目标端口;
[!] --portsport[,port|,port:port]... 不管是源端口还是目标端口
进入规则:源地址为172.16.0.0/16网段 目标地址为172.16.100.9 22 80 端口允许 ~]# iptables -I INPUT -s 172.16.0.0/16 -d 172.16.100.9 -p tcp -m multiport --dports 22,80 -j ACCEPT ~]# iptables -I OUTPUT -d 172.16.0.0/16 -s 172.16.100.9 -p tcp -m multiport --sports 22,80 -j ACCEPT |
2、iprange扩展
指明连续的(但一般是不能扩展为整个网络)ip地址范围时使用;
[!] --src-range from[-to]:指明连续的源IP地址范围;
[!] --dst-range from[-to]:指明连续的目标IP地址范围
172.16.100.1-172.16.100.120网段允许访问 10.10.100.128的22,23 ,80 tcp端口 ~]# iptables -I INPUT -d 10.10.100.128 -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 10.10.100.128 -p tcp -m multiport --sports 22:23,80 -m iprange --dst-range 172.16.100.1-172.16.100.120 -j ACCEPT |
3、string扩展
检查报文中出现的字符串;(前提没有加密)
条件:内核版本大于2.6.14
--algo {bm|kmp}
bm = Boyer-Moore 人名
kmp = Knuth-Pratt-Morris 人名
bm kmp 为算法
[!] --string pattern
含有movie的字符数据包统统拒绝
~]#iptables -I OUTPUT -m string --algo bm --string 'movie' -j REJECT
~]#iptables -I OUTPUT -m string --algo kmp --string 'mp3' -j DROP
4、time扩展
根据报文到达的时间与指定的时间范围进行匹配;
~]# iptables -IINPUT -d 10.76.249.160 -p tcp --dport 80 -m time --timestart 8:00 --timestop18:00 -i REJECT
~]# iptables -I INPUT -d10.10.100.128 -p tcp --dport 80 -m time --timestart 8:00 --timestop 18:00 -iDROP
#从8点到16点 10.76.249.160地址关闭80端口的访问(8-18点关闭web访问功能)
日期
--datestart
--datestop
时间
--timestart
--timestop
月1-31
--monthdays
周几
--weekdays1-7
5、connlimit扩展
根据每客户端IP(也可以是地址块)做并发连接数数量匹配;
单IP并发连接限制
--connlimit-above n:连接的数量大于n
#对于23号端口syn的连接数大于2时拒绝连接
a
~]#iptables -AINPUT -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
--connlimit-upto n: 连接的数量小于等于n
对于23号端口syn的连接数小于2时允许连接
b
iptables -AINPUT -p tcp --syn --dport 23 -m connlimit --connlimit-upto 2 -j ACCEPT
要使用哪个要看默认INPUT配置情况,如果默认为DROP,则使用b;默认为ACCEPT则使用a
6、limit扩展
基于收发报文的速率做检查;
令牌桶过滤器:
汽车有10个座位,刚刚开始可以上去10人(峰值),10分钟后1个下车,这时候可以让1个上车…;如果N个10分钟后,所有人都下车了,而没有人上车,可以一下子让10个人同时上车,但是不能超过10个
--limit rate[/second|/minute|/hour|/day]
--limit-burst number
#限制ping数量为峰值为5个,达到速率峰值后之后每秒只能允许2个ping请求(1分钟不能超过30个)
~]# iptables -AINPUT -d 10.76.249.160 -p icmp --icmp-type 8 -m limit --limit-burst 5 --limit30/minute -j ACCEPT
7、state扩展
根据连接追踪机制检查连接的状态;
记录数量定义
调整连接追踪功能所能够容纳的最大连接数量:
/proc/sys/net/nf_conntrack_max
记录的位置
已经追踪到并记录下的连接:
/proc/net/nf_conntrack
不同协议或连接类型追的时长:
/proc/sys/net/netfilter/
连接追踪表的相关设置
iptables的链接跟踪表最大容量为/proc/sys/net/ipv4/ip_conntrack_max,链接碰到各种状态的超时后就会从表中删除。
所以解決方法一般有两个:
(1) 加大ip_conntrack_max 值
vi /etc/sysctl.conf
net.ipv4.ip_conntrack_max = 393216
net.ipv4.netfilter.ip_conntrack_max = 393216
(2): 降低ip_conntrack timeout时间
vi /etc/sysctl.conf
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established= 300
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait= 120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait= 60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait= 120
可追踪的连接状态:
NEW:新发出的请求;连接追踪模板中不存此连接相关的信息条目,因此,将其识别为第一次发出的请求;
ESTABLISHED:NEW状态之后,连接追踪模板中为其建立的条目失效之前期间内所进行的通信的状态;
RELATED:相关的连接;如ftp协议的命令连接与数据连接之间的关系;
INVALIED:无法识别的连接;
UNTRACKED
--state STATE1,STATE2,...
#连接追踪,只允许访问22号端口,新建连接,已建立连接状态的连接通信
~]# iptables -IINPUT -d 10.76.249.160 -p tcp --dport22 -m state --state NEW,ESTABLISHED -jACCEPT
#连接追踪,从本机出去的22号端口状态只能是已经建立连接状态的连接
~]# iptables -IOUTPUT -s 10.76.249.160 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
#更优化的写法,只要是通过外面连接进来的,必然是已经连接状态,不会有新的连接状态的情况,所以只允许建立连接状态的主机连接
~]# iptables -IOUTPUT -m state --state ESTABLISHED -j ACCEPT
#如果是已建立连接状态的连接,入站时直接匹配已建立连接状态的链接,而不必一直扫描多个规则
~]# iptables -IINPUT -m state --state ESTABLISHED -j ACCEPT
#多端口设置允许建立新连接
~]# iptables -IINPUT 2 -d 10.76.249.160 -p tcp -m multiport --dports 22,80 -m state --stateNEW -j ACCEPT
日志记录功能
日志等级:debug,info, notice, warning, warn, err, error, crit, alert, emerg and panic
日志记录功能打开后,日志信息增长比较快,如果非必需应将日志记录功能关闭,需要额外注意。
指定等级
iptables -AFORWARD -p tcp -j LOG --log-level debug
指定记录”关卡”(五链)
]#iptables -A INPUT -p tcp -j LOG--log-prefix "INPUT packets-->进入数据包:"
]#iptables -A OUTPUT -p tcp -j LOG--log-prefix "OUTPUT packets-->流出数据包:"
[root@node1log]# cat /var/log/messages
Oct 20 23:04:43 node1 kernel: OUTPUTpackets-->流出数据IN= OUT=eno16777736 SRC=10.10.100.128DST=10.10.100.1 LEN=2960 TOS=0x10 PREC=0x00 TTL=64 ID=53996 DF PROTO=TCP SPT=22DPT=63819 WINDOW=152 RES=0x00 ACK URGP=0
Oct 20 23:04:43 node1 kernel: INPUTpackets-->进入数据 IN=eno16777736 OUT=MAC=00:0c:29:6b:bb:b2:00:50:56:c0:00:08:08:00 SRC=10.10.100.1 DST=10.10.100.128LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=9782 DF PROTO=TCP SPT=63819 DPT=22WINDOW=969 RES=0x00 ACK URGP=0
保存重载规则
1.保存配置
保存规则至指定文件:
iptables-save> /PATH/TO/SOMEFILE
[root@node1 ~]#pwd
/root
[root@node1 ~]#iptables-save >/root/iptable_rule.save
2.加载配置
从指定文件重载规则:
iptables-restore < /PATH/FROM/SOMEFILE
~]#iptables-restore </root/iptable_rule.save
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
网络防火墙
地址转换
使用前提
内核默认没有打开核心转发功能,需要打开以后才可以使用
echo 1 > /proc/sys/net/ipv4/ip_forward
nat:Network Address Translation,安全性,网络层+传输层
proxy:代理,应用层
nat:
SNAT: 只修改请求报文的源地址;
DNAT:只修改请求报文的目标地址;
nat表:
PREROUTING:DNAT
OUTPUT
POSTROUTING:SNAT
SNAT源地址转换
源地址转换: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
iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to-source 194.236.50.155-194.236.50.160:1024-32000
DNAT目标地址转换
目标地址转换:iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport PORT -j DNAT --to-destination InterSeverIP[:PORT]
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 |
FORWARD 实现转发功能
请求规则
响应规则
打开转发功能:
[root@localhost ~]# sysctl -w net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1 [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward 1 |
ping 外网主机:当数据包到达外网主机后,它需要回应但是发现不是本网段的主机,所以要将数据包发给网关,发现源地址是私有的地址无法转发回来给予丢弃,所以要添加一条路由,将内网的的主机包nat转发
添加路由
~]# route add -net 192.168.20.0/24 gw 10.76.249.160 |
防火墙转发过滤只能通过80,22端口
~]# iptables -P FORWARD DROP #设置默认策略为拒绝(白名单机制)
~]# iptables -I FORWARD -d 192.168.20.2 -p tcp --dport 80 -j ACCEPT
~]# iptables -I FORWARD -s 192.168.20.2 -p tcp --sport 80 -j ACCEPT
优化写法
~]# iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT
~]# iptables -A FORWARD -d 192.168.20.2 -p tcp -m multiport --dports 22,80 -m state --state NEW -j ACCEPT