一. 防火墙概述 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