一、四表五链理论
iptables 其实是多个表(table)的容器,每个表里包含不同的链(chain),链里边定义了不同的规则(policy),我们通过定义不同的规则,来控制数据包在防火墙的进出。
1、四表
filter表——过滤数据包
Nat表——用于网络地址转换(IP、端口)
Mangle表——修改数据包的服务类型、TTL、并且可以配置路由实现QOS
Raw表——决定数据包是否被状态跟踪机制处理
2、五链
INPUT链——进来的数据包应用此规则链中的策略
OUTPUT链——外出的数据包应用此规则链中的策略
FORWARD链——转发数据包时应用此规则链中的策略
PREROUTING链——对数据包作路由选择前应用此链中的规则(所有的数据包进来的时侯都先由这个链处理)
POSTROUTING链——对数据包作路由选择后应用此链中的规则(所有的数据包出来的时侯都先由这个链处理)
每一条链其实就是众多规则中的一个检查清单,每一条链中可以有一条或数条规则。当一个数据包到达一个链时,iptables就会从链中第一条规则开始检查,看该数据包是否满足规则所定义的条件。如果满足,系统就会根据 该条规则所定义的方法处理该数据包;否则iptables将继续检查下一条规则,如果该数据包不符合链中任一条规则,iptables就会根据该链预先定义的默认策略来处理数据包。
3、表包含的链路
Filter 是默认的主机防火墙,过滤流入流出主机的数据包。里边包含INPUT,OUTPUT,FOWARD三个链
INPUT 过滤进入主机的数据包
OUTPUT 处理从本机发出去的数据包
FOWARD 处理流经本主机的数据包,与NAT有关系
Filter表是企业实现防火墙功能的重要手段
NAT 负责网络地址转换(来源于目的地址的IP与端口的转换),一般用于局域网的共享上网,与网络交换机acl类似,包含OUTPUT,PREROUTING,POSTROUTING三条链
OUTPUT 改变主机发出去的数据包的目标地址
PREROUTING 数据包到达防火墙时进行分路由判断之前执行的规则,改变数据包的目的地址,目的端口
POSTROUTING 数据包离开防火墙时进行分路由判断之前执行的规则,改变数据包的源的地址,源的端口
mangle 表的系统 chain: PREROUTING,OUTPUT
二、常用设置
1、放行ssh端口:
1 iptables -A INPUT -p tcp –dport 22 -j ACCEPT
2 iptables -A OUTPUT -p tcp –sport 22 -j ACCEPT
注:/etc/rc.d/init.d/iptables save,否则直接执行service iptables restart命令后, 刚才添加的将丢失.
2、解决iptables导致的脑裂问题
1 iptables -A INPUT -i lo -j ACCEPT 允许来自于lo接口的数据包
2 iptables -A OUTPUT -o lo -j ACCEPT 允许向lo接口发送数据包
3 iptables -A INPUT -s 192.168.1.0/24 -d 224.0.0.18 -j ACCEPT #允许组播地址通信
4 iptables -A INPUT -s 192.168.1.0/24 -p vrrp -j ACCEPT #允许VRRP(虚拟路由器冗余协)通信
lo 是 loopback 的缩写,也就是环回地址网卡,linux主机向自身发送数据包时,实际上的数据包是通过虚拟的lo接口来发送接受的,而不会通过你的物理网卡 eth0/eth1。
3、利用iptables将目的地址为192.168.1.189的80端口的数据包更改目的地址为内网机器的IP1.1.1.2,目的端口为80.
iptables -t nat -A PREROUTING -d 192.168.1.189 -p tcp --dport 80 -j DNAT --to-destination 1.1.1.2:80
iptables -t nat -A PREROUTING -d 192.168.1.189 -j DNAT --to-destination 1.1.1.2 将所有流量转发到内网主机
4、iptables命令选项介绍
-t : 对指定的table进行操作。raw,nat,filter,mangle中的一个。默认是filter。
-A :追加防火墙规则
-D :删除规则
-I :插入规则
-F: 清空规则
-L :列出规则
-R:替换规则
-Z:清空计数
-P: 设置链默认规则
-N:创建新链
-X:删除用户自定义引用计数为0的空链
-E:自定义链重命名
-S: 列出选定链的规则
-n # 以数字形式显示地址和端口
-v # 在打印规则时显示详细信息
--line-numbers # 在打印规则时显示规则序号
###反向匹配
# 只需在选项前面使用 ! 即可,如: ! -s 192.168.0.0/16 表示除 192.168/16 外的源 IP
-p:匹配协议 {tcp|udp|udplite|icmp|icmpv6|esp|ah|sctp|mh|all} # 指定匹配的协议,all 表示所有
-s: 匹配源地址 # 源 IP,可以有多个,使用逗号隔开,有多少个地址就有多少条规则
-d:匹配目的地址 目的 IP,可以有多个,使用逗号隔开,有多少个地址就有多少条规则
-i: 匹配入站网卡地址
-o:匹配出站网卡地址
--sport: 匹配源端口
--dport:匹配目的端口
-j :满足某条件时执行什么样的动作。
触发动作:
ACCEPT :允许数据包通过
DROP :丢弃数据包
REJECT :拒绝数据包通过
LOG :将数据包信息记录syslog日志
DNAT :目的地址转换
SNAT :源地址转换
MASQUERADE :地址欺骗
REDIRRECT :重定向
如 # iptables -S -t nat
-S: 列出选定链的规则
,-t : 对指定的table进行操作。raw,nat,filter,mangle中的一个。默认是filter
5、禁止、放行ip
要封停一个IP(-I :插入规则)
iptables -I INPUT -s IP地址 -j DROP
要解封一个IP(-D :删除规则)
iptables -D INPUT -s IP地址 -j DROP
三、iptables脚本
脚本1
# vim iptables.sh
#!/bin/bash
#清空 filter 表和 nat 表
iptables -F
iptables -t nat -F
#关掉 firewalld
systemctl stop firewalld &>/dev/null
systemctl disable firewalld &>/dev/null
#以下两行允许某些调用 localhost 的应用访问
iptables -A INPUT -i lo -j ACCEPT #规则1
iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT #规则2
#以下一行允许从其他地方 ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT #规则3
#以下一行允许从其他主机、网络设备发送 MTU 调整的报文
#在一些情况下,例如通过 IPSec VPN 隧道时,主机的 MTU 需要动态减小
iptables -A INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT #规则4
#以下两行分别允许所有来源访问 TCP 80,443 端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT #规则5
iptables -A INPUT -p tcp --dport 443 -j ACCEPT #规则6
#以下一行允许所有来源访问 UDP 80,443 端口
iptables -A INPUT -p udp -m multiport --dports 80,443 -j ACCEPT #规则7
#以下一行允许 192.168.1.63 来源的 IP 访问 TCP 22 端口(OpenSSH)
iptables -A INPUT -p tcp -s 192.168.1.63 --dport 22 -j ACCEPT #规则8
#以下一行允许 192.168.1.3(发起SSH连接的系统对应网卡的IP) 来源的 IP 访问 TCP 22 端口(OpenSSH)
#如果是在远程终端跑本脚本,最好开启以下一行以防被踢掉
#另一种更加简便的方式:iptables -I INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.1.3 --dport 22 -j ACCEPT #规则9
#以下一行允许 192.168.1.26 来源的 IP 访问 UDP 161 端口(SNMP)
iptables -A INPUT -p udp -s 192.168.1.26 --dport 161 -j ACCEPT #规则10
#配置 NAT
#启用内核路由转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.conf
sysctl -p &>/dev/null
#配置源地址转换 SNAT
#将 192.168.2.0/24 转换成 192.168.1.63
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -j SNAT --to 192.168.1.63 #规则11
#配置目的地址转换 DNAT
#将 192.168.1.63 的 80 端口请求转发到 192.168.2.2 的 80 端口
iptables -t nat -A PREROUTING -d 192.168.1.63 -p tcp --dport 80 -j DNAT --to 192.168.2.2:80 #规则12
我们期望10.0.10.62为用户访问目标,而不是web服务192.168.0.110,但62上是没有web服务的,所以有人访问62的web服务必须将其转换到110上
iptables -t nat -A PREROUTING -d 10.0.10.62 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.110
#以下一行禁止所有其他的进入流量
iptables -A INPUT -j DROP #规则13
#以下一行允许本机响应规则编号为 1-12 的数据包发出
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT #规则14
#以下一行禁止本机主动发出外部连接
iptables -A OUTPUT -j DROP #规则15
#以下一行禁止本机转发数据包
iptables -A FORWARD -j DROP #规则16
#固化 iptables
iptables-save > /etc/sysconfig/iptables
脚本2
#!/bin/bash
#先允许
iptables -P INPUT ACCEPT
#清除规则
iptables -F
#清除用户自定义规则
iptables -X
#清除链的计数器
iptables -Z
#开启回环网络
iptables -A INPUT -i lo -j ACCEPT && iptables -A OUTPUT -o lo -j ACCEPT
#允许ping
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
#允许2-7访问
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 -j ACCEPT
#允许163-168访问22端口(ssh连接)
iptables -A INPUT -p tcp -m iprange --src-range 137.64.70.163-137.64.70.168 --dport 22 -j ACCEPT
#4A地址
iptables -A INPUT -p tcp -m iprange --src-range 137.64.35.151-137.64.35.156 -j ACCEPT
#只允许主机共享rpc服务
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 --dport 111 -j
ACCEPT
#只允许主机访问es
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 --dport 9200 -j ACCEPT
#允许主机访问2375端口
iptables -A INPUT -p tcp -m iprange --src-range 192.168.202.2-192.168.202.7 --dport 2375 -j ACCEPT
#只在164执行
iptables -A INPUT -p tcp -m iprange --src-range 137.64.76.179 --dport 28081 -j ACCEPT
#开发8080端口(只在164执行)
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
#在屏蔽
iptables -P INPUT DROP
#所有出站一律绿灯
iptables -P OUTPUT ACCEPT
#所有转发一律丢弃
iptables -P FORWARD ACCEPT
#保存
iptables-save
四、iptables自动封查IP、解禁ip
iptables是采用数据包过滤机制工作的,所以它会对请求的数据包的包头数据进行分析,并根据我们预先设定的规则进行匹配来决定是否可以进入主机。
脚本1:# more nginx_ip.sh
#!/bin/bash
. /etc/init.d/functions
conut=100
Path=/usr/local/nginx/logs/access.log
function ipt(){
awk '{print $1}'$Path|sort|uniq -c|sort -rn >/tmp/tmp.log
exec < /tmp/tmp.log
while read line
do
ip=echo $line|awk '{print $2}'
if [ echo $line|awk '{print $1}' -ge $conut -a iptables -L -n|grep "$ip"|wc -l -lt 1 ]
then
iptables -I INPUT -s $ip -j DROP
RETVAL=$?
if [ $RETVAL -eq 0 ]
then
action "iptables -I INPUT -s $ip -j DROP" /bin/true
echo "$ip" >>/tmp/ip_$(date +%F).log
else
action "iptables -I INPUT -s $ip -j DROP" /bin/false
fi
fi
done
}
function del(){
[ -f /tmp/ip_$(date +%F -d '-1 day').log ]||{
echo "log is not exist"
exit 1}
exec </tmp/ip_$(date +%F -d '-1 day').log
while read line
do
if [ iptables -L -n|grep "$line"|wc -l -ge 1 ]
then
iptables -D INPUT -s $line -j DROP
fi
done
}
function main(){
flag=0
while true
do
sleep 180
((falg++))
ipt
[ $flag -ge 480 ] && del && flag=0
done
}
main
更好的方法:nginx+lua拦截IP,或者搭建软件防火强的方法。
脚本2:iptables自动屏蔽访问网站频繁的IP
场景:恶意访问,安全防范
1)屏蔽每分钟访问超过200的IP
方法1:根据访问日志(Nginx为例)
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
ABNORMAL_IP=$(tail -n5000 access.log |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}')
#先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
方法2:通过TCP建立的连接
#!/bin/bash
ABNORMAL_IP=$(netstat -an |awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}')
#gsub是将第五列(客户端IP)的冒号和端口去掉
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
2)屏蔽每分钟SSH尝试登录超过10次的IP
方法1:通过lastb获取登录状态:
#!/bin/bash
DATE=$(date +"%a %b %e %H:%M") #星期月天时分 %e单数字时显示7,而%d显示07
ABNORMAL_IP=$(lastb |grep "$DATE" |awk '{a[$3]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
方法2:通过日志获取登录状态
#!/bin/bash
DATE=$(date +"%b %d %H")
ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')"
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -A INPUT -s $IP -j DROP
echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log
fi
done
脚本3:根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
#!/bin/bash
####################################################################################
#根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
####################################################################################
logfile=/data/log/access.log
#显示一分钟前的小时和分钟
d1=`date -d "-1 minute" +%H%M`
d2=`date +%M`
ipt=/sbin/iptables
ips=/tmp/ips.txt
block()
{
#将一分钟前的日志全部过滤出来并提取IP以及统计访问次数
grep '$d1:' $logfile|awk '{print $1}'|sort -n|uniq -c|sort -n > $ips
#利用for循环将次数超过100的IP依次遍历出来并予以封禁
for i in `awk '$1>100 {print $2}' $ips`
do
$ipt -I INPUT -p tcp --dport 80 -s $i -j REJECT
echo "`date +%F-%T` $i" >> /tmp/badip.log
done
}
unblock()
{
#将封禁后所产生的pkts数量小于10的IP依次遍历予以解封
for a in `$ipt -nvL INPUT --line-numbers |grep '0.0.0.0/0'|awk '$2<10 {print $1}'|sort -nr`
do
$ipt -D INPUT $a
done
$ipt -Z
}
#当时间在00分以及30分时执行解封函数
if [ $d2 -eq "00" ] || [ $d2 -eq "30" ]
then
#要先解再封,因为刚刚封禁时产生的pkts数量很少
unblock
block
else
block
fi
五、shell知识补充(while读取文件)
while读取文件的方法
1、管道的方式
cat /tmp/a.log |while read LINE
do
echo $LINE
done
2、重定向的方式(速度较快)
while read LINE
do
echo $LINE
done < /tmp/a.log
3、文件描述符法
exec </tmp/a.log
while read line
do
echo $line
done
https://blog.csdn.net/u011537073/article/details/82685586
https://devopstack.cn/linux/871.html Iptables 限制连接数(如SFTP) 以及 谨防CC/DDOS攻击的配置 ( connlimit模块)