免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2007 | 回复: 0

实用Iptables脚本分析(原创) [复制链接]

论坛徽章:
6
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-03 17:33:522015元宵节徽章
日期:2015-03-06 15:50:39IT运维版块每日发帖之星
日期:2016-01-11 06:20:00IT运维版块每日发帖之星
日期:2016-03-19 06:20:0019周年集字徽章-19
日期:2019-09-06 18:56:11
发表于 2013-12-09 18:50 |显示全部楼层
实用Iptables脚本分析
首先在/usr/bin下建立一个脚本名为firewall,设定可执行权限
#chmod +x /usr/bin/firewall
下面我最这个脚本的关键文件做一些说明:  
首先设定假设你想限制某IP(例如10.10.10.20),你只需将他们填入到BADIPS变量中,可以设定多个IP或网端,每个用空格分开.
BADIPS="10.10.10.20 10.1.14.0/24"
接下来开始设定impossible_ips变量,例如设定三个私有iP的网段,前提是你的主机IP 不能在三个设定的网段范围之内,如果在设定范围内就要删除.
IMPOSSIBLE_IPS="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16"
如果你的系统只是家用,单独上网,以下6行代码就无需设置。
1).IN_TCP_PORTALLOWED=""
2).IN_ICMP_ALLOWED=""
3).EGRESS="0"
4).OUT_TCP_PORTALLOWED=""
5).OUT_UDP_PORTALLOWED=""
6).OUT_ICMP_ALLOWED=""
如果你架设了服务器就需要下面的设定,这里强调一下in_tcp_porallowed,in_udp_portallowed是变量,他的值设定常见网络服务的端口号。
如果需要开放连续端口就需要使用: 号,例如需要开放38000-38090之间的所有端口,只要进行如下设定:
in_tcp_portallowed=”38000:38090”
下面看个复杂的例子,
例1:
假定SSH服务只允许200.100.10.10访问,而FTP服务之开放给192.168.20.0/24网段使用;SMTP则是出了10.10.10.20以外其余都可以访问:
In_tcp_portallowed=”ssh,200.100.10.10  ftp,192.168.20.0/24  smtp,!10.10.10.20”
例2:
架设需要开放smtp,domain服务给所有IP使用,然后仅允许来自200.100.10.10和192.168.20.0/24的使用者使用ssh登陆服务器:
In_tcp_portallowed=”ssh,200.100.10.10 ssh,192.168.20.0/24 smtp domain”
案3:一个错误的案例
有人想允许192.168.150.30对内网ssh服务器访问,但是除了192.168.20.10以外其他所有Ip都可以访问22端口,其余都阻断。他是这样写的:
In_tcp_portallowed=”ssh,192.168.150.30  ssh,!192.168.20.10”
我们可以看到虽然规则1限制了只有192.168.150.30可以访问 ssh服务器,但是规则2却反而将其开放给所有人,第一个规则等于摆设。


