美文网首页
iptables主机防火墙的常见配置

iptables主机防火墙的常见配置

作者: li_zw | 来源:发表于2018-06-07 16:15 被阅读0次

    前言

    学习了netfilter的基础知识和一些iptables的常用选项,匹配条件的隐式扩展,显式扩展和处理动作后,可以动手操作一下iptables的规则编写。

    实验环境

    Centos7_64位系统,防火墙使用iptables;
    先关闭Centos7的默认防火墙firewall,安装iptables。

    [root@test2 ~]# systemctl stop firewalld
    [root@test2 ~]# systemctl disable firewalld
    [root@test2 ~]# yum install iptables-services
    

    常用应用

    先清除防火墙的默认规则。

    [root@test2 ~]# iptables -F
    [root@test2 ~]# iptables -nvL
    Chain INPUT (policy ACCEPT 37 packets, 2612 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    
    Chain OUTPUT (policy ACCEPT 14 packets, 1336 bytes)
     pkts bytes target     prot opt in     out     source               destination 
    
    

    链的默认规则建议:iptables chain的默认规则是ACCEPT的,这样的好处在于不容易出现操作失误后永远地跟服务器失去联系,通常,默认规则设置在链中的最后一条比较妥当。

    [root@test2 ~]# iptables -A INPUT -d 192.168.30.138 -p tcp --dport 22 -j ACCEPT    #先设置允许ssh的连接
    [root@test2 ~]# iptables -A INPUT -j REJECT #添加默认规则
    [root@test2 ~]# iptables -A OUTPUT -s 192.168.30.138 -p tcp --sport 22 -j ACCEPT
    [root@test2 ~]# iptables -A OUTPUT -j REJECT
    
    [root@test2 ~]# iptables -nvL
    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
      636 46525 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.30.138       tcp dpt:22
      816 70227 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
    
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    
    Chain OUTPUT (policy ACCEPT 54 packets, 4174 bytes)
     pkts bytes target     prot opt in     out     source               destination         
       71  8531 ACCEPT     tcp  --  *      *       192.168.30.138       0.0.0.0/0            tcp spt:22
       80 12072 REJECT     all  --  *      *       192.168.30.138       0.0.0.0/0            reject-with icmp-port-unreachable
    

    multiport

    multiport能够在一条规则上指定多个端口,最多指定15个,连续的端口如20:22,只算两个,离散端口使用“,”分割
    实例:在本机开放SSH服务和HTTPD服务

    [root@test2 ~]# iptables -R INPUT 1 -d 192.168.30.138 -p tcp -m multiport --dports 22,80 -j ACCEPT   #修改下第一条
    [root@test2 ~]# iptables -R OUTPUT 1 -s 192.168.30.138 -p tcp -m multiport --sports 22,80 -j ACCEPT   
    [root@test2 ~]# iptables -nvL
    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
      247 16328 ACCEPT     tcp  --  *      *       0.0.0.0/0            192.168.30.138       multiport dports 22,80
     1572  134K REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
    
    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
    
    Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
       14  1336 ACCEPT     tcp  --  *      *       192.168.30.138       0.0.0.0/0            multiport sports 22,80
       80 12072 REJECT     all  --  *      *       192.168.30.138       0.0.0.0/0            reject-with icmp-port-unreachable
    
    开放自己对外ping测,但不开放外对内Ping测
    icmp 8/0类型是icmp request请求
    icmp 0/0类型是icmp reply报文
    可以在INPUT禁止8/0报文,允许0/0报文,在OUTPUT上放开8/0报文,达到目的。
    [root@test2 ~]# iptables -I INPUT 2 -d 192.168.30.138 -p icmp --icmp-type 0 -j ACCEPT #放开0类型报文,8类型报文被最后的规则过滤了
    [root@test2 ~]# iptables -I OUTPUT 2 -s 192.168.30.138  -p icmp --icmp-type 8 -j ACCEPT    #OUTPUT放开类型8的报文
    
    

    ip_conntrack

    ip_conntrack提供追踪功能,后来改称为nf_conntrack,由nf_conntrack模块提供。
    只要一加载该模块,/proc/net/nf_conntrack文件中就会记录下追踪的连接状态。虽然会追踪TCP/UDP/ICMP的所有连接,但是在此文件中只保存tcp的连接状态。

    [root@test2 ~]# tail /proc/net/nf_conntrack
    ipv4     2 tcp      6 299 ESTABLISHED src=192.168.30.1 dst=192.168.30.138 sport=52408 dport=22 src=192.168.30.138 dst=192.168.30.1 sport=22 dport=52408 [ASSURED] mark=0 zone=0 use=2
    ipv4     2 udp      17 11 src=192.168.1.170 dst=108.59.2.24 sport=59756 dport=123 src=108.59.2.24 dst=192.168.1.170 sport=123 dport=59756 mark=0 zone=0 use=2
    ipv4     2 unknown  2 198 src=192.168.1.125 dst=224.0.0.251 [UNREPLIED] src=224.0.0.251 dst=192.168.1.125 mark=0 zone=0 use=2
    

    nf_conntrack好处好多,但每一个监控和追踪的工具都是消耗性能的,而nf_conntrack也有其瓶颈所在。nf_conntrack也会消耗一定的资源,所以在设计的时候默认给出了其最大的追踪数量,最大追踪数量值由/proc/sys/net/netfilter/nf_conntrack_max文件决定。默认是31384个。这个值显然是无法满足较高并发量的服务器的,所以可以将其增大一些,否则追踪数达到了最大值后,后续的所有连接都将排队被阻塞,可能会因此给出警告。但是无论如何要明白的是追踪是会消耗性能的,所以该值应该酌情考虑。

    state 显式扩展

    该扩展是conntrack的子集,有4个状态(NEW、ESTABLISHED、RELATED、INVALID)这些状态跟TCP的状态机没关系,这4种状态对TCP,UDP,ICMP都是适用的,这些状态是数据包的状态,另外在NAT中,防火墙是不会去改变这些数据包的状态。

    NEW状态

    发送的第一个数据包状态即为NEW状态,如果在TCP中,为了建立连接而三次握手,就算不能成功建立,但第二个数据包状态已经不是NEW了

    ESTABLISHED

    无论是TCP\UDP\ICMP只要发送的第一个数据包穿过了防火墙,那么接下来双方的数据包状态就是ESTABLISHED

    RELATED

    相关联的连接,当前连接是一个新请求,但附属于某个已存在的连接,
    RELATED状态和协议无关,只要数据包是因为本机先送出一个数据包而导致另一条连接的产生,那么这个新连接的所有数据包都属于RELATED状态的数据包。

    INVALID

    ESTABLISHED、NEW、RELATED状态的数据包,那么就一定是INVALID状态。是一个非法的状态,应当禁止

    通常使用state状态来设置防火墙会大大提升效率
    例如,对于本机对外访问,我们一般都可以考虑放行,对于响应报文我们只需要在INPUT上放行ESTABLISHED状态,就可以正常通信了;对于外部一些NEW状态进入INPUT链,我们可以明确指定放开哪些服务NEW状态通信,否则会匹配最后的拒绝规则;另外,为了防止反弹式木马,像一些恶意木马,利用本机已开放的端口,如80,去连接服务端;可以对这些端口在OUTPUT链上禁止NEW状态通过,因为通常,这些服务端口都是服务端口,不太可能主动去连接别人。

    使用state优化规则

    先把iptables的所有规则清空

    [root@test2 ~]# iptables -F 
    
    在INPUT链上放通ESTABLISHED状态和 http和ssh的NEW状态。
    [root@test2 ~]# iptables -A INPUT -p tcp -m multiport --dports 22,80 -m state --state=NEW -j ACCEPT
    [root@test2 ~]# iptables -I INPUT -m state --state=ESTABLISHED -j ACCEPT 
    [root@test2 ~]# iptables -A INPUT -j REJECT
    
    #OUTPUT链也放通ESTABLISHED 和NEW状态
    [root@test2 ~]# iptables -A OUTPUT -m state --state=ESTABLISHED -j ACCEPT
    [root@test2 ~]# iptables -I OUTPUT -m state --state=NEW -j ACCEPT
    [root@test2 ~]# iptables -A OUTPUT -j REJECT
    
    #为了防止反弹式木马,应该对80,22的NEW状态不允许通过
    [root@test2 ~]# iptables -I OUTPUT -p tcp -m multiport --sports 22,80 -m state --state=NEW -j REJECT
    
    

    NAT

    服务器接受到的报文有两种不同的走向,第一种是走向用户空间的报文,另一种是走向其他网卡出去的报文,对于第二种,linux默认是不会帮忙转发的,但是打开了linux系统的核心转发功能,就能像路由器那样可以转发报文。

    实验:利用linux做转发数据包

    实验环境:3台linux,1台linux打开ip_forward,转发2台linux之间的报文
    linux客户端:Centos6.9(192.168.30.128)SUSE(172.16.1.2)
    linux网关服务器: Centos7,两张网卡(192.168.30.138)(172.16.1.1)

    centos6主机:
    ![image_1cf79lougpkl1q1b1povjsu1rv79.png-38.9kB][1]

    suse主机
    ![image_1cf79mrcs1aeud17gbt19jt1idp1m.png-27.8kB][2]

    在centos7 上ping测双方都可以通信

     [root@test2 ~]# ping 192.168.30.128
    PING 192.168.30.128 (192.168.30.128) 56(84) bytes of data.
    64 bytes from 192.168.30.128: icmp_seq=1 ttl=64 time=0.969 ms
    [root@test2 ~]# ping 172.16.1.2
    PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
    64 bytes from 172.16.1.2: icmp_seq=1 ttl=64 time=0.751 ms
    64 bytes from 172.16.1.2: icmp_seq=2 ttl=64 time=0.317 ms
    

    我现在没配置ip_forword,数据包默认是不能过去的
    在Centos6上去ping测172.16.1.1,是可以通的

    [root@test1 ~]# ping 172.16.1.1
    PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
    64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=0.557 ms
    64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=0.933 ms
    64 bytes from 172.16.1.1: icmp_seq=3 ttl=64 time=0.906 ms
    
    #在Centos7上抓包:
    [root@test2 ~]# tcpdump -nn -i ens37 icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on ens37, link-type EN10MB (Ethernet), capture size 262144 bytes
    14:50:49.506112 IP 192.168.30.128 > 172.16.1.1: ICMP echo request, id 7187, seq 1, length 64
    14:50:49.506162 IP 172.16.1.1 > 192.168.30.128: ICMP echo reply, id 7187, seq 1, length 64
    14:50:50.521664 IP 192.168.30.128 > 172.16.1.1: ICMP echo request, id 7187, seq 2, length 64
    14:50:50.521723 IP 172.16.1.1 > 192.168.30.128: ICMP echo reply, id 7187, seq 2, length 64
    //虽然172.16.1.1是ens33网卡的地址,但整个tcp/ip协议栈都是由内核管理,所以,数据包并没有到达ens33的这块网卡,数据包在内核已经回复了。
    
    #我在Centos6上去ping测172.16.1.2结果:
    [root@test1 ~]# ping 172.16.1.2 
    PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
    ^C
    --- 172.16.1.2 ping statistics ---
    4 packets transmitted, 0 received, 100% packet loss, time 4013ms
    没有回复
    并且在Centos7上抓包,ens37这张网卡能抓包ICMP的请求报文,但是ens33这张是不能抓到的,因为linux没有开启ip_forward功能,数据包直接被丢弃
    #
    #下面我在Centos7上开启转发功能,
    [root@test2 ~]# echo "1" >  /proc/sys/net/ipv4/ip_forward   #开启转发功能
    
    下面Centos6上ping,然后在Centos7上抓包,就能在ens33上看到被转发的数据包
    [root@test2 ~]# tcpdump  -nn -i ens33 icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    14:58:21.294997 IP 192.168.30.128 > 172.16.1.2: ICMP echo request, id 12563, seq 1, length 64
    14:58:21.295966 IP 172.16.1.2 > 192.168.30.128: ICMP echo reply, id 12563, seq 1, length 64
    14:58:22.300825 IP 192.168.30.128 > 172.16.1.2: ICMP echo request, id 12563, seq 2, length 64
    14:58:22.302045 IP 172.16.1.2 > 192.168.30.128: ICMP echo reply, id 12563, seq 2, length 64
    
    

    网络防火墙

    把linux的转发功能打开后,linux就可以充当一台路由器来使用,如果需要过滤数据包,例如我把Centos6当作内网的一台主机,SUSE当作外网,则可以在网关上设置过滤规则来保护内网主机。
    例如:对于内网访问外网的数据包,我们可以放行,但外网想要访问内网,拒绝,我们可以使用state状态来设置防火墙。

    先设置默认规则,拒绝。

    [root@test2 ~]# iptables -A FORWARD -j REJECT   #拒绝所有
    [root@test2 ~]# iptables -R FORWARD 2 -s 192.168.30.0/24 -i ens37 -m state --state=NEW -j ACCEPT   #对ens37 192.168.30.0网络的主机状态为NEW的放行
    [root@test2 ~]# iptables -I FORWARD -m state --state=ESTABLISHED -j ACCEPT   #对ESTABLISH状态的报文放通。
    
    #ping测无问题
    [root@test1 ~]# ping 172.16.1.2 
    PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
    64 bytes from 172.16.1.2: icmp_seq=1 ttl=63 time=1.29 ms
    64 bytes from 172.16.1.2: icmp_seq=2 ttl=63 time=2.21 ms
    64 bytes from 172.16.1.2: icmp_seq=3 ttl=63 time=1.81 ms
    反过来,SUSE想Ping测 因为状态为NEW不能通过
    
    如果想放通Centos6的80端口,可以这样放通:
    [root@test2 ~]# iptables -I FORWARD 2 -d 192.168.30.128 -p tcp --dport 80 -m state --state=NEW -j ACCEPT   #放通STATE=NEW的tcp80数据包
    
    #在SUSE上curl来测试80端口是否能通信。
    linux-olth:~ # curl http://192.168.30.128/index.html
    <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
    <html><head>
    <title>403 Forbidden</title>
    </head><body>
    <h1>Forbidden</h1>
    <p>You don't have permission to access /index.html
    on this server.</p>
    <hr>
    <address>Apache/2.2.15 (CentOS) Server at 192.168.30.128 Port 80</address>
    </body></html>
    //虽然网页因为权限问题被拒绝访问,但其实访问80端口是没问题的
    
    

    NAT网络地址转换

    在最开始的时候,NAT是用来保护内网主机不暴露在外网之中,后来发现NAT可以很好的用来解决IP地址数量不足的情况,即使用一个外网IP地址,就可以使得N台内网主机同时上网,而且上网的主机不会真正的暴露在外网之中。
    在Linux上也可以很好的使用nat,而很多的家庭路由器,无非就是一个安装了linux内核的固件安装好netfilter然后提供一个WEB管理接口,就能成为一个路由器了。

    SNAT

    SNAT在POSTROUTING上做,例如,我把192.168.30.128在防火墙上通过SNAT转换成172.16.1.1,这样外网主机就认为是172.16.1.1这台主机在访问自己。这样可以把内网主机隐藏起来。

    在Centos7的nat表中的POSTROUTING链上增加一条规则:

    [root@test2 ~]# iptables -t nat -A POSTROUTING -s 192.168.30.128 -j SNAT --to-source 172.16.1.1 #这样192.168.30.128访问外网时候,就被转换成172.16.1.1
    [root@test1 ~]# ping 172.16.1.2
    PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
    ...#我在192.168.30.128上ping 172.16.1.2
    
    #在172.16.1.2上抓包,可以发现是172.16.1.2发过来的请求。
    
    linux-olth:~ # tcpdump -nn -i ens33 icmp
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
    16:20:01.191918 IP 172.16.1.1 > 172.16.1.2: ICMP echo request, id 4116, seq 1, length 64
    16:20:01.191988 IP 172.16.1.2 > 172.16.1.1: ICMP echo reply, id 4116, seq 1, length 64
    
    
    

    如果内网地址不固定,可以使用MASQUERADE,这个target会消耗资源,所以斟酌

    DNAT是用于保护服务器的
    如,Centos6作为web服务器,在网关做一个DNAT,外网通过172.16.1.1:80可以访问192.168.30.128:80,DNAT需要在PREROUTING上做,

    [root@test2 ~]# iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.30.128:80   #把访问172.16.1.1:80转换成192.168.30.128:80
    
    
    #在SUSE上telnet 172.16.1.1:80
    linux-olth:~ # telnet 172.16.1.1 80
    Trying 172.16.1.1...
    Connected to 172.16.1.1.
    Escape character is '^]'.
    
    #在192.168.30.128 80端口上抓包
    [root@test1 ~]# tcpdump -nn -i eth0 tcp dst port 80
    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
    11:00:51.932726 IP 172.16.1.2.40394 > 192.168.30.128.80: Flags [S], seq 2023634883, win 29200, options [mss 1460,sackOK,TS val 3943340391 ecr 0,nop,wscale 7], length 0
    11:00:51.934523 IP 172.16.1.2.40394 > 192.168.30.128.80: Flags [.], ack 1947788900, win 229, options [nop,nop,TS val 3943340392 ecr 3631953577], length 0
    11:00:52.979786 IP 172.16.1.2.403
    
    能顺利捕捉到172.16.1.2发过来的数据包
    
    
    
    

    相关文章

      网友评论

          本文标题:iptables主机防火墙的常见配置

          本文链接:https://www.haomeiwen.com/subject/fobgsftx.html