在生产实践过程中,为了保证生产安全,通常需要进行数据加密,例如通过网络层面上将应用隔离成内网和公网应用,内网再分成生产、测试、开发、DMZ等区域,然后进行不同的策略更改,例如将重要应用添加防火墙,从物理层面看,有如下两种:
硬件防火墙:在硬件级别实现部分防火墙功能,另一部分功能基于软件实现,性能高,成本高,例如Radware公司的WAF
软件防火墙:应用软件处理逻辑运行于通用硬件平台之上的防火墙,性能低,成本低,例如微软自带的防火墙。
netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)等功能,在RedHat 6 系列及以下中作为内核层的防火墙,在在RedHat 7系列中采用firewall 进行替代,但同时保留iptables功能。
在说明iptables 功能作用前,我们先看下正常情况下用户流量访问经过iptables时,有哪些环节,针对每个环节我们再细说。
根据上图,我们能够归纳出常用场景中,网络流量流向:
到本机某进程的走向:PREROUTING –> INPUT->WEB->OUTPUT –> POSTROUTING
由本机转发的走向:PREROUTING –> FORWARD –> POSTROUTING
由本机的某进程发出走向:OUTPUT –> POSTROUTING
这就是我们日常提到的IPTABLES 实际控制的“链”路,其工作原理就是在这五条链路 设置规则(rules),规则其实就是网络管理员预定义的条件,规则一般的定义为”如果数据包头符合这样的条件,就这样处理这个数据包”。规则存储在内核空间的信息包过滤表中,这些规则分别指定了源地址、目的地址、传输协议(如TCP、UDP、ICMP)和服务类型(如HTTP、FTP和SMTP)等。当数据包与规则匹配时,iptables就根据规则所定义的方法来处理这些数据包,如放行(accept)、拒绝(reject)和丢弃(drop)等。配置防火墙的主要工作就是添加、修改和删除这些规则。
那么规则又有哪些呢?这五条链路分别又可以设置什么呢?
iptables把相同规则进行分类,集合成一个大类,也就是我们所说的“表”,包括我们自定义的规则,也是对这些表进行操作,通常我们认为有如下四张表:
1.filter表——三个链:INPUT、FORWARD、OUTPUT
作用:过滤数据包 内核模块:iptables_filter.
2.Nat表——三个链:PREROUTING、POSTROUTING、OUTPUT、INPUT(RedHat系列Linux 7 及以上可支持)
作用:用于网络地址转换(IP、端口) 内核模块:iptable_nat
3.Mangle表——五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
作用:修改数据包的服务类型、TTL、并且可以配置路由实现QOS内核模块:iptable_mangle(所有链路都可以使用)
4.Raw表——两个链:OUTPUT、PREROUTING
作用:决定数据包是否被状态跟踪机制处理 内核模块:iptable_raw
可以明显看出,并不是所有规则表都可以作用于某一条链路,唯一一个例如就是OUTPUT 链,它作为Web 应用最后的一套防线。
当这些规则表全部在一个链路上时,并不是满足先后设定顺序限制性原则,而是按照如下顺序,进行先后执行:
raw –> mangle –> nat –> filter
上面规则十分重要,这将是下面我们执行设定规则时所依据参考的。
看完前两步,大家可能还没感觉到iptables 作用在哪,其实netfilter才是防火墙真正的安全框架(framework),netfilter位于内核空间,完成封包过滤、封包重定向和网络地址转换(NAT)等功能,用户通过iptables这个功能代理,将用户数据按照设定网络规则链表送进安全框架,从而起到软件防火墙功能。
命令格式: iptables [-t 表名] 命令选项 [链名] [条件匹配] [-j 目标动作或跳转]
iptables v1.4.21 Usage: iptables -[ACD] chain rule-specification [options] iptables -I chain [rulenum] rule-specification [options] iptables -R chain rulenum rule-specification [options] iptables -D chain rulenum [options] iptables -[LS] [chain [rulenum]] [options] iptables -[FZ] [chain] [options] iptables -[NX] chain iptables -E old-chain-name new-chain-name iptables -P chain target [options] iptables -h (print this help information) Commands: Either long or short options are allowed. --append -A chain Append to chain --check -C chain Check for the existence of a rule --delete -D chain Delete matching rule from chain --delete -D chain rulenum Delete rule rulenum (1 = first) from chain --insert -I chain [rulenum] Insert in chain as rulenum (default 1=first) --replace -R chain rulenum Replace rule rulenum (1 = first) in chain --list -L [chain [rulenum]] List the rules in a chain or all chains --list-rules -S [chain [rulenum]] Print the rules in a chain or all chains --flush -F [chain] Delete all rules in chain or all chains --zero -Z [chain [rulenum]] Zero counters in chain or all chains --new -N chain Create a new user-defined chain --delete-chain -X [chain] Delete a user-defined chain --policy -P chain target Change policy on chain to target --rename-chain -E old-chain new-chain Change chain name, (moving any references) Options: --ipv4 -4 Nothing (line is ignored by ip6tables-restore) --ipv6 -6 Error (line is ignored by iptables-restore) [!] --protocol -p proto protocol: by number or name, eg. `tcp' [!] --source -s address[/mask][...] source specification [!] --destination -d address[/mask][...] destination specification [!] --in-interface -i input name[+] network interface name ([+] for wildcard) --jump -j target target for rule (may load target extension) --goto -g chain jump to chain with no return --match -m match extended match (may load extension) --numeric -n numeric output of addresses and ports [!] --out-interface -o output name[+] network interface name ([+] for wildcard) --table -t table table to manipulate (default: `filter') --verbose -v verbose mode --wait -w [seconds] maximum wait to acquire xtables lock before give up --wait-interval -W [usecs] wait time to try to acquire xtables lock default is 1 second --line-numbers print line numbers when listing --exact -x expand numbers (display exact values) [!] --fragment -f match second or further fragments only --modprobe=<command> try to insert modules using this command --set-counters PKTS BYTES set the counter during insert/append [!] --version -V print package version.
上面列举了iptables 所有参数,但实际上我们常用到其实没有这么多,主要就这几个常见:
command 选项 -A 添加防火墙规则 -D 删除防火墙规则 -I 插入防火墙规则 -F 清空防火墙规则 -L 列出添加防火墙规则 -R 替换防火墙规则 -Z 清空防火墙数据表统计信息 -P 设置链默认规则 parametes 选项 -p 协议(protocol) # 指定规则的协议,如tcp, udp, icmp等,可以使用all来指定所有协议。 # 如果不指定-p参数,则默认是all值。这并不明智,请总是明确指定协议名称。 # 可以使用协议名(如tcp),或者是协议值(比如6代表tcp)来指定协议。映射关系请查看/etc/protocols # 还可以使用–protocol参数代替-p参数 -s 源地址(source) # 指定数据包的源地址 # 参数可以使IP地址、网络地址、主机名 # 例如:-s 192.168.31.101指定IP地址 # 例如:-s 192.168.31.10/24指定网络地址 # 如果不指定-s参数,就代表所有地址 -d 目的地址(destination) # 指定目的地址 # 参数和-s相同 # 还可以使用–dst或者–destination -j 执行目标(jump to target) # 指定了当与规则(Rule)匹配时如何处理数据包 # 可能的值是ACCEPT, DROP, QUEUE, RETURN,MASQUERADE # 还可以指定其他链(Chain)作为目标 # 注:MASQUERADE,地址伪装,算是snat中的一种特例,可以实现自动化的snat -i 输入接口(input interface) # 指定了要处理来自哪个接口的数据包 # 这些数据包即将进入INPUT, FORWARD, PREROUTE链 # 例如:-i eth0指定了要处理经由eth0进入的数据包 # 如果不指定-i参数,那么将处理进入所有接口的数据包 # 如果出现! -i eth0,那么将处理所有经由eth0以外的接口进入的数据包 # 如果出现-i eth+,那么将处理所有经由eth开头的接口进入的数据包 -o 输出(out interface)指定了数据包由哪个接口输出 # 这些数据包即将进入FORWARD, OUTPUT, POSTROUTING链 # 如果不指定-o选项,那么系统上的所有接口都可以作为输出接口 # 如果出现! -o eth0,那么将从eth0以外的接口输出 # 如果出现-i eth+,那么将仅从eth开头的接口输出 –sport 源端口(source port)针对 -p tcp 或者 -p udp # 缺省情况下,将匹配所有端口 # 可以指定端口号或者端口名称,例如”–sport 22″与”–sport ssh”。 # 如”–sport 22:100″ –-dport 目的端口(destination port)针对-p tcp 或者 -p udp # 参数和–sport类似
下面就实际使用情况举例:
[root@test01 ~]# rpm -qa|grep iptables iptables-1.4.21-33.el7.x86_64
[root@test01 ~]# iptables -nvL Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 372 26903 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 130 25795 INPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0 130 25795 INPUT_ZONES_SOURCE all -- * * 0.0.0.0/0 0.0.0.0/0 130 25795 INPUT_ZONES all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID 128 25691 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
[root@test01 ~]# iptables-save # Generated by iptables-save v1.4.21 on Mon Jul 11 01:38:27 2022 *nat :PREROUTING ACCEPT [132:25859] :INPUT ACCEPT [2:104] :OUTPUT ACCEPT [8:500] :POSTROUTING ACCEPT [8:500] :OUTPUT_direct - [0:0] :POSTROUTING_ZONES - [0:0] :POSTROUTING_ZONES_SOURCE - [0:0] :POSTROUTING_direct - [0:0] :POST_public - [0:0] :POST_public_allow - [0:0] :POST_public_deny - [0:0] :POST_public_log - [0:0] :PREROUTING_ZONES - [0:0] :PREROUTING_ZONES_SOURCE - [0:0] :PREROUTING_direct - [0:0] :PRE_public - [0:0] :PRE_public_allow - [0:0] :PRE_public_deny - [0:0] :PRE_public_log - [0:0]
备份到/tmp/test.txt
[root@test01 ~]# iptables-save > /tmp/test.txt [root@test01 ~]# cat /tmp/test.txt # Generated by iptables-save v1.4.21 on Mon Jul 11 01:39:19 2022 *nat :PREROUTING ACCEPT [132:25859] :INPUT ACCEPT [2:104] :OUTPUT ACCEPT [8:500] :POSTROUTING ACCEPT [8:500] :OUTPUT_direct - [0:0] :POSTROUTING_ZONES - [0:0] :POSTROUTING_ZONES_SOURCE - [0:0] :POSTROUTING_direct - [0:0] :POST_public - [0:0] :POST_public_allow - [0:0] :POST_public_deny - [0:0] :POST_public_log - [0:0] :PREROUTING_ZONES - [0:0] :PREROUTING_ZONES_SOURCE - [0:0] :PREROUTING_direct - [0:0] :PRE_public - [0:0] :PRE_public_allow - [0:0] :PRE_public_deny - [0:0] :PRE_public_log - [0:0]
从备份文件还原回来
注意,这里导入的文件必须是使用 iptables-save工具导出来的才可以。
[root@test01 ~]# iptables-restore < /tmp/test.txt
ping
通iptables -I INPUT -p icmp -j REJECT
iptables -A FORWARD -s 192.168.31.100 -j REJECT
iptables -A FORWARD -s 192.168.31.0/24 -j ACCEPT
iptables -A INPUT -i eth1 -s 192.168.31.0/16 -j DROP
iptables -A INPUT -i eth1 -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-ports 8080
说明:这里需要开启NAT功能,否则可能失败,实际中用的比较少,端口转发一般采用中间件nginx等,这样性能损耗会比较少。
echo 1 > /proc/sys/net/ipv4/ip_forward
隐藏网内主机的IP地址,共享公网IP,访问互联网
iptables -t nat -A POSTROUTING -s 192.168.31.0/24 -j SNAT --to-source 公网IP
反过来,将访问的IP 映射成其它IP
iptables -t nat -I PREROUTING -d 访问IP -p tcp --dport 访问端口 -j DNAT --to-destination 映射IP:端口号
192.168.31.0/16
网段使用SSH远程登录防火墙主机,生产中一般采用jumpserver等堡垒机,这里是做演示。iptables -A INPUT -p tcp --dport 22 -s 192.168.31.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
说明:使用“!”可以将条件取反,从而限制源IP。
iptables -A INPUT -p tcp -s !192.168.31.0/16 --dport 22 -j DROP
iptables -A INPUT -p tcp --dport 20:1024 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 20:1024 -j ACCEPT
iptables -I INPUT -p tcp -m multiport --dport 20,80,110,1250:1280 -j ACCEPT
iptables -A INPUT -p tcp DROP
说明:这里用“-m multiport –dport”来指定目的端口及范围
iptables -A INPUT -p tcp -m state --state NEW -j DROP
iptables -A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
说明:“ESTABLISHED”表示已经响应请求或者已经建立连接的数据包,“RELATED”表示与已建立的连接有相关性的,比如FTP数据连接等。
iptables -I INPUT -p tcp -m multiport --dport 20,21,80 ,443-j ACCEPT
iptables -I INPUT -p tcp --dport 20450:20480 -j ACCEPT
iptables -I INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
iptables -P INPUT DROP