一. 防火墙概述
1. 防火墙简介
Linux防火墙全称:netfilter/iptables
netfilter/iptables是unix/Linux(2.4版本内核后)自带的一款优秀且免费的基于包过滤的防火墙工具。
netfilter组件也称为内核空间(kernelspace),是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集。
iptables是一种组件工具,也称为用户空间(userspace),它使插入、修改和除去信息包过滤表中的规则变得容易。
2. 包过滤防火墙
在网络层对数据包进行控制,主要对数据包所使用的协议、端口、源地址、目标地址等参数来进行过滤。
二. iptables基本概念和使用
1. iptables简介
iptables有3个表:
表名: 包过滤filter 网络地址转换nat 数据包打标记mangle
表动作 INPUT PREROUTING PREROUTING
FORWARD POSTROUTING INPUT
OUTPUT OUTPUT FORWARD
OUTPUT
POSTROUTING
2. iptables命令参数
-A 增加一条规则,默认就是在后面增加,append追加
-D 删除
-L 列出规则
-n 以数值显示
-I 在最前面插入规则
-v 显示统计数据,与-L -n一起用,看到的信息更多
-F 清空规则
-t 后接表名
-P policy,默认策略
-p 后接协议名 tcp udp icmp
--dport 目标端口
--sport 源端口
-d 目标地址
-s 源地址
-i 接网卡接口, 进入的网卡接口
-o 接网卡接口, 出去的网卡接口
-j 后接动作
动作的分类
ACCEPT 接收数据包
DROP 丢弃数据包
REJECT 拒绝数据包,和DROP的区别就是REJECT会返回错误信息,DROP不会
MASQUEREAD IP地址伪装,使用NAT转换成外网IP,可以PPP拔号(外网IP不固定情况)
SNAT 源地址转换,它与MASQUEREAD的区别是SNAT是接一个固定IP
DNAT 目标地址转换
LOG 记录日志
iptables -A参数 -p 协议 -j 动作
3. 查看配置规则
iptables -n -v -L --line-number -t filter
iptables -n -v -L --line-number -t nat
iptables -n -v -L --line-number -t mangle
--line-number 可以简写成 --line
如果执行iptables命令时不接 -t 表名,防火阅默认使用filter表
参数说明:
-n ip地址以数值显示
-v 详细信息
-L --list,列表
--line-number 规则的行号
--line
-t 表,表有:filter、nat、mangle三个表
4. 添加规则
-A 追加规则
-I 在最前面插入
例:对ping的控制
ICMP协议传输过程是双向的,可以对其input或ouput都可以控制
# iptables -A INPUT -p icmp -j REJECT --可以不加-t filter,默认就是对此表进行操作
# iptables -t filter -A INPUT -p icmp -j REJECT --拒绝ping,但别人ping你有返回信息,会告诉他你拒绝了
# iptables -t filter -A OUTPUT -p icmp -j REJECT --拒绝ping,但你ping出去时会返回信息,会告诉你拒绝ping
# iptables -t filter -A INPUT -p icmp -j DROP --拒绝ping,无论是你ping出去,还是别人ping进来都没有返回信息
# iptables -t filter -A OUTPUT -p icmp -j DROP --拒绝ping
--以上的操作没有写针对谁来控制,默认是所有人
# iptables -t filter -A INPUT -p icmp -s 192.168.1.0/24 -j DROP
# iptables -t filter -A OUTPUT -p icmp -d 192.168.1.0/24 -j DROP
--这两条其中任意一条都是可以控制192.168.1.0/24这个网段ping不通本机
只允许 192.168.1.70 ping本地,其它都拒绝
# iptables -t filter -A INPUT -p icmp -j REJECT
# iptables -t filter -A INPUT -s 192.168.1.70 -p icmp -j ACCEPT
--错误写法,因这里是写先拒绝所有,再允许192.168.1.79ping,这是错误的
# iptables -t filter -A INPUT -s 192.168.1.70 -p icmp -j ACCEPT
# iptables -t filter -A INPUT -p icmp -j REJECT
--正确写法,要先允许谁,再拒绝所有
--如果要把一条规则加到前面,使用 -I参数
# iptables -t filter -A INPUT -p icmp -j REJECT
# iptables -t filter -I INPUT -s 192.168.1.70 -p icmp -j ACCEPT
--正确写法
# iptables -t filter -I INPUT 2 -s 192.168.1.36 -p icmp -j ACCEPT
--把这一条加为第2条(指定数字为第几条)
------------------------------------------------
规则就是一个访问控制列表(ACL),读取的顺序是从上往下一条一条匹配,匹配一条就不继续往下匹配,所以正确写法应该是把刚才允许192.168.1.70的写到最前面
5. 删除规则
方法一:
# iptables -t filter -D INPUT -s 192.168.1.35 -p icmp -j ACCEPT
--加的时候怎么写,删除时就要怎么写 A 参数换成 D就可以
方法二;
# iptables -L -n --line
# iptables -D INPUT 2
--在规则比较多或者不好写规则的情况下,可以先用--line或者--line-number列出行号,再用行号删除
方法三:
# iptables -t filter -F
--直接清空filter表的所有规则
6. 修改规则(用的少)
将第三行规则改为ACCEPT
# iptables -R INPUT 3 -j ACCEPT
7. 规则的保存与还原
# /etc/init.d/iptables save --这样是默认保存到/etc/sysconfig/iptables
# iptables-save > /etc/sysconfig/iptables --将当前规则保存到这个文件,文件可以自定义
# iptables -F
--清空filter表,如果别的表也要清空的话,就加-t 表名都清一次
# iptables-restore < /etc/sysconfig/iptables --把保存的规则还原回去
重启iptables服务,会加载/etc/sysconfig/iptables,
8. 修改默认策略
# iptables -P INPUT DROP --INPUT键默认策略改为DROP,改回来把DROP换成ACCEPT就行了
# iptables -P OUTPUT DROP --OUTPUT键默认策略改为DROP
下面两条定义允许ssh进来
# iptables -A INPUT -p tcp -s 192.168.1.70 --dport 22 -j ACCEPT
进来 协议 从哪来 连接本机的22端口 接受
下面两条定义允许ssh出去
# iptables -A OUTPUT -p tcp -d 192.168.1.70 --sport 22 -j ACCEPT
出去 协议 到哪去 本机的22端口出去 接受
示例:在上例的基础上允许ping自己的IP,本地回环127.0.0.1和192.168.1.151
下面两条自己ping通自己
# iptables -A INPUT -i lo -p icmp -j ACCEPT
# iptables -A OUTPUT -o lo -p icmp -j ACCEPT
下面两条定义此服务器和70这台机器可以互ping
# iptables -A INPUT -p icmp -s 192.168.1.70 -j ACCEPT
# iptables -A OUTPUT -p icmp -d 192.168.1.70 -j ACCEPT
示例:在上面的基础上再加上只允许192.168.1.0/24这个网段访问你的httpd服务
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -d 192.168.1.0/24 --sport 80 -j ACCEPT
示例:在上面的基础上再加上只允许192.168.0.49访问本机的8080端口
![]()
![]()
![]()
![]()
9. 规则特殊的写法
连续端口
iptables -A INPUT -p tcp --dport 1:1000 -j ACCEPT --端口1到1000都接受
iptables -A INPUT -p tcp -m multiport --dport 22,80,110 -j ACCEPT -- m参数,接受多个端口
硬件地址
iptables -A INPUT -m mac --mac-source 00:23:CD:95:DA:0B -p all --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -d 192.168.1.0/24 --sport 80 -j ACCEPT
mac-source不能用于OUTPUT链
10. 示例
示例:FTP
主动 被动
用iptables实现ftp的主动模式能够访问
下面两句实现的是命令端口的连接
# iptables -A INPUT -p tcp --dport 21 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 21 -j ACCEPT
--不加这两句,客户端访问时都不能登录,加了后可以登录,但用ls列出ftp的共享信息的话就发现不行,这是因为20的数据端口还没有做规则
# iptables -A INPUT -p tcp --dport 20 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT
--主动模式是20端口去主动连接,所以上面两条,实现了主动模式的连接,注意:如果使用linux的ftp命令来做实验的话,注意登录后使用passive命令关掉被动模式再试验
被动模式
客户端连接服务器的随机端口
vim /etc/vsftpd/vsftpd.conf
在最后加上
pasv_enable=YES
pasv_min_port=3000
pasv_max_port=3100 --最小端口范围和最大端口范围可以自定义
/etc/init.d/vsftpd restart --重启服务
下面两句就是针对上面的被动配置来设置的允许规则
# iptables -A INPUT -p tcp --dport 3000:3100 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 3000:3100 -j ACCEPT
示例:nfs
--因为nfs用到rpc调用,端口不固定,所以需要把端口给固定起来.nis服务也会用到rpc调用,也需要做端口绑定
vim /etc/sysconfig/nfs --在此文件里加上下面四句
LOCKD_TCPPORT=3000
LOCKD_UDPPORT=3000
MOUNTD_PORT=3001
STATD_PORT=3002
/etc/init.d/nfs restart
/etc/init.d/portmap restart --这里先把默认策略改成ACCEPT,再启动就可以启动起来,然后再把默认策略改回成DROP,再继续做下面的实验
netstat -ntl |grep 300 去查看,看到rpc.的守护进程的端口为自己绑定的端口
iptables -A INPUT -p tcp --dport 3000:3002 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 3000:3002 -j ACCEPT
iptables -A INPUT -p udp --dport 3000:3002 -j ACCEPT
iptables -A OUTPUT -p udp --sport 3000:3002 -j ACCEPT
还要加上2049(nfs)和111(rpcbind)的端口的规则
iptables -A INPUT -p tcp --dport 2049 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 2049 -j ACCEPT
iptables -A INPUT -p udp --dport 2049 -j ACCEPT
iptables -A OUTPUT -p udp --sport 2049 -j ACCEPT
iptables -A INPUT -p tcp --dport 111 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 111 -j ACCEPT
iptables -A INPUT -p udp --dport 111 -j ACCEPT
iptables -A OUTPUT -p udp --sport 111 -j ACCEPT
--现在就可以用另一台机showmount -e 查看并进行挂载了
把上面的3000,3001,3002,2049,111合起来只写4条iptables来做
# iptables -A INPUT -p tcp -m multiport --dport 111,2049,3000,3001,3002 -j ACCEPT
# iptables -A INPUT -p udp -m multiport --dport 111,2049,3000,3001,3002 -j ACCEPT
# iptables -A OUTPUT -p tcp -m multiport --sport 111,2049,3000,3001,3002 -j ACCEPT
# iptables -A OUTPUT -p udp -m multiport --sport 111,2049,3000,3001,3002 -j ACCEPT
mysql
3306
# iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 3306 -d 192.168.1.0/24 -j ACCEPT
rsync
873
# iptables -A INPUT -p tcp --dport 873 -s 192.168.1.0/24 -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 873 -d 192.168.1.0/24 -j ACCEPT
11. FORWARD链的使用
网络拓扑图
内网 iptables网关 外网
1.1.1.128 ------> 1.1.1.1 vmnet1
网关指向
打开ip_forward
192.168.1.70 eth1 <----- 192.168.1.128
网关指向
--注意:模拟上面的环境时,宿主机可以模拟中间的双网卡网关,但不能模拟内网或外网其中一台(原因是宿主机本来就是与虚拟的所有网段是直通的,你如果把它做为内网,则它会直接连接外网而不会走中间的网关)
--所以两种模拟方法:1,宿主机模拟网关,两台虚拟机分别模拟内外网;2,不要宿主机,三台虚拟机来模拟,中间的双网卡网关使用一台双网关的虚拟机模拟,另两台用单两卡来模拟
把gateway加上路由功能
echo "1" > /proc/sys/net/ipv4/ip_forward --临时生效
vim /etc/sysctl.conf --永久生效
net.ipv4.ip_forward = 1
sysctl -p --改完后使用此命令,使之修改永久生效
路由功能加了后,网关都指向了gateway这台物理机,那么 两个网段的这两台机就能互相ping通
# route add default gw 1.1.1.1
# route add default gw 192.168.1.70
问题:这里我们模拟内外网的访问,网关互指,中间网关打开ip_forward,但实际的网络访问环境中,外网客户会把网关指向你公司的网关吗?
--禁止内网128这台和外网128互ping
# iptables -A FORWARD -p icmp -s 1.1.1.128 -j REJECT
--禁止内外网互ping
# iptables -A FORWARD -i vmnet2 -p icmp -j REJECT
或
# iptables -A FORWARD -o eth0 -p icmp -j REJECT
--禁止内网128这台上外网的192.168.1.128这个IP的这一个网站
# iptables -A FORWARD -s 1.1.1.128 -d 192.168.1.128 -p tcp --dport 80 -j REJECT
--这样的做法,如果要做网络管理(控制内部员工上网的行为,用iptables来做就比较繁锁,可以选用squid这种代理网关)
12. NAT表
NAT分为SNAT(源地址转换)和DNAT(目标地址转换)
(1) SNAT 源地址转换
内网多个IP转换成外网IP去连接公网
内网 -------> iptables网关 -------> 外网
1.1.1.128 -------> 1.1.1.1 vmnet1
网关指向
打开ip_forward
192.168.1.70 eth1 <--- 192.168.1.128
去掉网关
把上图先去掉外网上的网关(因为实际情况下,别人公司的外网服务器不可能把网关指向你),去掉这个网关后,内外网就不能通了,要靠NAT
解决方法:在中间网关机器上写规则
# iptables -t nat -A POSTROUTING -p icmp -o eth0 -j SNAT --to-source 192.168.1.70
--内网从eth0出去的icmp协议包都把源地址转换为192.168.1.70
# iptables -t nat -A POSTROUTING -p tcp --dport 80 -o eth0 -j SNAT --to-source 192.168.1.70
--内网从eth0出去的访问80端口的TCP包都把源地址转换为192.168.1.70
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 192.168.1.70
--内网从eth0出去的任何类型的数据包都把源地址转换为192.168.1.70
可以在外网201的/var/log/httpd/access_log里验证得到:在你做NAT之前,靠双网关互指访问网站,它的访问日志里全是你内网的IP。而做了NAT之后,日志里是你公网的IP。
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-- MASQUERADE 是伪装的意思,默认就是自动转换成eth0的外网IP,可以用于外网IP不固定的情况(比如PPP拔号时)
(2) DNAT 目的地址转换
也就是外网是客户端,要访问我们内网的服务器,客户端只是访问外网IP,内网里不同的服务器不同的IP,可以使用DNAT把不同的请求转换到不同的内网服务器
外网 -------> iptables网关 -------> 内网
192.168.1.128 -------> 192.168.1.70 eth0
网关指向
打开ip_forward
1.1.1.1 vmnet1 ---> 1.1.1.128
去掉网关
# iptables -t nat -A PREROUTING -i eth0 -p icmp -j DNAT --to-destination 1.1.1.1
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 1.1.1.128
默认情况web是监听80端口,如果我把web改成监听8080.那么客户端在elinks 1.1.1.128时就访问不到,除非elinks 1.1.1.128:8080
在web服务器上写上一条端口转换的iptables规则,把访问80的转成8080.然后客户端再去elinks 1.1.1.128不用写端口也可以访问成功
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
只允许每组C类IP同时100个http连接
iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 --connlimit-mask 24 -j REJECT
只允许每个IP同时5个80端口转发,超过的丢弃
iptables -I FORWARD -p tcp --syn --dport 80 -m connlimit --connlimit-above 5 -j DROP
限制某IP最多同时100个http连接
iptables -A INPUT -s 222.222.222.222 -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT
限制每IP在一定的时间(比如60秒)内允许新建立最多100个http连接数
iptables -A INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --update --seconds 60 --hitcount 100 -j REJECT
iptables -A INPUT -p tcp --dport 80 -m recent --name BAD_HTTP_ACCESS --set -j ACCEPT