zoukankan      html  css  js  c++  java
  • 实用防火墙(Iptables)脚本分析

    实用防火墙(Iptables)脚本分析

    ——Redhat,CentOS,Ubuntu等常见Linux发行版中都会预装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.10ftp,192.168.20.0/24smtp,!10.10.10.20”

    2

    ——架设需要开放smtp,domain服务给所有IP使用,然后仅允许来自200.100.10.10192.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.30ssh,!192.168.20.10”

    ——我们可以看到虽然规则1限制了只有192.168.150.30可以访问 ssh服务器,但是规则2却反而将其开放给所有人,第一个规则等于摆设。

    170513441.jpg

    更多详细的信息您可以在/etc/service文件中找到。

    允许内网的TCP链接

    IN_TCP_PORTALLOWED="ssh,192.14.0.3 smtp domain http https"

    允许内网的UDP链接

    IN_UDP_PORTALLOWED="domain"

    如果你想让ping包通过那么需要如下设定

    In_icmp_allowed=”8”

    当然也可以设定只有某个IPping,例如:

    In_icmp_allowed=”8,61.63.33.172”

    表示只有61.63.33.172可以ping 主机。

    允许内网ICMP的类型

    IN_ICMP_ALLOWED="0 3 8 11"

    170637136.jpg

    下面看个例子帮助我们理解这张表,在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.0222.189.239.255242054

    195.178.109.0195.178.109.255241601PROVIDERRU[no email]

    216.145.110.0216.145.110.255241355

    193.219.163.0193.219.163.255241264LITNET-3LTdaiva@litnet.lt

    221.6.51.0221.6.51.255241075CNll@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)的包通过,lo代表环路接口。

    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 " 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 " 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"

    这样一个200多行脚本就能实现基本功能的防火墙,大家可以去上机试试,附件中带完整脚本。

    本文出自 “李晨光原创技术博客” 博客,请务必保留此出处http://chenguang.blog.51cto.com/350944/1338882

  • 相关阅读:
    poj 2187 Beauty Contest(旋转卡壳)
    poj 2540 Hotter Colder(极角计算半平面交)
    poj 1279 Art Gallery(利用极角计算半平面交)
    poj 3384 Feng Shui(半平面交的联机算法)
    poj 1151 Atlantis(矩形面积并)
    zoj 1659 Mobile Phone Coverage(矩形面积并)
    uva 10213 How Many Pieces of Land (欧拉公式计算多面体)
    uva 190 Circle Through Three Points(三点求外心)
    zoj 1280 Intersecting Lines(两直线交点)
    poj 1041 John's trip(欧拉回路)
  • 原文地址:https://www.cnblogs.com/chenguang/p/3742166.html
Copyright © 2011-2022 走看看