• iptables的一次修复日志


    iptables的一次修复日志

    搭建配置wireguard后,使用内网连接设备十分方便,我采用的是星型连接,即每个节点都连接到中心节点,但是突然发生了重启wg后中心节点不转发流量的问题,即每个接入的节点只能与中心节点连接,而节点与节点间无法连接。然而reboot重启中心节点机器后,wg内网却能正常工作。最后发现是iptables配置的问题。借此机会熟悉了iptables的逻辑。

    1. 发现和解决问题

    1.1 现象

    当时中心节点上挂了 ipsec,wireguard,和docker等,当时也不知道是谁干的好事,我甚至不知道ipsec也写了这个表,最后锁定了问题出在FORWARD 链。具体是这样的
    重启wireguard,复现了问题后,使用

    sudo iptables -nvL
    
    • 1

    查看这个表,最后观察到这个表是这样的。

    Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
    num   pkts bytes target     prot opt in     out     source               destination         
    1     195K   51M DOCKER-USER  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    2     195K   51M DOCKER-ISOLATION-STAGE-1  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    3        0     0 ACCEPT     0    --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    4        0     0 DOCKER     0    --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    5        0     0 ACCEPT     0    --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    6        0     0 ACCEPT     0    --  docker0 docker0  0.0.0.0/0            0.0.0.0/0           
    7       20   800 DROP       0    --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
    8        0     0 ACCEPT     0    --  eth0   ppp+    0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    9        0     0 ACCEPT     0    --  ppp+   eth0    0.0.0.0/0            0.0.0.0/0           
    10       0     0 ACCEPT     0    --  ppp+   ppp+    0.0.0.0/0            0.0.0.0/0           
    11       0     0 ACCEPT     0    --  eth0   *       0.0.0.0/0            192.168.43.0/24      ctstate RELATED,ESTABLISHED
    12       0     0 ACCEPT     0    --  *      eth0    192.168.43.0/24      0.0.0.0/0           
    13       0     0 ACCEPT     0    --  *      ppp+    192.168.43.0/24      0.0.0.0/0           
    14       0     0 ACCEPT     0    --  wg2    *       0.0.0.0/0            0.0.0.0/0           
    15       0     0 ACCEPT     0    --  *      wg2     0.0.0.0/0            0.0.0.0/0           
    16     393 26860 DROP       0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    17       0     0 ACCEPT     0    --  wg2    *       0.0.0.0/0            0.0.0.0/0           
    18       0     0 ACCEPT     0    --  *      wg2     0.0.0.0/0            0.0.0.0/0           
    19       0     0 ACCEPT     0    --  wg0    *       0.0.0.0/0            0.0.0.0/0           
    20       0     0 ACCEPT     0    --  *      wg0     0.0.0.0/0            0.0.0.0/0           
    21       0     0 ACCEPT     0    --  wg0    *       0.0.0.0/0            0.0.0.0/0           
    22       0     0 ACCEPT     0    --  *      wg0     0.0.0.0/0            0.0.0.0/0           
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    流量从上往下匹配,在匹配到wg0的规则前,匹配到了DROP,卒。
    然后reboot重启了机器,FORWARD链变成了这样

    1      491  106K DOCKER-USER  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    2      491  106K DOCKER-ISOLATION-STAGE-1  0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    3        0     0 ACCEPT     0    --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    4        0     0 DOCKER     0    --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    5        0     0 ACCEPT     0    --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    6        0     0 ACCEPT     0    --  docker0 docker0  0.0.0.0/0            0.0.0.0/0           
    7        0     0 DROP       0    --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
    8        0     0 ACCEPT     0    --  eth0   ppp+    0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    9        0     0 ACCEPT     0    --  ppp+   eth0    0.0.0.0/0            0.0.0.0/0           
    10       0     0 ACCEPT     0    --  ppp+   ppp+    0.0.0.0/0            0.0.0.0/0           
    11       0     0 ACCEPT     0    --  eth0   *       0.0.0.0/0            192.168.43.0/24      ctstate RELATED,ESTABLISHED
    12       0     0 ACCEPT     0    --  *      eth0    192.168.43.0/24      0.0.0.0/0           
    13       0     0 ACCEPT     0    --  *      ppp+    192.168.43.0/24      0.0.0.0/0           
    14       0     0 ACCEPT     0    --  wg2    *       0.0.0.0/0            0.0.0.0/0           
    15       0     0 ACCEPT     0    --  *      wg2     0.0.0.0/0            0.0.0.0/0           
    16     491  106K ACCEPT     0    --  wg0    *       0.0.0.0/0            0.0.0.0/0           
    17       0     0 ACCEPT     0    --  *      wg0     0.0.0.0/0            0.0.0.0/0           
    18       0     0 DROP       0    --  *      *       0.0.0.0/0            0.0.0.0/0           
    19       0     0 ACCEPT     0    --  wg2    *       0.0.0.0/0            0.0.0.0/0           
    20       0     0 ACCEPT     0    --  *      wg2     0.0.0.0/0            0.0.0.0/0           
    21       0     0 ACCEPT     0    --  wg0    *       0.0.0.0/0            0.0.0.0/0           
    22       0     0 ACCEPT     0    --  *      wg0     0.0.0.0/0            0.0.0.0/0                
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    因为有wg0的规则出现在了DROP之前,所以流量成功的走了出来。

    1.2 补充知识点

    iptables中的-A和-I,一个是Insert,一个是Append,Insert会直接插在链规则的最前边,Append则是会直接插在最后边。

    1.3 解决问题

    看了下wg0.conf是怎么写的

    Address = **.**.**.1/24
    PrivateKey = *******************************************=
    PostUp   = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
    
    [Peer]
    publickey = *******************************************=
    AllowedIPs = **.**.**.2/32
    
    [Peer]
    publickey = *******************************************=
    AllowedIPs = **.**.**.3/32
    
    [Peer]
    publickey = *******************************************=
    AllowedIPs = **.**.**.4/32
    
    [Peer]
    publickey =  *******************************************=
    AllowedIPs = **.**.**.5/32
    
    ... ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    其中的PostUp和PostDown被执行,-A 指定了规则append到该表该链的所有规则的后边。
    所以reboot重启机器的时候,由于DROP最后才被append加进来,而wireguard的规则先append进来了,所以从上往下执行。就没事。
    然而此后重启wireguard,由于重新append时append到了DROP后边,所以该规则没能先于DROP被执行
    所以只要重启的时候使用Insert而不是Append就解决了,即把PostUP中的"-A"换成"-I",即

    PostUp   = iptables -I FORWARD -i %i -j ACCEPT; iptables -I FORWARD -o %i -j ACCEPT; iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
    
    • 1

    问题就解决了。

    2. 问题的解释

    关于wg0的规则并排的0有两条,一条是in * out wg0 ,一条是in wg0 out *,它们是冗余的,因为有路由表保证了只有来自wg0的流量才会到wg0。

    3.排查docker和ipsec

    缺德的DROP是谁添加的呢?为了观察这一点,首先引入了两条工具

    3.1 工具

    iptables的注释
    语法是

    iptables -m comment --comment "My comments here"
    
    • 1

    具体使用案例(直接写在wg0.conf里)

    PostUp   = iptables -I FORWARD -i %i -m comment --comment "Added in wg0.conf" -j ACCEPT; iptables -I FORWARD -o %i -m comment --comment "Added in wg0.conf" -j ACCEPT; iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
    
    • 1

    这样就可以在打印iptables表的时候看到注释。

    sudo iptables -nvL
    
    • 1
     4270  203K ACCEPT     0    --  *      wg0     0.0.0.0/0            0.0.0.0/0            /* Added in wg0.conf */
        0     0 ACCEPT     0    --  wg0    *       0.0.0.0/0            0.0.0.0/0            /* Added in wg0.conf */
    
    • 1
    • 2

    TRACE功能
    执行以下命令

    iptables -t raw -I PREROUTING -d **.**.**.70 -j TRACE
    
    • 1

    在raw表的PREROUTING链中添加这条规则,
    这样在到**.**.**.70的流量如何通过的iptables就可以观察了。观察的方法是执行以下命令

    sudo xtables-monitor -t
    
    • 1

    事后我看到的是这样的情况

    PACKET: 2 31ae5dec IN=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=128 ID=59853
     TRACE: 2 31ae5dec raw:PREROUTING:rule:0x2:CONTINUE  -4 -t raw -A PREROUTING -d 11.11.11.70/32 -j TRACE
     TRACE: 2 31ae5dec raw:PREROUTING:return:
     TRACE: 2 31ae5dec raw:PREROUTING:policy:ACCEPT
     TRACE: 2 31ae5dec nat:PREROUTING:return:
     TRACE: 2 31ae5dec nat:PREROUTING:policy:ACCEPT
    PACKET: 2 31ae5dec IN=wg0 OUT=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=127 ID=59853
     TRACE: 2 31ae5dec filter:FORWARD:rule:0x25:ACCEPT  -4 -t filter -A FORWARD -o wg0 -m comment --comment "Added in wg0.conf" -j ACCEPT
     TRACE: 2 31ae5dec nat:POSTROUTING:return:
     TRACE: 2 31ae5dec nat:POSTROUTING:policy:ACCEPT
    PACKET: 2 510f38f9 IN=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=128 ID=59854
     TRACE: 2 510f38f9 raw:PREROUTING:rule:0x2:CONTINUE  -4 -t raw -A PREROUTING -d 11.11.11.70/32 -j TRACE
     TRACE: 2 510f38f9 raw:PREROUTING:return:
     TRACE: 2 510f38f9 raw:PREROUTING:policy:ACCEPT
    PACKET: 2 510f38f9 IN=wg0 OUT=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=127 ID=59854
     TRACE: 2 510f38f9 filter:FORWARD:rule:0x25:ACCEPT  -4 -t filter -A FORWARD -o wg0 -m comment --comment "Added in wg0.conf" -j ACCEPT
    PACKET: 2 47202071 IN=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=128 ID=59855
     TRACE: 2 47202071 raw:PREROUTING:rule:0x2:CONTINUE  -4 -t raw -A PREROUTING -d 11.11.11.70/32 -j TRACE
     TRACE: 2 47202071 raw:PREROUTING:return:
     TRACE: 2 47202071 raw:PREROUTING:policy:ACCEPT
    PACKET: 2 47202071 IN=wg0 OUT=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=127 ID=59855
     TRACE: 2 47202071 filter:FORWARD:rule:0x25:ACCEPT  -4 -t filter -A FORWARD -o wg0 -m comment --comment "Added in wg0.conf" -j ACCEPT
    PACKET: 2 47202071 IN=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=128 ID=59856
     TRACE: 2 47202071 raw:PREROUTING:rule:0x2:CONTINUE  -4 -t raw -A PREROUTING -d 11.11.11.70/32 -j TRACE
     TRACE: 2 47202071 raw:PREROUTING:return:
     TRACE: 2 47202071 raw:PREROUTING:policy:ACCEPT
    PACKET: 2 47202071 IN=wg0 OUT=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=127 ID=59856
     TRACE: 2 47202071 filter:FORWARD:rule:0x25:ACCEPT  -4 -t filter -A FORWARD -o wg0 -m comment --comment "Added in wg0.conf" -j ACCEPT
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    当时的情况是

    PACKET: 2 831e9d23 IN=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=128 ID=59207 
    TRACE: 2 831e9d23 raw:PREROUTING:rule:0x2:CONTINUE  -4 -t raw -A PREROUTING -d 11.11.11.70/32 -j TRACE
    TRACE: 2 831e9d23 raw:PREROUTING:return:
    TRACE: 2 831e9d23 raw:PREROUTING:policy:ACCEPT 
    TRACE: 2 831e9d23 nat:PREROUTING:return:
    TRACE: 2 831e9d23 nat:PREROUTING:policy:ACCEPT 
    PACKET: 2 831e9d23 IN=wg0 OUT=wg0 SRC=11.11.11.20 DST=11.11.11.70 LEN=60 TOS=0x0 TTL=127 ID=59207 
    TRACE: 2 831e9d23 filter:FORWARD:rule:0x36:JUMP:DOCKER-USER  -4 -t filter -A FORWARD -j DOCKER-USER
    TRACE: 2 831e9d23 filter:DOCKER-USER:return:
    TRACE: 2 831e9d23 filter:FORWARD:rule:0x33:JUMP:DOCKER-ISOLATION-STAGE-1  -4 -t filter -A FORWARD -j DOCKER-ISOLATION-STAGE-1
    TRACE: 2 831e9d23 filter:DOCKER-ISOLATION-STAGE-1:return:
    TRACE: 2 831e9d23 filter:FORWARD:rule:0x1f:DROP  -4 -t filter -A FORWARD -j DROP
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    就是通过这个DROP发现的问题。

    3.2 排查结果

    其实上边的工具都没用上,最后发现是ipsec写的DROP,它还同时添加了两条wg0的规则,导致wg0的规则出现了四次。

    它想做的是用一个DROP兜底,结果不幸的是我的wg规则append了在它后边。其实这个DROP应该写进policy。

    由于iptables大家一起用,所以我感觉在最后append一个DROP这种行为其实本身就很不负责。调整了ipsec,结束维护。

    4.iptables的三表五链

    三表: nat,mangle,filter,(raw)
    五链: PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
    请添加图片描述

  • 相关阅读:
    真Unity3D编辑器Editor二次开发
    华为aarch64架构的泰山服务器EulerOS 2.0 (SP8)系统离线安装saltstack3003.1实践
    单调栈是什么?
    Java面试题16-线程池的底层工作原理
    【C&C++编码规范】
    MFC Windows 程序设计[125]之罗盘的奥秘
    linux彻底干干净净完全卸载 mysql
    界面组件Kendo UI for Angular——让应用数据显示更直观!(一)
    网络技术六:TCP/UDP原理
    线程池ThreadPoolExecutor、ThreadLocal
  • 原文地址:https://blog.csdn.net/weixin_43479599/article/details/134515658