systemd-nspawnコンテナのネットワーク設定

Arch Linuxホストのブリッジインタフェース経由で外部と通信するコンテナを、systemd-nspawnで作成する際のネットワーク設定をまとめる。

構成

  • コンテナ用ネットワークは10.39.252.0/24
  • 外部ネットワークからの通信はsshのみ許可する
  • 内部ネットワークから外部ネットワークへの通信は全て許可する
  • コンテナ - ホスト間、各コンテナ間のIPv4通信は全て許可する

  • ホスト側
    • 外部側インタフェースはeth0
      • 外部のDHCPサーバ経由でネットワーク設定を受け取る
    • ブリッジインタフェースはbr0
    • br0のIPアドレスは10.39.252.254
  • コンテナ側
    • コンテナ名はbase
    • 静的IPアドレスを割り当てる
    • vethインタフェースはhost0
    • host0のIPアドレスは10.39.252.1

ホスト側作業(ホスト構築時のみ)

ホスト側パッケージの導入

1
HOST# pacman -S nftables arch-install-scripts

ホスト側設定ファイルの作成

HOST: /etc/systemd/network/eth0.network

1
2
3
4
5
6
[Match]
Name=eth0

[Network]
DHCP=yes
IPForward=yes

HOST: /etc/systemd/network/br0.netdev

1
2
3
[NetDev]
Name=br0
Kind=bridge

HOST: /etc/systemd/network/br0.network

1
2
3
4
5
[Match]
Name=br0

[Network]
Address=10.39.252.254/24

HOST: /etc/systemd/network/vb.network

参考: document what the “degraded” state of network interfaces precisely means #575

1
2
3
4
5
[Match]
Name=vb-*

[Network]
LinkLocalAddressing=no

HOST: /etc/nftables.conf

ちょっとあやしいけどとりあえず動く

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
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/nft -f
table ip nat {
        chain prerouting {
                type nat hook prerouting priority 0
                policy accept
        }

        chain postrouting {
                type nat hook postrouting priority 100
                oifname eth0 masquerade
                policy accept
        }
}

table inet filter {
  chain input {
    policy drop
    type filter hook input priority 0

    ct state { established, related } accept
    ct state invalid drop
    iifname lo accept
    ip protocol icmp accept
    tcp dport ssh accept
    ip saddr 10.39.252.0/24 accept

    reject with icmp type port-unreachable
  }

  chain forward {
    policy accept
    type filter hook forward priority 0
  }

  chain output {
    policy accept
    type filter hook output priority 0
  }
}

ホスト側設定コマンドの実行

1
2
3
4
HOST# systemctl enable --now systemd-networkd
HOST# systemctl enable --now systemd-resolved
HOST# systemctl enable --now nftables
HOST# systemctl enable --now machines.target

ホスト側作業(コンテナ作成時に毎回)

ホスト側コンテナ用設定ファイルの作成

HOST: /etc/systemd/nspawn/base.nspawn

1
2
[Network]
Bridge=br0

コンテナの作成

1
2
3
4
5
6
HOST# pacstrap -d /var/lib/machines/base base
HOST# machinectl enable base
HOST# machinectl start base
HOST# machinectl shell base
Connected to machine base. Press ^] three times within 1s to exit session.
[root@base ~]#

コンテナ側作業

コンテナ側設定ファイルの作成

CONTAINER: /etc/systemd/network/host0.network

1
2
3
4
5
6
7
8
[Match]
Virtualization=container
Name=host0

[Network]
Address=10.39.252.1/24
Gateway=10.39.252.254
DNS=8.8.8.8

コンテナ側設定コマンドの実行

1
2
3
CONTAINER# ln -s /dev/null /etc/systemd/network/80-container-host0.network
CONTAINER# systemctl enable --now systemd-networkd
CONTAINER# systemctl enable --now systemd-resolved

確認

machinectl

1
2
3
4
5
HOST# machinectl
MACHINE CLASS     SERVICE        OS   VERSION ADDRESSES
base    container systemd-nspawn arch -       10.39.252.1...

1 machines listed.

networkctl(HOST)

1
2
3
4
5
6
7
8
HOST# networkctl
IDX LINK    TYPE     OPERATIONAL SETUP
  1 lo      loopback carrier     unmanaged
  2 eth0    ether    routable    configured
  3 br0     bridge   routable    configured
  4 vb-base ether    carrier     configured

4 links listed.

networkctl(CONTAINER)

1
2
3
4
5
6
CONTAINER# networkctl
IDX LINK  TYPE     OPERATIONAL SETUP
  1 lo    loopback carrier     unmanaged
  2 host0 ether    routable    configured

2 links listed.

ip(HOST)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
HOST# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:60:11:05 brd ff:ff:ff:ff:ff:ff
    inet 10.39.254.249/24 brd 10.39.254.255 scope global dynamic eth0
       valid_lft 364sec preferred_lft 364sec
    inet6 fe80::215:5dff:fe60:1105/64 scope link
       valid_lft forever preferred_lft forever
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 32:74:bf:c5:eb:be brd ff:ff:ff:ff:ff:ff
    inet 10.39.252.254/24 brd 10.39.252.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::3074:bfff:fec5:ebbe/64 scope link
       valid_lft forever preferred_lft forever
4: vb-base@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP group default qlen 1000
    link/ether 26:44:40:f2:da:4c brd ff:ff:ff:ff:ff:ff link-netnsid 0

ip(CONTAINER)

1
2
3
4
5
6
7
8
9
10
11
12
13
CONTAINER# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: host0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether da:5b:0b:b9:45:13 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.39.252.1/24 brd 10.39.252.255 scope global host0
       valid_lft forever preferred_lft forever
    inet6 fe80::d85b:bff:feb9:4513/64 scope link
       valid_lft forever preferred_lft forever

ping(HOST)

1
2
3
4
5
6
7
HOST# ping -c 1 10.39.254.1
PING 10.39.254.1 (10.39.254.1) 56(84) bytes of data.
64 bytes from 10.39.254.1: icmp_seq=1 ttl=64 time=0.278 ms

--- 10.39.254.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.278/0.278/0.278/0.000 ms

ping(CONTAINER)

1
2
3
4
5
6
7
8
9
HOST# machinectl shell base
Connected to machine base. Press ^] three times within 1s to exit session.
CONTAINER# ping -c 1 google.com
PING google.com (172.217.26.110) 56(84) bytes of data.
64 bytes from 172.217.26.110: icmp_seq=1 ttl=54 time=20.0 ms

--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 19.978/19.978/19.978/0.000 ms

変更履歴