表1为您列出常见的网络协议
服务名称 Tcp/Udp  端口号
Www Tcp 80
ftp Tcp 21
ssh Tcp 22
telnet tcp 23
Smtp Tcp 25
Pop3 Tcp 110
Domain Udp  53
更多详细的信息您可以在/etc/service文件中找到。
# 允许内网的TCP链接
IN_TCP_PORTALLOWED="ssh,192.168.0.32 smtp domain http https"
# 允许内网的UDP链接
IN_UDP_PORTALLOWED="domain"
如果你想让ping包通过那么需要如下设定
In_icmp_allowed=”8”
当然也可以设定只有某个IP能ping,例如:
In_icmp_allowed=”8,61.63.33.172”
表示只有61.63.33.172可以ping 主机。
# 允许内网ICMP的类型
IN_ICMP_ALLOWED="0 3 8 11"
表 2
类别 含义 说明
0 Echo-replay 回应ping包
3 Destination-unreachable 无法到达目的端
8 Echo-request 要求对方回应ping包
11 Time-exceeded 源端口封包超时
下面看个例子帮助我们理解这张表,在ping时,如果这个 echo-request 不能到达对方的机器﹐或是对方回应的 echo-reply 不能顺利送回来﹐那 ping 就失败。在许多有防火墙的环境中都会碰到﹐如果防火墙将 request 和 reply 拦下来就会导致 ping 失败。另外﹐就算不是防火墙设置的问题﹐对方也可以将机器设定为不回应任何 echo-request 封包﹐若在 Linux 上,只要用下面命令就可以了﹕
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
再举一个例子,在使用traceroute命令式,我们要知道当封包被一个路由节点处理之后﹐它原来的 TTL 值就会被扣掉 1 ﹐这样﹐如果封包的 TTL 降到 0 的时候﹐路由器就会丢弃这个封包﹐并且同时向来源地送出一个 time_exceeded( type 11 ) 的 ICMP 封包﹐以告知其封包的命运。
egress这个设置表示是否限制对外的链接,值为0代表不限制,1代表限制对外链接。
EGRESS="0"
# 允许对外链接的通讯端口
OUT_TCP_PORTALLOWED="ssh smtp,root http https pop3"
# 允许对外链接的UDP通讯端口
OUT_UDP_PORTALLOWED=""
OUT_ICMP_ALLOWED="0 3 8 11"
#如果你希望记录所有被放火墙阻止的数据包,就需要将droplog的值设定为1,不过这样会使/var/log/messages日志容量上升
DROPLOG="0"
#
DSHIELD="0"
#装载iptables核心模块
modprobe ip_tables 2>/dev/null
modprobe ip_conntrack 2>/dev/null
modprobe ip_conntrack_ftp 2>/dev/null
modprobe ip_conntrack_irc 2>/dev/null
#清除当前iptables所有表的规则
echo -n "Initiating iptables..."
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t filter -F
iptables -t nat -F
iptables -t filter -X
iptables -t nat -X
echo "ok"
#
if [ "$DSHIELD" = "1" ]; then
   echo -n "Getting the DShield Block List..."
   BADIPS="$BADIPS
      `lynx --dump http://feeds.dshield.org/block.txt | \
      awk '/^[1-9]/ {print $1 "/" $3}'`"
   echo "ok"
fi
block.txt的部分内容如下:
开始IP 结束IP 网络号 攻击数量  Name Country email
222.189.239.0 222.189.239.255 24 2054   
195.178.109.0 195.178.109.255 24 1601 PROVIDER RU [no email]
216.145.110.0 216.145.110.255 24 1355   
193.219.163.0 193.219.163.255 24 1264 LITNET-3 LT daiva@litnet.lt
221.6.51.0 221.6.51.255 24 1075  CN ll@jsnetcom.com
# 若你加上start参数,则将$skiptest变量置1,那么就会跳过测试模式,设定所有规则后不再清除。
[ "$1" = "start" ] && skiptest="1"
##设置iptables核心的安全相关参数
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 3 > /proc/sys/net/ipv4/tcp_retries1
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1400 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 0 > /proc/sys/net/ipv4/tcp_window_scaling
echo 0 > /proc/sys/net/ipv4/tcp_sack
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
## ?下面开始设定防火墙规则
echo -n "Setting rules..."
#设定input,output,forward的过滤规则,不符合规则的就会丢弃。
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
# 允许流经环路地址(loopback)的包通过
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -i ! lo -s 127.0.0.0/8 -j DROP
iptables -A OUTPUT -o ! lo -d 127.0.0.0/8 -j DROP
# 增加新链badpkt
iptables -N BADPKT
# 若droplog数值为1则记录所有badpkt链的数据包???
if [ "$DROPLOG" = "1" ]; then
   iptables -A BADPKT -j LOG --log-prefix "** Firewall BADPKT **"
fi
# 丢弃所有进入badpkt链的封包??
iptables -A BADPKT -j DROP
# 将可疑封包交给badpkt链处理。
iptables -A INPUT -m state --state INVALID -j BADPKT
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j BADPKT
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADPKT
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j BADPKT
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j BADPKT
iptables -A INPUT -p tcp --tcp-flags ALL FIN -j BADPKT
# 允许目的端口为53的UDP包通过,这样才能使用DNS查询。
iptables -A OUTPUT -p udp -m state --state NEW --dport 53 -j ACCEPT
# 允许已建立连线和回应的数据包通过
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 增加一个阻止IP的新链
iptables -N BADIP
# 若droplog变量为1,则记录所有进入badip链的封包
if [ "$DROPLOG" = "1" ]; then
   iptables -A BADIP -j LOG --log-prefix "** Firewall BADIP **"
