Linux的防火墙iptables与firewalld
iptables相关配置
配置iptables
之前,建议添加一个crontab定时重置iptables,防止将自己阻挡.
建议写入/usr/iptab.sh
,加入crontab
,每个整点执行
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -X
iptables -Z
查看本机关于IPTABLES的设置情况
iptables -L -n
清除原有规则.
不管你在安装linux时是否启动了防火墙,如果你想配置属于自己的防火墙,那就清除现在filter的所有规则. 清除预设表filter中的所有规则链的规则
iptables -F
清除预设表filter中使用者自定链中的规则
iptables -X
保存配置
刚刚配置的重启以后就会丢失,想要保存使用
iptables save
有的可能是iptables-save
这样就写到/etc/sysconfig/iptables
文件里了.
写入后记得把防火墙重起一下,才能起作用.
service iptables restart
设定预设规则
默认的入口,出口,转发策略都是ACCEPT 下面要改变这种规则
iptables 采用黑名单加白名单的方式, 未命中白名单的将采用预设规则
下面操作注意,为避免ssh端口22被拦截,首先添加
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
保证22端口入口畅通,注意如果你的OUTPUT模式设置为DROP(上面已经清空了,默认为ACCEPT),还需要添加
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
保证出口22端口畅通 下面开始折腾吧
1.修改入口流量默认规则为DROP,除非命中用户规则,否则拦截所有入口流量(注意上面一定要排除ssh的端口,否则直接掉线)
iptables -P INPUT DROP
如果你使用了docker,这里好像会对docker的网络造成影响
2.允许所有出口流量(重置iptables时,这其实就是默认的规则)
iptables -P OUTPUT ACCEPT
3.禁止所有转发流量,除了命中用户规则的
iptables -P FORWARD DROP
查看流量统计
iptables -L -vn
iptables -L -vxn
常用端口开启
开启80,443端口,http,https服务
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
开启21端口,ftp服务
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
开启基本端口
允许icmp包通过,也就是允许ping
iptables -A INPUT -p icmp -j ACCEPT
允许loopback!(不然会导致DNS无法正常关闭等问题)
如果未启用此项,常见的fastcgi_pass 127.0.0.1 将会有问题
iptables -A INPUT -i lo -p all -j ACCEPT
iptables 配置实时生效,如果拦截了ssh端口,将立即掉线!
无论iptabes启动与否,ps -ef都不会看到iptables的进程,这是因为iptables是由内核来实现的,也就是说iptables的功能已经融入到内核里面了
iptables只是一个工具,将IP规则写入内核,让内核去处理。所以iptables只有在加规则的时候才会看得到进程,加完了就退出了
iptables并不是一个普通的daemon,只是一个普通的工具,添加一些规则到kernel的filter列表里面。
systemctl stop iptables
也与进程无关,他只是执行了/usr/libexec/iptables/iptables.init stop
将规则从内核清除到存到文件.
IP 拦截
拦截一个IP
iptables -I INPUT -s 1.2.3.4 -j DROP
解封此IP
iptables -D INPUT -s 1.2.3.4 -j DROP
参数-I是表示Insert(添加),-D表示Delete(删除)
INPUT表示入站,DROP表示放弃连接
IP段
192.168.1.x 可以写 192.168.1.0/24
192.168.x.x 可以写 192.168.0.0/16
192.x.x.x 可以写 192.0.0.0/8
iptables -I INPUT -s 112.198.0.0/16 -j DROP
iptables 过滤大量IP地址任然是挨个遍历,如需拦截数以万计的IP地址,需使用
ipset
,能获取最佳性能.yum info ipset -y
安装ipset
iptables -A INPUT -p tcp --dport 8000 -s 1.2.3.4 -j ACCEPT
iptables -A INPUT -p tcp --dport 8000 -j DROP
iptables -D INPUT 2
https://stackoverflow.com/questions/10197405/how-can-i-remove-specific-rules-from-iptables
路由黑洞
linux 黑洞路由命令
net-tool 用法
route add -host 10.10.0.1 127.0.0.1 -blackhole
iprouter2 用法
ip route add blackhole 192.168.32.128/32
中国 ip 段获取
wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > ./ignore.list
示例:拦截ssh登录失败次数过多的IP
lastb -i | awk '{print $3}' | sort | uniq -c | sort -nr | head -50 | awk '{print "ip route add blackhole ", $2}' | sort -n | uniq | sh
前面是找出登录失败过多的IP,后面使用awk拼接 ip route 命令并执行
使用 netstat -nr
或者 route -n
可以验证,这两个命令都可以查看 Kernel IP routing table
ip route add
的好处是会自动判断是否重复给出RTNETLINK answers: File exists
,但不影响未重复的添加。比起iptables也更简单
可以存储为文件,定时执行
/home/block.sh
lastb -i | awk '{print $3}' | sort | uniq -c | sort -nr | head -50 | awk '{print "/usr/sbin/ip route add blackhole ", $2}' | sort -n | uniq | sh
crontab -e
每小时执行
0 * * * * sh /home/block.sh &>/dev/null
netstat -anltp | awk '{print $5}' | grep -E -o "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 0.0 | sort | uniq -c | sort -nr | head -10
netstat -anltp | awk '{print $5}' | grep -E -o "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 0.0 | sort | uniq -c | sort -nr | head -10 | awk '{print "ip route add blackhole ", $2 }'
查看路由黑洞信息
ip route show
删除黑洞
ip route del 192.168.0.195
ip route show
批量删除符合规则的IP ip route show | grep "0.0.0 " | awk {'print "ip route del ",$2'} | sh
清除所有blackhole的规则 ip route show | grep blackhole | grep -E -o "([0-9]{1,3}\.){3}[0-9]{1,3}" | awk {'print "ip route del ",$1'} | sh
添加的IP也可以是一个网段 192.168.0.195/32
路由黑洞的工作原理就是将攻击者的IP引导到一个不存在的地址,从而直接丢弃。 当开启路由黑洞以后,攻击者到你服务器的TCP握手将不能成功,因为你的服务器根本不会响应SYN+ACK包,但是攻击者的SYN还是发过来了,这个阻止不了。所有UDP的包也不能阻止接受,但是服务器不会发送任何响应给攻击者。简单说就是攻击你没法阻止,但可以不回应。
路由黑洞 比 iptables 更节省cpu
无论是iptables还是路由黑洞,都是依次遍历查找,效率始终不如ipset,但ipset一个set最大支持65535个ip
iptable 与 route 区别
https://superuser.com/questions/419659/iptables-vs-route
http://www.adminsehow.com/2011/09/iptables-packet-traverse-map/
参考 http://ximunix.blogspot.com/2015/02/howto-drop-or-block-attackers-ip.html
IPSET
创建一个ipset
ipset create xxx hash:net
(也可以是hash:ip ,这指的是单个ip,xxx是ipset名称)
ipset默认可以存储65536个元素,使用maxelem指定数量
ipset create blacklist hash:net maxelem 1000000
#黑名单
ipset create whitelist hash:net maxelem 1000000
#白名单
查看已创建的ipset
ipset list
加入一个名单ip
ipset add blacklist 10.60.10.xx
去除名单ip
ipset del blacklist 10.60.10.xx
创建防火墙规则,与此同时,allset这个IP集里的ip都无法访问80端口(如:CC攻击可用)
iptables -I INPUT -m set –match-set blacklist src -p tcp -j DROP
iptables -I INPUT -m set –match-set blacklist src -p tcp –destination-port 80 -j DROP
Enable blacklists
iptables -I INPUT 1 -m set --match-set blacklist src -j DROP
将ipset规则保存到文件
ipset save blacklist -f blacklist.txt ipset save whitelist -f whitelist.txt
删除ipset
ipset destroy blacklist ipset destroy whitelist
导入ipset规则
ipset restore -f blacklist.txt ipset restore -f whitelist.txt
ipset -exist restore -f blacklist.txt
可以忽略已有的当冲突时不报错
ipset -exist add blacklist 10.60.10.0
查看被拦截的数据包 iptables -L INPUT -v –line-numbers
输出类似
Chain INPUT (policy DROP 60 packets, 17733 bytes)
num pkts bytes target prot opt in out source destination
1 15 1349 DROP all -- any any anywhere anywhere match-set blacklist src
有效期
在创建set时可以指定有效期,单位为秒
ipset create blacklist hash:ip timeout 300
set里添加的每一条记录自添加以后默认有效期就是指定的timeout值
到期后会自动清理
可以在添加记录时覆盖默认的有效期
ipset add blacklist 6.6.6.6 timeout 60
要修改一个条目的有效期,需要使用-exist
ipset -exist add blacklist 1.2.3.4 timeout 100
如果在创建集合时没有指定 timeout,那么之后添加条目也就不支持 timeout 参数,执行 add 会收到报错。
想要默认条目不会过期(自动删除),又需要添加某些条目时加上 timeout 参数,可以在创建集合时指定 timeout 为 0。
并发限制
iptable限制,控制单个IP的最大30并发连接数
sudo iptables -I INPUT -p tcp --dport 443 -m connlimit --connlimit-above 30 -j REJECT
sudo iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j REJECT
端口转发
允许服务器的IP转发功能: echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 31521 -j DNAT --to 192.168.0.211:1521
相同端口后面可省略不写 iptables -t nat -I PREROUTING -p tcp --dport 1521 -j DNAT --to 192.168.0.211
iptables -t nat -A POSTROUTING -d 192.168.203.235 -p tcp --dport 80 -j MASQUERADE
http://www.dkys.org/archives/1075.html
- 特别注明:本地服务器 IP 未必是公网 IP ,像阿里云就是内网 IP ,请用 ipconfig 确认下走流量的网卡 IP 是外网还是内网。
单端口转发(tcp、udp)
iptables -t nat -A PREROUTING -p tcp --dport [要转发的端口号] -j DNAT --to-destination [要转发的服务器IP]
iptables -t nat -A PREROUTING -p udp --dport [要转发的端口号] -j DNAT --to-destination [要转发的服务器IP]
iptables -t nat -A POSTROUTING -p tcp -d [要转发的服务器IP] --dport [要转发的端口号] -j SNAT --to-source [本机IP]
iptables -t nat -A POSTROUTING -p udp -d [要转发的服务器IP] --dport [要转发的端口号] -j SNAT --to-source [本机IP]
端口段转发(tcp、udp)
转发10000到20000这个端口段,则填10000:20000
iptables -t nat -A PREROUTING -p tcp --dport [要转发的端口段] -j DNAT --to-destination [要转发的服务器IP]
iptables -t nat -A PREROUTING -p udp --dport [要转发的端口段] -j DNAT --to-destination [要转发的服务器IP]
iptables -t nat -A POSTROUTING -p tcp -d [要转发的服务器IP] --dport [要转发的端口段] -j SNAT --to-source [本机IP]
iptables -t nat -A POSTROUTING -p udp -d [要转发的服务器IP] --dport [要转发的端口段] -j SNAT --to-source [本机IP]
我们可能需要将访问主机的7979端口映射到8080端口。也可以iptables重定向完成
iptables -t nat -A PREROUTING -p tcp --dport 7979 -j REDIRECT --to-ports 8080
更改iptables,使之实现nat映射功能
iptables -t nat -A PREROUTING -p tcp --dport 21358 -j DNAT --to-destination 67.215.245.160:1358
iptables -t nat -A POSTROUTING -p tcp -d 67.215.245.160 --dport 1358 -j SNAT --to-source 101.200.151.143:21358
需求很简单,把本地81端口映射到8080端口上
- 所有的81请求转发到了8080上.
iptables -t nat -A PREROUTING -p tcp –dport 81 -j REDIRECT –to-ports 8080
1
iptables -t nat -A PREROUTING -p tcp –dport 81 -j REDIRECT –to-ports 8080
如果需要本机也可以访问,则需要配置OUTPUT链:
iptables -t nat -A OUTPUT -p tcp –dport 81 -j REDIRECT –to-ports 8080 1 iptables -t nat -A OUTPUT -p tcp –dport 81 -j REDIRECT –to-ports 8080 原因:外网访问需要经过PREROUTING链,但是localhost不经过该链,因此需要用OUTPUT,或者POSTROUTING。POSTROUTING不行,需要看看。
#清除配置
/sbin/iptables -P INPUT ACCEPT
/sbin/iptables -F
/sbin/iptables -X
#开放本地和Ping
/sbin/iptables -A INPUT -i lo -j ACCEPT
/sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A INPUT -p icmp -j ACCEPT
#配置内网白名单
/sbin/iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
/sbin/iptables -A INPUT -s 172.16.0.0/12 -j ACCEPT
/sbin/iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
#配置外网白名单
/sbin/iptables -A INPUT -s 180.168.36.198 -j ACCEPT
/sbin/iptables -A INPUT -s 180.168.34.218 -j ACCEPT
/sbin/iptables -A INPUT -s 222.73.202.251 -j ACCEPT
#控制端口
/sbin/iptables -A INPUT -p tcp --dport 80 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#拒绝其它
/sbin/iptables -A INPUT -j DROP
/sbin/iptables -A FORWARD -j DROP
#开放出口
/sbin/iptables -A OUTPUT -j ACCEPT
参考 http://liaoph.com/iptables/
firewalld
systemctl status firewalld
查看服务状态
firewall-cmd --state
常看当前的状态
firewall-cmd --get-active-zones
查看区域信息
查看某区域打开的端口
firewall-cmd --zone=public --list-ports
添加一个开放端口
firewall-cmd --zone=public --add-port=8080/tcp
开放一段端口
firewall-cmd --zone=public --add-port=6010-6060/tcp
add-port 后只是本次生效,并没有保存到配置文件内,执行firewall-cmd --reload
未保存到配置文件内的就丢失了.
需要永久生效时,添加需加上--permanent
,如 firewall-cmd --permanent --zone=public --add-port=9090/tcp
firewall-cmd --reload
生效
更多可参考 http://www.ywnds.com/?p=7570&viewuser=30 https://linux.cn/article-8098-1.html
firewalld 新添加的规则,对于已经建立好的链接是无效的,iptables的规则则是立即对所有链接生效.
如果要使用iptables而不用firewalld:
yum install -y iptables-services
systemctl stop firewalld
systemctl disable firewalld
systemctl enable iptables
流量转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 开启防火墙转发
firewall-cmd --permanent --add-port=2333/tcp
firewall-cmd --permanent --add-port=2333/udp
firewall-cmd --permanent --add-masquerade
firewall-cmd --permanent --add-forward-port=port=2333:proto=tcp:toport=6666:toaddr=1.1.1.1
firewall-cmd --permanent --add-forward-port=port=2333:proto=udp:toport=6666:toaddr=1.1.1.1
firewall-cmd --reload
其中 2333 代表本地监听端口, 6666 表示欲中转服务器的端口, 1.1.1.1 代表欲中转服务器的ip地址。
配置服务器作为路由上网
需求: 有两台服务器:A,B
A,B 组成局域网, A有公网IP,可访问公网资源,B无公网IP,也无法访问互联网
现配置B自由链接到互联网.
在A上配置:
iptables -A INPUT -i eth0 -j ACCEPT
echo "1" > /proc/sys/net/ipv4/ip_forward
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 172.16.0.43 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 172.16.0.43 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -j SNAT –to 172.16.0.148 iptables -t nat -A POSTROUTING -s 172.16.0.43 -o eth0 -j SNAT –to-source 172.16.0.148
这一行最关键!就是加入 nat table 封包伪装!本例中 $innet 是 172.168.100.0/24
而 $EXTIF 则是对外界面,本例中为 eth0
在B上配置,网关设置为A的IP
ip route delete default
ip route add default via 172.16.0.148
route add default gw 172.16.0.148
其中IP为A的局域网IP