使用iptables限制区域访问

事情的起因是不停的有国外ip扫描我阿里云服务器,于是想限制只能国内ip访问,期间用了 fail2ban 但是这个是被动防御,查阅相关资料后写了个脚本使用 iptablesipset 来实现限制地区访问,区域列表来自 ipdeny

安装 ipset

sudo apt-get -y install ipset
iptables 常用命令
iptables -F  # 清除预设链中规则
iptables -X  # 清除自定义链中规则

iptables -A INPUT -i lo -j ACCEPT                                  # 允许来自本机的全部连接
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT   # 允许已建立的连接不中断
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT       # 允许icmp协议,即允许ping服务器
iptables -A INPUT -m set ! --match-set china src -j DROP           # 匹配china链,非国内IP则直接丢弃包
iptables -A INPUT -p udp --dport 5060 -j ACCEPT                    # 允许UDP协议的5060端口
iptables -A INPUT -p udp --dport 20000:30000 -j ACCEPT             # 允许UDP协议的20000-30000端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT                      # 允许TCP协议的80端口
iptables -A INPUT -p tcp --dport 443 -j ACCEPT                     # 允许TCP协议的443端口

iptables -A INPUT -j DROP                                          # 未匹配以上规则的请求直接丢弃
iptables -A OUTPUT -j ACCEPT                                       # 允许全部出网数据包
iptables -A FORWARD -j DROP                                        # 不允许Iptables的FORWARD转发

-I-A 的区别为前者始终在 iptables 的开头添加规则,后者则是追加规则到 iptables 的末尾

allow_ips.sh

#! /bin/bash

Green="\033[32m"
Red="\033[31m"
Font="\033[0m"

# 从ipdeny获取IP地址范围 空格隔开 e.g. cn jp
GEOIPS="cn"
TEMP="$GEOIPS cloudflare private domains"

# 需要放行的域名服务
domains="ipdeny.com download.docker.com registry.docker.io"

# 查询并收集IPv4地址
for domain in $domains; do
    echo "查询域名:$domain"
    nslookup "$domain" | awk '/^Address: / { print $2 }' | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | grep -v ':' >> /tmp/domains.zone
done


# 下载GEOIP
for GEOIP in $GEOIPS; do
  wget -P /tmp https://www.ipdeny.com/ipblocks/data/countries/$GEOIP.zone 2> /dev/null

  if [ -f "/tmp/"$GEOIP".zone" ];then
    echo -e "${Green}$GEOIP IPs data下载成功!${Font}"
  else
    echo -e "${Red}$GEOIP下载失败,请检查你的输入!${Font}"
    echo -e "${Green}代码查看地址:http://www.ipdeny.com/ipblocks/data/countries/${Font}"
    exit 1
  fi
done

wget -O /tmp/cloudflare.zone https://www.cloudflare.com/ips-v4 2> /dev/null

if [ -f "/tmp/cloudflare.zone" ];then
    echo -e "${Green}cloudflare IPs data下载成功!${Font}"
  else
    echo -e "${Red}cloudflare下载失败,请检查你的输入!${Font}"
    echo -e "${Green}代码查看地址:https://www.cloudflare.com/ips-v4${Font}"
    exit 1
fi


cat << 'EOF' > "/tmp/private.zone"
localhost
127.0.0.1
10.0.0.0/8
100.64.0.0/10
172.16.0.0/12
192.168.0.0/16
EOF


#创建规则
lookuplist=`ipset list | grep "Name:" | grep ALLOW_SET`
if [ -n "$lookuplist" ]; then
  ipset flush ALLOW_SET
else
  ipset -N ALLOW_SET hash:net
fi

# 销毁 
# iptables -D INPUT -m set ! --match-set ALLOW_SET src -j DROP
# ipset destroy ALLOW_SET

# 设置iptables
for GEOIP in $TEMP; do
  for i in $(cat /tmp/$GEOIP.zone ); do ipset -A ALLOW_SET $i; done
  rm -f /tmp/$GEOIP.zone
  echo -e "${Green}$GEOIP规则添加成功!${Font}"