fi
# 丢弃所有进入badip链的封包
iptables -A BADIP -j DROP
# 阻止特定IP
for ip in $BADIPS $IMPOSSIBLE_IPS ; do
   iptables -A INPUT -s $ip -j BADIP
done
# 允许特定TCP号对内新连接
for i in $IN_TCP_PORTALLOWED ; do
   IFS=','
   set $i
   unset IFS ipt_option
   port="$1"
   [ -n "$2" ] && ipt_option="-s `echo $2 | sed 's/^!/! /'`"
   iptables -A INPUT -p tcp $ipt_option --dport $port \
         --syn -m state --state NEW -j ACCEPT
done
# 允许特定UDP端口的对内新链接
for i in $IN_UDP_PORTALLOWED ; do
   IFS=','
   set $i
   unset IFS ipt_option
   port="$1"
   [ -n "$2" ] && ipt_option="-s `echo $2 | sed 's/^!/! /'`"
   iptables -A INPUT -p udp $ipt_option --dport $port \
         -m state --state NEW -j ACCEPT
done
# 允许特定ICMP类型数据包进入
for i in $IN_ICMP_ALLOWED ; do
   IFS=','
   set $i
   unset IFS ipt_option
   type="$1"
   [ -n "$2" ] && ipt_option="-s `echo $2 | sed 's/^!/! /'`"
   
   iptables -A INPUT -p icmp $ipt_option --icmp-type $type \
      -m state --state NEW -j ACCEPT
done
# 前面讲过egress数值为1标志管制对外链接
if [ $EGRESS = "1" ]; then
# 允许特定TCP对外链接
for i in $OUT_TCP_PORTALLOWED ; do
   IFS=','
   set $i
   unset IFS ipt_option
   port="$1"
   [ -n "$2" ] && ipt_option="-d `echo $2 | sed 's/^!/! /'`"
   [ -n "$3" ] && ipt_option="$ipt_option -m owner \
      `echo $3 | sed 's/\([^!]\)/ --uid-owner \1/'`"
   iptables -A OUTPUT -p tcp $ipt_option --dport $port \
         --syn -m state --state NEW -j ACCEPT
done
#
for i in $OUT_UDP_PORTALLOWED ; do
   IFS=','
   set $i
   unset IFS ipt_option
   
   port="$1"
   [ -n "$2" ] && ipt_option="-d `echo $2 | sed 's/^!/! /'`"
   [ -n "$3" ] && ipt_option="$ipt_option -m owner \
      `echo $3 | sed 's/\([^!]\)/ --uid-owner \1/'`"
   iptables -A OUTPUT -p udp $ipt_option --dport $port \
         -m state --state NEW -j ACCEPT
done
#
for i in $OUT_ICMP_ALLOWED ; do
   IFS=','
   set $i
   unset IFS ipt_option
   type="$1"
   [ -n "$2" ] && ipt_option="-d `echo $2 | sed 's/^!/! /'`"
   [ -n "$3" ] && ipt_option="$ipt_option -m owner \
      `echo $3 | sed 's/\([^!]\)/ --uid-owner \1/'`"
   iptables -A OUTPUT -p icmp $ipt_option --icmp-type $type \
      -m state --state NEW -j ACCEPT
done
fi
if [ ! "$EGRESS" = "1" ]; then
   iptables -A OUTPUT -m state --state NEW -j ACCEPT
fi
if [ "$DROPLOG" = "1" ]; then
   iptables -A INPUT -j LOG --log-prefix "** Firewall DROP **"
   iptables -A OUTPUT -j LOG --log-prefix "** Firewall DROP **"
   iptables -A FORWARD -j LOG --log-prefix "** Firewall DROP **"
fi
echo "done"
# 5秒后自动清除iptables规则,这样可以避免锁住自己。
if [ "$skiptest" = "1" ]; then exit ;fi
echo -e "\n     TEST MODE"
echo -n "All chains will be cleaned after 5 sec."
i=1; while [ "$i" -le "5" ]; do
   echo -n "."
   i=`expr $i + 1`
   sleep 1
done
echo -en "\n Flushing ruleset..."
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t filter -F
iptables -t nat -F
iptables -t filter -X
iptables -t nat -X
echo "ok"
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP