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

两个 Network Namespace 无法互相 Ping 通。

  •  1
     
  •   lxy42 · 2019-07-30 21:57:48 +08:00 · 2298 次点击
    这是一个创建于 1725 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网络拓扑:

                                bridge
    
           +------------------------------------------------+
           |                     br0                        |
           |                 192.168.3.1/24                 |
           |   +------------+              +------------+   |
           |   | veth+host1 |              | veth+host1 |   |
           |   |            |              |            |   |
           +---+--+---------+--------------+------+-----+---+
                  |                               |
                  |                               |
                  |                               |
                  |                               |
    +------+------v---+------+        +------+----v-----+------+
    |      |   eth0   |      |        |      |   eth0   |      |
    |      +----------+      |        |      +----------+      |
    |          host1         |        |          host2         |
    |                        |        |                        |
    |    192.168.3.11/24     |        |     192.168.3.12/24    |
    +------------------------+        +------------------------+
          Network Namespace                 Network Namespace
    

    执行的命令:

    # 创建 Network Namespace
    sudo ip netns add host1
    sudo ip netns add host2
    
    # 添加网桥
    sudo brctl addbr br0
    sudo ip addr add 192.168.3.1/24 dev br0
    sudo ip link set br0 up
    
    # 创建 veth peer
    sudo ip link add P type veth peer name veth-host1
    sudo brctl addif br0 veth-host1
    sudo ip link set dev veth-host1 up
    sudo ip link set P netns host1
    sudo ip netns exec host1 ip link set dev P name eth0
    sudo ip netns exec host1 ip link set eth0 up
    sudo ip netns exec host1 ip addr add 192.168.3.11/24 dev eth0
    sudo ip netns exec host1 ip link set lo up
    sudo ip netns exec host1 ip route add default via 192.168.3.1
    
    # 创建 veth peer
    sudo ip link add P type veth peer name veth-host2
    sudo brctl addif br0 veth-host2
    sudo ip link set dev veth-host2 up
    sudo ip link set P netns host2
    sudo ip netns exec host2 ip link set P name eth0
    sudo ip netns exec host2 ip link set eth0 up
    sudo ip netns exec host2 ip addr add 192.168.3.12/24 dev eth0
    sudo ip netns exec host2 ip link set lo up
    sudo ip netns exec host2 ip route add default via 192.168.3.1
    

    最近在研究 Docker 的底层网络原理,想要手动模拟 Docker 容器网络。通过上面的命令创建两个 Network Namespace 后,问题是在 host1 无法 ping 通过 host2,host2 也无法 ping 通 host1。

    $ sudo ip netns exec host1 ping 192.168.3.12
    PING 192.168.3.12 (192.168.3.12) 56(84) bytes of data.
    From 192.168.3.11 icmp_seq=10 Destination Host Unreachable
    
    $ sudo ip netns exec host2 ping 192.168.3.11
    PING 192.168.3.11 (192.168.3.11) 56(84) bytes of data.
    From 192.168.3.12 icmp_seq=1 Destination Host Unreachable
    

    不知道是不是还要配置什么,例如 iptables。

    第 1 条附言  ·  2019-07-30 22:39:42 +08:00

    我不太熟悉iptables,正在研究。下面是我宿主机的iptables:

    $ sudo iptables -L                             
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain FORWARD (policy ACCEPT)
    target     prot opt source               destination         
    DOCKER-USER  all  --  anywhere             anywhere            
    DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
    DOCKER     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
    DOCKER     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere            
    ACCEPT     all  --  anywhere             anywhere            
    
    
    第 2 条附言  ·  2019-07-30 22:40:10 +08:00

    附言长度限制,接上一条

    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain DOCKER (2 references)
    target     prot opt source               destination         
    ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:mysql
    
    Chain DOCKER-ISOLATION-STAGE-1 (1 references)
    target     prot opt source               destination         
    DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
    DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
    RETURN     all  --  anywhere             anywhere            
    
    Chain DOCKER-ISOLATION-STAGE-2 (2 references)
    target     prot opt source               destination         
    DROP       all  --  anywhere             anywhere            
    DROP       all  --  anywhere             anywhere            
    RETURN     all  --  anywhere             anywhere            
    
    Chain DOCKER-USER (1 references)
    target     prot opt source               destination         
    RETURN     all  --  anywhere             anywhere            
    
    17 条回复    2020-10-26 21:49:09 +08:00
    lcdtyph
        1
    lcdtyph  
       2019-07-30 22:16:22 +08:00
    没有复现你的问题= =我这里可以相互 ping 通

    你可以检查一下 iptables 的默认策略,还有两个 ns 能 ping 通 192.168.3.1 么。
    可以用 arping 检查一下二层通没通。
    lxy42
        2
    lxy42  
    OP
       2019-07-30 22:23:12 +08:00 via Android
    @lcdtyph 可以 ping 通 192.168.3.1,也可以 ping 通宿主机的其它网络接口。
    singerll
        3
    singerll  
       2019-07-30 22:30:00 +08:00 via Android   ❤️ 1
    traceroute 看一下卡到哪里了
    lcdtyph
        4
    lcdtyph  
       2019-07-30 22:41:06 +08:00
    traceroute 可能看不出来,正常只有一个跃点才对,两个 vpeer 相当于同一个子网下的

    我觉得你检查一下宿主机的 bridge 设置= =
    lxy42
        5
    lxy42  
    OP
       2019-07-30 22:41:53 +08:00
    @singerll 就只有一跳啊,traceroute 也看不出来问题。
    lcdtyph
        7
    lcdtyph  
       2019-07-30 22:50:08 +08:00
    forward 链确实能匹配到 drop 规则,不过在我本地测试 bridge 的流量不会过 netfilter 呀= =
    你试试插入一条 accept 能不能 ping 通吧:
    ```
    iptables -I FORWARD ACCEPT

    # recover:
    # iptables -D FORWARD 1
    ```

    测完记得复原= =
    lxy42
        8
    lxy42  
    OP
       2019-07-30 22:52:51 +08:00
    用 tcpdump 在网桥 br0 上抓包可以看到 ICMP 的请求,可以看不到响应。

    ```
    $ sudo tcpdump -i br0 -XX -n -vv "icmp"
    tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
    22:50:38.681424 IP (tos 0x0, ttl 64, id 11788, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.3.12 > 192.168.3.11: ICMP echo request, id 992, seq 1, length 64
    0x0000: 7e10 f6c2 178e 7e10 f6c2 178e 0800 4500 ~.....~.......E.
    0x0010: 0054 2e0c 4000 4001 8535 c0a8 030c c0a8 .T..@[email protected]......
    0x0020: 030b 0800 0730 03e0 0001 3e59 405d 0000 .....0....>Y@]..
    0x0030: 0000 a565 0a00 0000 0000 1011 1213 1415 ...e............
    0x0040: 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 ...........!"#$%
    0x0050: 2627 2829 2a2b 2c2d 2e2f 3031 3233 3435 &'()*+,-./012345
    0x0060: 3637 67
    ```
    orzfly
        9
    orzfly  
       2019-07-30 22:57:10 +08:00   ❤️ 1
    看看 host1 eth0 和 host2 eth0 的 MAC 地址?
    lxy42
        10
    lxy42  
    OP
       2019-07-30 22:57:12 +08:00
    @lcdtyph 加了还是不行。
    lcdtyph
        11
    lcdtyph  
       2019-07-30 23:02:22 +08:00
    你这抓包里面怎么目的 mac 和源 mac 是一样的呀
    lcdtyph
        12
    lcdtyph  
       2019-07-30 23:03:23 +08:00   ❤️ 1
    @lcdtyph 都是 7e:10:f6:c2:17:8e
    lxy42
        13
    lxy42  
    OP
       2019-07-30 23:11:09 +08:00
    @orzfly
    @lcdtyph

    问题根源是 MAC 地址重复了。应该是我的执行命令有问题,

    创建 host1 的 veth peer 时:`sudo ip link add P type veth peer name veth-host1`
    创建 host2 的 veth peer 时:`sudo ip link add P type veth peer name veth-host2`
    注意两条命令的其中一个 peer 都是 P。

    导致 host1 和 host2 的 eth0 的 MAC 地址重复。
    lcdtyph
        14
    lcdtyph  
       2019-07-30 23:16:29 +08:00
    @lxy42
    神奇,我就是复制了你的命令,但是我这边的 mac 是没重复的。
    内核版本 4.19.0-5-amd64
    lxy42
        15
    lxy42  
    OP
       2019-07-30 23:20:29 +08:00
    我当初运行命令时,就是想着名字 P 只是临时的,稍后就会分配到新的 Network Namespace,所以没有起不同的名字。

    可能有什么缓存机制。

    我的是 Linux Manjaro 4.19.56-1-MANJARO
    lxy42
        16
    lxy42  
    OP
       2019-07-30 23:33:04 +08:00
    先创建一对 veth peer:P 和 veth-b,接着删除,再创建。发现 P 和 veth-b 两次分配的 MAC 地址是一样的。

    ```
    $ sudo ip link add P type veth peer name veth-b
    $ sudo ip link delete P
    $ sudo ip link add P type veth peer name veth-b
    ```
    11060
        17
    11060  
       2020-10-26 21:49:09 +08:00
    遇到了同样的问题,但我的执行命令没有错,MAC 也没重复;结果还是 namespace 中可以 ping 通网桥,宿主机中也 ping 的通 namespace,但是就是两个 namespace 互相不通。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   861 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 21:40 · PVG 05:40 · LAX 14:40 · JFK 17:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.