done

# 仅允许ALLOW_SET访问
iptables -A INPUT -m set ! --match-set ALLOW_SET src -j DROP

echo "iptables规则已更新"

删除

iptables -D INPUT -m set ! --match-set ALLOW_SET src -j DROP
ipset destroy ALLOW_SET

定时更新iptables规则

sudo crontab -e

# 每周一凌晨更新
0 0 * * 1 /<you ptah>/allow_ips.sh

\color{red}{上述规则并不完善,仅放行了我常用的域名,需要根据自身需求调整上述脚本}

17 个赞

多写点,爱看 :heart_eyes:

都是大佬

之前研究朝鲜系统 RedStar 3.0 捣鼓这个好久……不过那边是出站入站双限制

实用,顶

学到了,给一万个赞

实用,点赞

有用爱看

必须赞!竟然这么巧我也遇到了一样的需求!膜拜大佬!

我这个脚本比较简单粗暴,会存在一定的误杀,误杀那部分需要自行去放行相关IP;
还有个方案是通过 maxmind + geoiplookup 来做限制和这个大同小异有兴趣的可以研究一下:grin:

亲测有效,设置了十分钟后,现在我frp的日志安静下来了。然后我也发现我的fail2ban也有一定的效果,我发现那些搞我的,现在换到国内IP来了 :joy:

root@mytestfun:~# fail2ban-client status armbian-ssh
Status for the jail: armbian-ssh
|- Filter
|  |- Currently failed: 7
|  |- Total failed:     308
|  `- File list:        /var/log/frps/logs.log
`- Actions
   |- Currently banned: 15
   |- Total banned:     15
   `- Banned IP list:   45.55.255.232 138.199.36.230 84.17.51.19 138.199.36.236 84.17.51.25 45.133.173.48 84.17.51.13 181.215.176.227 156.146.55.163 84.17.51.4 84.17.51.17 185.182.185.226 173.249.45.162 101.133.136.70 39.103.162.98
root@mytestfun:~# tail -n 20 /var/log/frps/logs.log
2024/04/05 10:05:12 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [101.133.136.70:35884]
2024/04/05 10:05:12 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [101.133.136.70:35898]
2024/04/05 10:05:12 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [101.133.136.70:35936]
2024/04/05 10:05:12 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [101.133.136.70:35956]
2024/04/05 10:42:57 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [120.33.140.199:12382]
2024/04/05 10:53:59 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [120.33.140.199:13055]
2024/04/05 11:07:13 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [113.215.189.84:58956]
2024/04/05 11:07:13 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [113.215.189.92:19274]
2024/04/05 11:09:06 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [39.103.162.98:57158]
2024/04/05 11:09:06 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [39.103.162.98:57222]
2024/04/05 11:09:06 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [39.103.162.98:57254]
2024/04/05 11:09:06 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [39.103.162.98:57270]
2024/04/05 11:09:06 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [39.103.162.98:57286]
2024/04/05 11:09:07 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [39.103.162.98:57308]
2024/04/05 13:03:59 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [113.215.189.92:35259]
2024/04/05 13:03:59 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [113.215.189.88:49641]
2024/04/05 13:35:07 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [120.33.140.199:10807]
2024/04/05 13:41:50 [I] [proxy.go:204] [8484036070bb2a59] [armbian-ssh] get a user connection [103.59.148.187:39924]
root@mytestfun:~#

误杀之类的不怕,宁杀错一百,不放过一个。
最后,谢谢楼主的脚本!

请教一下,不允许密码登录,只能证书登录,有没有必要也装fail2ban?

有必要的,不允许密码登陆但是不妨碍别人扫你端口,就不停的给你来ssh爆破你服务器响应也会逐渐变慢

如果不存在安全性风险,就等空了再去研究下,还没用过 ~

我的ssh在2万以后的某个端口,下次再装机改到5万以后去