iptables防火墙 、 filter表控制 、 扩展匹配 、 nat表典型应用
iptables
iptables有多种功能,每一种功能都用一张表来实现
最常用的功能是防火墙和NAT
从RHEL7开始,默认的防火墙为firewalld,但是它的底层仍然调用iptables
安装iptables服务
# 关闭firewalld [root@node1 ~]# systemctl stop firewalld [root@node1 ~]# systemctl disable firewalld # 安装iptables [root@node1 ~]# yum install -y iptables-services.x86_64
iptables的表和链。我们只关心nat表和filter表。filter表是默认的表,它实现防火墙,也就是包过滤的功能。nat表实现网络地址转换。
防火墙filter表
配置iptables时,不指定表,就是使用filter表
配置时不指定规则链,则配置所有链
可以向规则链中加入很多规则,数据包进入该链时,从上向下匹配,一旦匹配就停止,开始应用规则。如果全都不匹配,则应用默认规则
命令选项、链名、目标操作使用大写字母,其他小写
filter中的三条链
INPUT:数据包的目标地址是自己,则进入INPUT链
OUTPUT:数据包的源地址是自己,则进入OUTPUT链
FORWARD:数据包穿过自己,则进入FORWARD链
环境准备
client1:eth0 -> 192.168.4.10/24 网关:192.168.4.11
node1:eth0 -> 192.168.4.11/24,eth1 -> 192.168.2.11/24
server1:eth1 -> 192.168.2.100/24 网关:192.168.2.11
iptables操作
# 查看filter表中的规则。-t指定表名 [root@node1 ~]# iptables -t filter -L # 所有规则链都是空的 Chain INPUT (policy ACCEPT) # INPUT链默认规则是接受 target prot opt source destination Chain FORWARD (policy ACCEPT) # FORWARD链默认规则是接受 target prot opt source destination Chain OUTPUT (policy ACCEPT) # OUTPUT链默认规则是接受 target prot opt source destination [root@node1 ~]# iptables -L # 不指定表名,默认操作filter表 Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination # 起动服务时,iptables将会出现一些默认规则 [root@node1 ~]# systemctl start iptables.service [root@node1 ~]# iptables -L # 默认规则往往不合我们的要求,可以先将所有的规则清空 [root@node1 ~]# iptables -F
iptables的语法
iptables [-t 表名] 选项 [链名] [条件] [-j 满足条件的操作]
示例
可以设置默认拒绝,然后明确允许
也可以设置默认允许,然后明确拒绝
# 向INPUT链追加规则,192.168.4.254发来的包全部接受 # -A是追加,-s是匹配源地址,-j为jump,采取的行为,ACCEPT是接受 [root@node1 ~]# iptables -A INPUT -s 192.168.4.254 -j ACCEPT # 将INPUT链的默认规则改为DROP丢弃。-P设置默认规则 [root@node1 ~]# iptables -P INPUT DROP # 查看INPUT链的规则 [root@node1 ~]# iptables -L INPUT Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- 192.168.4.254 anywhere # 在192.168.4.10上访问node1,将会被拒绝 [root@client1 ~]# ping -c2 192.168.4.11 [root@client1 ~]# ssh 192.168.4.11 # 注意,数据通信多数是双向的。现在node1也不能与192.168.4.254以外的其他机器通信,因为数据回不来。 [root@node1 ~]# ping -c2 192.168.4.10 # 失败 # 允许192.168.4.0网络的主机ssh连接node1 # -I是插入到INPUT链的第1个位置。-p指定协议,--dport指定目标端口号。-j是执行的操作 [root@node1 ~]# iptables -I INPUT 1 -s 192.168.4.0/24 -p tcp --dport 22 -j ACCEPT # 查看规则 [root@node1 ~]# iptables -L INPUT Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.4.0/24 anywhere tcp dpt:ssh ACCEPT all -- 192.168.4.254 anywhere # 查看规则,n是指用数字来表示端口号、主机等 [root@node1 ~]# iptables -nL INPUT Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.4.0/24 0.0.0.0/0 tcp dpt:22 ACCEPT all -- 192.168.4.254 0.0.0.0/0 # 测试,192.168.4.10已经可以ssh到node1,但是ping不通,因为只允许了ssh # 配置任何地址访问node1的80端口,即http协议,都接受 [root@node1 ~]# yum install -y httpd [root@node1 ~]# systemctl start httpd # 不指定源,就是任何源 [root@node1 ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT [root@node1 ~]# iptables -nL INPUT Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.4.0/24 0.0.0.0/0 tcp dpt:22 ACCEPT all -- 192.168.4.254 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 # 拒绝192.168.4.254 ping node1。以下写法不会生效,因为插入到了规则尾部,在它上面已经存在允许192.168.4.254通信的规则了。 # icmp就是ping命令底层用到的协议,叫Internet控制消息协议 [root@node1 ~]# iptables -A INPUT -s 192.168.4.254 -p icmp -j REJECT [root@node1 ~]# iptables -nL INPUT Chain INPUT (policy DROP) target prot opt source destination ACCEPT tcp -- 192.168.4.0/24 0.0.0.0/0 tcp dpt:22 ACCEPT all -- 192.168.4.254 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 REJECT icmp -- 192.168.4.254 0.0.0.0/0 reject-with icmp-port-unreachable # 查看规则的行号 [root@node1 ~]# iptables -nL INPUT --line-numbers Chain INPUT (policy DROP) num target prot opt source destination 1 ACCEPT tcp -- 192.168.4.0/24 0.0.0.0/0 tcp dpt:22 2 ACCEPT all -- 192.168.4.254 0.0.0.0/0 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 4 REJECT icmp -- 192.168.4.254 0.0.0.0/0 reject-with icmp-port-unreachable # 删除第4条规则 [root@node1 ~]# iptables -D INPUT 4 [root@node1 ~]# iptables -nL INPUT --line-numbers Chain INPUT (policy DROP) num target prot opt source destination 1 ACCEPT tcp -- 192.168.4.0/24 0.0.0.0/0 tcp dpt:22 2 ACCEPT all -- 192.168.4.254 0.0.0.0/0 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 # 拒绝192.168.4.254 ping node1。-I不指定位置,默认插到最上面 [root@node1 ~]# iptables -I INPUT -s 192.168.4.254 -p icmp -j REJECT [root@node1 ~]# iptables -nL INPUT --line-numbers Chain INPUT (policy DROP) num target prot opt source destination 1 REJECT icmp -- 192.168.4.254 0.0.0.0/0 reject-with icmp-port-unreachable 2 ACCEPT tcp -- 192.168.4.0/24 0.0.0.0/0 tcp dpt:22 3 ACCEPT all -- 192.168.4.254 0.0.0.0/0 4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 # DROP是直接丢弃,REJECT是明确拒绝。 # 保存规则。不保存规则,重启iptables服务,自定义规则将消失 [root@node1 ~]# service iptables save
验证FORWARD链
准备环境
# 为node1的eth1配置ip地址 [root@node1 ~]# nmcli connection modify eth1 ipv4.method manual ipv4.addresses 192.168.2.11/24 [root@node1 ~]# nmcli connection down eth1 [root@node1 ~]# nmcli connection up eth1 # 配置server1 [root@localhost ~]# hostnamectl set-hostname server1 [root@localhost ~]# nmcli connection modify eth1 ipv4.method manual ipv4.addresses 192.168.2.100/24 [root@localhost ~]# nmcli connection down eth1 [root@localhost ~]# nmcli connection up eth1 [root@localhost ~]# echo a | passwd --stdin root
为192.168.4.10和192.168.2.100配置网关
[root@client1 ~]# nmcli connection modify eth0 ipv4.gateway 192.168.4.11 [root@client1 ~]# ifdown eth0; ifup eth0 [root@server1 ~]# nmcli connection modify eth1 ipv4.gateway 192.168.2.11 [root@server1 ~]# ifdown eth1; ifup eth1 # 在中间节点node1上打开路由转发功能 [root@node1 ~]# sysctl -a | grep ip_forward [root@node1 ~]# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf [root@node1 ~]# sysctl -p # client和server已经可以通信 [root@client1 ~]# ping -c2 192.168.2.100
在server1上安装httpd服务
[root@server1 ~]# yum install -y httpd [root@server1 ~]# systemctl start httpd # 在客户端访问web服务,可以访问 [root@client1 ~]# curl http://192.168.2.100/
配置FORWARD链
要求:在node1上配置防火墙,保护server1
默认拒绝所有数据包通过
从server1发往client1的包全部允许
从client1到server1,允许icmp,允许22、80、443端口通过
# 默认拒绝所有数据包通过,此时client1和server1完全不通 [root@node1 ~]# iptables -P FORWARD DROP # 源地址是192.168.2.0/24,目标地址是192.168.4.0/24的包,放行 [root@node1 ~]# iptables -A FORWARD -s 192.168.2.0/24 -d 192.168.4.0/24 -j ACCEPT # 从client1到server1,允许icmp [root@node1 ~]# iptables -A FORWARD -s 192.168.4.0/24 -d 192.168.2.0/24 -p icmp -j ACCEPT # client1和server1已经可以ping通了 [root@client1 ~]# ping -c2 192.168.2.100 # 允许从client1访问server1的22、80、443,100-120端口范围 # -m是引入扩展模块,multiport多端口 [root@node1 ~]# iptables -A FORWARD -p tcp -m multiport --dport 22,80,443,100:120 -s 192.168.4.0/24 -j ACCEPT # 现在从client1到server1的ssh、http都可以放行了 [root@client1 ~]# ssh 192.168.2.100 [root@client1 ~]# curl http://192.168.2.100/ # 拒绝192.168.4.10-192.168.4.20访问192.168.2.50-192.168.2.150 # -m是引入扩展模块,src-range是源地址范围,dst-range目标地址范围 [root@node1 ~]# iptables -I FORWARD -m iprange --src-range 192.168.4.10-192.168.4.20 --dst-range 192.168.2.50-192.168.2.150 -j REJECT
NAT
NAT:网络地址翻译、网络地址转换
NAT技术产生,主要是解决IPV4地址不够用。
NAT一般用于将私有地址转成全球唯一的公有地址。
私有地址:
A类:10.x.x.x
B类:172.16.x.x-172.31.x.x
C类:192.168.x.x
私有地址,如果需要访问互联网中的公有地址,进行上网,可以通过NAT技术,将私有地址转成公有地址,再访问外界。
配置SNAT
现在的实验环境,client1可以访问server1,server1看到的是客户端地址是client1的地址。
# 跟踪httpd日志的尾部 [root@server1 ~]# tail -f /var/log/httpd/access_log # 在client上访问server1的web服务 [root@client1 ~]# curl http://192.168.2.100/ # 查看服务器终端的日志,将会显示client1的地址192.168.4.10访问了它 192.168.4.10 - - [13/Oct/2021:17:31:35 +0800] "GET / HTTP/1.1" 403 4897 "-" "curl/7.29.0"
互联网环境下,运营商不允许私有地址出现在互联网上,发现有这样的数据,就直接丢弃。所以,私有地址发往互联网时,需要用NAT转换成公有地址,也叫合法地址。
在我们的练习环境下,在node1上配置NAT,当client1访问server1时,将client1的地址转换成server1的192.168.2.x再发给server1。因为数据包的源地址改变了,所以叫SNAT,S即Source。
# 向nat表中的POSTROUTING链添加规则。将源地址192.168.4.0/24转换成它外网卡地址。 [root@node1 ~]# iptables -t nat -A POSTROUTING -s 192.168.4.0/24 -j MASQUERADE [root@node1 ~]# iptables -t nat -nL # client1再次访问server1时,server1上的日志将会显示node1的192.168.2.11访问 [root@server1 ~]# tail -f /var/log/httpd/access_log 192.168.2.11 - - [13/Oct/2021:17:45:07 +0800] "GET / HTTP/1.1" 403 4897 "-" "curl/7.29.0"