V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Phishion
V2EX  ›  程序员

请问 Linux 防火墙屏蔽 IP 为什么无效?

  •  
  •   Phishion · 2019-08-02 01:31:45 +08:00 · 5615 次点击
    这是一个创建于 1940 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前使用 fail2ban 设置了一下 ssh 暴力尝试 root 用户名密码会被拒绝的功能

    现在想如法炮制设置 nginx 404 访问次数达到阈值之后,也会被拒绝访问

    但是我发现 iptable 能看到被捕获的 ip 也生成了相应规则,但是依然可以正常访问,然而 ssh 登录的规则一直是正常的

    另外,我自己直接在防火墙写规则也是无效,还是可以正常访问。

    iptables -A INPUT -s 182.254.74.167 -j DROP

    有没有大佬能指点一二,我自己琢磨半天了,谢谢

    附上 fail2ban 规则

    /etc/fail2ban/jail.local
    
    [nginxno404]
    enabled = true
    port = http,https
    filter = nginx-not-found
    action = iptables[name=nginxno404, port=http, protocol=tcp]
    logpath  = /var/log/nginx/access.log
    bantime = 86400
    findtime = 300
    maxretry = 50
    
    

    附上 iptable 结果

    Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        8   320 f2b-nginxno404  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
     3748  305K f2b-SSH    tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
     2585  243K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
     1293 70223 INPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
     1293 70223 INPUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
     1293 70223 INPUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
       15   747 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
     1119 61450 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited
     
    
    Chain f2b-SSH (1 references)
     pkts bytes target     prot opt in     out     source               destination         
       20  1720 REJECT     all  --  *      *       218.92.0.181         0.0.0.0/0            reject-with icmp-port-unreachable
       31  2176 REJECT     all  --  *      *       132.232.18.128       0.0.0.0/0            reject-with icmp-port-unreachable
       57  3776 REJECT     all  --  *      *       177.32.64.189        0.0.0.0/0            reject-with icmp-port-unreachable
       2259  210K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0  
    
    
    Chain f2b-nginxno404 (1 references)
     pkts bytes target     prot opt in     out     source               destination         
        8   320 REJECT     all  --  *      *       182.254.74.167       0.0.0.0/0            reject-with icmp-port-unreachable
        0     0 REJECT     all  --  *      *       182.254.28.36        0.0.0.0/0            reject-with icmp-port-unreachable
        0     0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    
    第 1 条附言  ·  2019-08-02 12:51:57 +08:00
    输入 iptables -I INPUT -s 182.254.74.167 -j DROP 之后,SSH 会被立即断开,但是 web 依然可以正常访问,应该不是 iptable 没有启动,肯定不是缓存的问题,也没有 CDN,我推测会不会是 fail2ban 里面规则的顺序问题。
    第 2 条附言  ·  2019-08-02 12:56:07 +08:00
    目前没启用 https,访问都是 80 端口
    第 3 条附言  ·  2019-08-02 18:51:54 +08:00
    问题已经解决,排查出是 Docker 的问题,因为宿主机的端口映射到容器的端口,所以无论怎么配置 iptables,80 端口都不会受到影响。

    应该是 Docker 提前接管了对于端口的访问

    解决方法如下:
    编辑 /etc/fail2ban/action.d/iptables-common.conf 文件
    将 chain = INPUT 改成 chain = DOCKER-USER 这样 fail2ban 生成的 iptables 规则就可以正常生效了。

    关键词:Docker Linux fail2ban iptables nginx 80 端口 不生效
    32 条回复    2019-08-05 10:21:53 +08:00
    ladypxy
        1
    ladypxy  
       2019-08-02 05:26:12 +08:00 via iPhone   ❤️ 1
    顺序很重要,drop 部分要放在最上面
    ik
        2
    ik  
       2019-08-02 08:46:47 +08:00 via iPhone   ❤️ 1
    iptables -I INPUT -s 182.254.74.167 -j DROP
    Bardon
        3
    Bardon  
       2019-08-02 08:55:56 +08:00   ❤️ 1
    什么情况
    INPUT 引用 f2b-nginxno404 链,然后 f2b-nginxno404 中 针对 182.254.74.167 reject 了

    暴力破解 ssh 的,在 f2b-SSH 链中 reject 了
    xduanx
        4
    xduanx  
       2019-08-02 10:38:49 +08:00   ❤️ 1
    @Bardon 理论上,这样操作没问题吧,但 LZ 说不生效,大佬是否看出哪里不对么
    lpvekk
        5
    lpvekk  
       2019-08-02 10:58:18 +08:00   ❤️ 1
    iptables service start
    skylancer
        6
    skylancer  
       2019-08-02 11:23:07 +08:00   ❤️ 1
    @lpvekk 回帖前请看清楚人家写了什么,谢谢茄子
    omph
        7
    omph  
       2019-08-02 11:33:41 +08:00   ❤️ 1
    网页有缓存吗?
    laminux29
        8
    laminux29  
       2019-08-02 12:27:05 +08:00   ❤️ 1
    开 debug 模式,规则全删,一条条地加进去,加一条测一条。当加到某条,发生测试结果与预计不符的情况时,调换顺序,或者随机删除某几项。
    Phishion
        9
    Phishion  
    OP
       2019-08-02 12:50:32 +08:00
    @ik @omph @lpvekk @xduanx @Bardon @ladypxy

    报告各位大佬:
    输入 iptables -I INPUT -s 182.254.74.167 -j DROP 之后,SSH 会被立即断开,但是 web 依然可以正常访问,应该不是 iptable 没有启动,肯定不是缓存的问题,也没有 CDN,我推测会不会是 fail2ban 里面规则的顺序问题。
    znood
        10
    znood  
       2019-08-02 12:51:28 +08:00   ❤️ 1
    是不是只 REJECT 了 80 端口,依然可以通过 443 访问?
    Phishion
        11
    Phishion  
    OP
       2019-08-02 12:55:31 +08:00
    @znood 我开没启用 https,目前访问都是 80 的
    VD
        12
    VD  
       2019-08-02 13:12:31 +08:00
    -I 是插入到指定位置,然而你没有指定行位置,所以还是插入到 INPUT 最后一行了


    如果你就是想对 INPUT 操作,不论 f2b-SSH 还是 f2b-nginxno404 都要生效,注意顺序,譬如放在 INPUT 中的第一行,iptables 是从上到下匹配。
    iptables -I INPUT 1 -s 182.254.74.167 -j DROP
    VD
        13
    VD  
       2019-08-02 13:14:28 +08:00
    说错了,不指定行数,默认就是第一行...

    那就不可能了呀,对方访问的是缓存数据?你确定对方 web 访问后,你的 nginx 中有对应的日志产生?
    VD
        14
    VD  
       2019-08-02 13:20:15 +08:00   ❤️ 1
    一般而言,iptables 的 input 默认 drop

    然后第一条放行 ping,禁 ping 的忽略
    -A INPUT -p icmp -m icmp --icmp-type echo-request -j ACCEPT
    第二条放行以连接的,譬如 ssh 目前连接着,防止被立即 drop 掉
    -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    第三条放行 lo 回环
    -A INPUT -i lo -j ACCEPT
    ......
    中间放具体规则
    ......
    末尾收尾
    -A INPUT -m conntrack --ctstate INVALID -j DROP
    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    VD
        15
    VD  
       2019-08-02 13:29:45 +08:00   ❤️ 1
    问下 182.254.74.167 是你的外网吧,你在内网测试?流量通过网关直接走了内网。
    Phishion
        16
    Phishion  
    OP
       2019-08-02 13:58:19 +08:00
    @VD 感谢你的回复,IP 是我的外网 IP,iptables -I INPUT 1 -s 182.254.74.167 -j DROP 之后,SSH 会立即断开,但是网页竟然还是正常的,不是内网,我是电信宽带,服务器在美国。

    iptables -L -n

    ```
    Chain INPUT (policy ACCEPT)
    target prot opt source destination
    DROP all -- 182.254.74.167 0.0.0.0/0
    f2b-nginxno404 tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
    DROP all -- 182.254.74.167 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
    INPUT_direct all -- 0.0.0.0/0 0.0.0.0/0
    INPUT_ZONES_SOURCE all -- 0.0.0.0/0 0.0.0.0/0
    INPUT_ZONES all -- 0.0.0.0/0 0.0.0.0/0
    DROP all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
    REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

    Chain FORWARD (policy DROP)
    target prot opt source destination
    DOCKER-USER all -- 0.0.0.0/0 0.0.0.0/0
    DOCKER-ISOLATION-STAGE-1 all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
    DOCKER all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
    DOCKER all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
    ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
    FORWARD_direct all -- 0.0.0.0/0 0.0.0.0/0
    FORWARD_IN_ZONES_SOURCE all -- 0.0.0.0/0 0.0.0.0/0
    FORWARD_IN_ZONES all -- 0.0.0.0/0 0.0.0.0/0
    FORWARD_OUT_ZONES_SOURCE all -- 0.0.0.0/0 0.0.0.0/0
    FORWARD_OUT_ZONES all -- 0.0.0.0/0 0.0.0.0/0
    DROP all -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
    REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

    Chain OUTPUT (policy ACCEPT)
    target prot opt source destination
    OUTPUT_direct all -- 0.0.0.0/0 0.0.0.0/0

    Chain DOCKER (2 references)
    target prot opt source destination
    ACCEPT tcp -- 0.0.0.0/0 172.19.0.2 tcp dpt:8080
    ACCEPT tcp -- 0.0.0.0/0 172.19.0.2 tcp dpt:8000
    ACCEPT tcp -- 0.0.0.0/0 172.19.0.3 tcp dpt:80
    ACCEPT tcp -- 0.0.0.0/0 172.19.0.4 tcp dpt:5432

    Chain DOCKER-ISOLATION-STAGE-1 (1 references)
    target prot opt source destination
    DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0
    DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0
    RETURN all -- 0.0.0.0/0 0.0.0.0/0

    Chain DOCKER-ISOLATION-STAGE-2 (2 references)
    target prot opt source destination
    DROP all -- 0.0.0.0/0 0.0.0.0/0
    DROP all -- 0.0.0.0/0 0.0.0.0/0
    RETURN all -- 0.0.0.0/0 0.0.0.0/0

    Chain DOCKER-USER (1 references)
    target prot opt source destination
    RETURN all -- 0.0.0.0/0 0.0.0.0/0

    Chain FORWARD_IN_ZONES (1 references)
    target prot opt source destination
    FWDI_public all -- 0.0.0.0/0 0.0.0.0/0 [goto]
    FWDI_public all -- 0.0.0.0/0 0.0.0.0/0 [goto]

    Chain FORWARD_IN_ZONES_SOURCE (1 references)
    target prot opt source destination

    Chain FORWARD_OUT_ZONES (1 references)
    target prot opt source destination
    FWDO_public all -- 0.0.0.0/0 0.0.0.0/0 [goto]
    FWDO_public all -- 0.0.0.0/0 0.0.0.0/0 [goto]

    Chain FORWARD_OUT_ZONES_SOURCE (1 references)
    target prot opt source destination

    Chain FORWARD_direct (1 references)
    target prot opt source destination

    Chain FWDI_public (2 references)
    target prot opt source destination
    FWDI_public_log all -- 0.0.0.0/0 0.0.0.0/0
    FWDI_public_deny all -- 0.0.0.0/0 0.0.0.0/0
    FWDI_public_allow all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0

    Chain FWDI_public_allow (1 references)
    target prot opt source destination

    Chain FWDI_public_deny (1 references)
    target prot opt source destination

    Chain FWDI_public_log (1 references)
    target prot opt source destination

    Chain FWDO_public (2 references)
    target prot opt source destination
    FWDO_public_log all -- 0.0.0.0/0 0.0.0.0/0
    FWDO_public_deny all -- 0.0.0.0/0 0.0.0.0/0
    FWDO_public_allow all -- 0.0.0.0/0 0.0.0.0/0

    Chain FWDO_public_allow (1 references)
    target prot opt source destination

    Chain FWDO_public_deny (1 references)
    target prot opt source destination

    Chain FWDO_public_log (1 references)
    target prot opt source destination

    Chain INPUT_ZONES (1 references)
    target prot opt source destination
    IN_public all -- 0.0.0.0/0 0.0.0.0/0 [goto]
    IN_public all -- 0.0.0.0/0 0.0.0.0/0 [goto]

    Chain INPUT_ZONES_SOURCE (1 references)
    target prot opt source destination

    Chain INPUT_direct (1 references)
    target prot opt source destination

    Chain IN_public (2 references)
    target prot opt source destination
    IN_public_log all -- 0.0.0.0/0 0.0.0.0/0
    IN_public_deny all -- 0.0.0.0/0 0.0.0.0/0
    IN_public_allow all -- 0.0.0.0/0 0.0.0.0/0
    ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0

    Chain IN_public_allow (1 references)
    target prot opt source destination
    ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ctstate NEW

    Chain IN_public_deny (1 references)
    target prot opt source destination

    Chain IN_public_log (1 references)
    target prot opt source destination

    Chain OUTPUT_direct (1 references)
    target prot opt source destination

    Chain f2b-nginxno404 (1 references)
    target prot opt source destination
    REJECT all -- 182.254.74.167 0.0.0.0/0 reject-with icmp-port-unreachable
    RETURN all -- 0.0.0.0/0 0.0.0.0/0
    ```
    daviswei
        17
    daviswei  
       2019-08-02 13:59:45 +08:00
    目测你这 INPUT 链没有啥问题,要不看看 mangle 表,是不是这里也配置了 INPUT 链啊?
    daviswei
        18
    daviswei  
       2019-08-02 14:01:27 +08:00
    daviswei
        19
    daviswei  
       2019-08-02 14:02:23 +08:00   ❤️ 1
    @Phishion 还有个可能,你访问网页的时候 ,浏览器是不是有代理?
    Phishion
        20
    Phishion  
    OP
       2019-08-02 14:18:28 +08:00
    @daviswei 感谢你的帮助
    我试了一下,不是代理的问题,我关掉代理也可以访问,和我同一个局域网的手机也可以正常访问,而且 IP 地址实际上是服务端 fail2ban 捕获的,跟我本地的 IP 也吻合。
    我不是专业运维,所以不太懂 mangle 这样的问题
    Phishion
        21
    Phishion  
    OP
       2019-08-02 14:38:46 +08:00
    @daviswei 我在想是不是 Docker 的问题,我的 nginx 是容器,宿主机上的 80 端口实际上是映射到 nginx 容器的 80 端口,是不是因为 Docker 导致所有 80 端口无视 iptable 无条件转发给 nginx
    littlewing
        22
    littlewing  
       2019-08-02 15:00:13 +08:00 via iPhone   ❤️ 1
    @Phishion 很有可能,如果流量在进入 input 链之前就被截获然后发到 docker 的话,iptables 根本就不起作用了
    artandlol
        23
    artandlol  
       2019-08-02 17:41:08 +08:00 via Android   ❤️ 1
    iptable 有两种模式,一个默认 drop 一个默认 accept, docker 默认会把局域网的特定网段都打通
    Phishion
        24
    Phishion  
    OP
       2019-08-02 18:54:35 +08:00
    @ik @omph @lpvekk @xduanx @Bardon @ladypxy @znood @VD @daviswei @littlewing @artandlol

    感谢各位大佬
    问题已经解决,排查出是 Docker 的问题,因为宿主机的 80 口映射到容器的 80 端口,所以无论怎么配置 iptables,80 端口都不会受到影响。

    应该是 Docker 提前接管了对于端口的访问

    解决方法如下:
    编辑 /etc/fail2ban/action.d/iptables-common.conf 文件
    将 chain = INPUT 改成 chain = DOCKER-USER 这样 fail2ban 生成的 iptables 规则就可以正常生效了。
    znood
        25
    znood  
       2019-08-02 19:09:45 +08:00   ❤️ 1
    @Phishion 你改成 DOCKER-USER 其他规则可能就无法生效了,改成 PREROUTING
    littlewing
        26
    littlewing  
       2019-08-02 19:14:09 +08:00   ❤️ 2
    楼上说的对
    顺便贴一张 iptables 的图

    https://i.loli.net/2019/08/02/5d43e5e06f3ff84451.jpg
    Phishion
        27
    Phishion  
    OP
       2019-08-02 19:25:20 +08:00
    @littlewing
    @znood
    得,我花时间再看看,目前没啥规则,谢谢大佬指导
    Phishion
        28
    Phishion  
    OP
       2019-08-02 19:49:52 +08:00
    @znood @littlewing
    确实出问题了,改成 DOCKER-USER 的话,SSH 规则就失效了,但改成 PREROUTING 所有规则都不会生效,真是伤脑筋。。。
    xduanx
        29
    xduanx  
       2019-08-02 21:14:11 +08:00 via iPhone   ❤️ 1
    做了端口映射的话,这就说得通了,docker 端口映射是在 nat 的 prerouting 链里配置的,数据包过防火墙的时候会先经过 prerouting 链,nat 把数据包的目的 IP 修改为 docker 的 IP 后,由于数据包目的 IP 不是本机 IP,数据包不会经过 INPUT 链(所以楼主的 INPUT 链虽然配置正确但没有达到效果)而是进入 forward 链,然后匹配 dorward 里的规则,之后数据包进入 docker。对于 INPUT 链里的规则匹配到了数据包,由于知识有限,看不懂源码,无法作出解释。
    znood
        30
    znood  
       2019-08-02 21:14:25 +08:00   ❤️ 1
    failban 添加到了 filter 表,转发包不走 filter-INPUT,需要在之前处理,PREROUTING 不在 filter 表里,加到 nat 表试下。
    Phishion
        31
    Phishion  
    OP
       2019-08-02 21:25:32 +08:00
    最终我还是解决掉了,做法是单独给 nginx404 指定一个动作,2 个规则现在都正确生效,不知道算不算临时解决方案,不过搞定就行。

    1. 给 nginxno404 规则指定一个自定义动作
    vi /etc/fail2ban/jail.local
    [nginxno404]
    action = iptables-nginx[name=nginxno404, port=http, protocol=tcp]

    2.新建动作页面
    复制 /etc/fail2ban/action.d/iptables-common.conf 为 iptables-nginx.conf
    承接 iptables.conf,然后将 iptables-common.local 注释掉
    再指定 chain name 为 DOCKER-USER

    ```
    vi /etc/fail2ban/action.d/iptables-nginx.conf
    [INCLUDES]
    before = iptables.conf
    after = iptables-blocktype.local
    [Init]
    chain = DOCKER-USER
    ```

    3. 重启 fail2ban
    systemctl restart fail2ban.service
    VD
        32
    VD  
       2019-08-05 10:21:53 +08:00
    仔细看下这里
    https://gist.github.com/tehmoon/b1c3ae5e9a67d66186361d4728bed799#file-iptables-reload-sh

    似乎现在也只有这种办法了

    阅读下这篇文章
    https://medium.com/@ebuschini/iptables-and-docker-95e2496f0b45

    安装有 docker 的主机,nat 表第一条就是
    -A PREROUTING -m addrtype — dst-type LOCAL -j DOCKER
    表示所有流量被路由到 DOCKER 链

    如果对 iptables 足够自信,那么直接自己手动配置,而不要启用 docker 的 iptables 规则,譬如 centos 下这个文件 /etc/sysconfig/docker,其中启动 options 加上--iptables=false
    然后发挥你自己功力吧,虽然我并不建议这么做
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1696 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:48 · PVG 00:48 · LAX 08:48 · JFK 11:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.