備忘録的なもの

nmcli を使って固定 IP アドレスの設定を行う

nmcli を使ってネットワーク設定を行ったので、やったこととその中で気付いたこと等。

諸用で自宅にサーバでも立てるかと思い作業中で、その設定作業の中で固定 IP 設定をするために nmcli を初めて使った。

NetworkManager 自体は普段使っているデスクトップマシンでも使っていたのだが、 インストール時点で特に設定せずとも疎通できていたのと、ちょっと設定弄る場合も GUI で済ませていた。 なので nmcli の存在自体は知ってはいつつ実際に使ったことはなかったのだが、 久しぶりに GUI 無しの Linux で色々設定しているというのもあり、 せっかくなので触ってみようと思った次第。

実際やってみると NetworkManager での connection の概念とか、 GUI だと全然意識してなかったことに気付いたりしたので、 設定作業としてやったこととその中で気付いたこと等をまとめてみる。

nmcli について

文字通り Linux でのネットワーク管理に広く使われている NetworkManger のコマンドラインインターフェース。

コマンドの基本的な使い方としてはこんな感じ。

❯ nmcli help
Usage: nmcli [OPTIONS] OBJECT { COMMAND | help }

OPTIONS
  -a, --ask                                ask for missing parameters
  -c, --colors auto|yes|no                 whether to use colors in output
  -e, --escape yes|no                      escape columns separators in values
  -f, --fields <field,...>|all|common      specify fields to output
  -g, --get-values <field,...>|all|common  shortcut for -m tabular -t -f
  -h, --help                               print this help
  -m, --mode tabular|multiline             output mode
  -o, --overview                           overview mode
  -p, --pretty                             pretty output
  -s, --show-secrets                       allow displaying passwords
  -t, --terse                              terse output
  -v, --version                            show program version
  -w, --wait <seconds>                     set timeout waiting for finishing operations

OBJECT
  g[eneral]       NetworkManager's general status and operations
  n[etworking]    overall networking control
  r[adio]         NetworkManager radio switches
  c[onnection]    NetworkManager's connections
  d[evice]        devices managed by NetworkManager
  a[gent]         NetworkManager secret agent or polkit agent
  m[onitor]       monitor NetworkManager changes

コマンドの途中でも help 付ければ候補や説明を表示してくれる他、コマンドはある程度省略できたりする。(例えば nmcli device status = nmcli d s とか) 1

❯ nmcli d help
Usage: nmcli device { COMMAND | help }

COMMAND := { status | show | set | connect | reapply | modify | disconnect | delete | monitor | wifi | lldp }

  status

  show [<ifname>]

  set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]

...(後略)...

あと全てのディストリビューションでもそうかは確認してないが、 NetworkManager のパッケージに bash 用の補完スクリプトも付属していたので、bash を使ってる場合は設定しておくと良さげ。

❯ pacman -Ql networkmanager | grep completion
networkmanager /usr/share/bash-completion/
networkmanager /usr/share/bash-completion/completions/
networkmanager /usr/share/bash-completion/completions/nmcli

NetworkManager における connection の概念

具体的な設定作業の前に NetworkManager で connection と呼ぶモノについて。

NetworkManager は有線なり Wi-Fi なりの各ネットワークデバイスに対して直接 IP アドレスやルーティング等の設定を行うのではなく、 一旦 connection と呼ばれるプロファイルの様なものを作成し、それを各インターフェースに紐付ける形を取っている。

connectionのイメージ図
こんなイメージ

こうすることで論理的なネットワーク設定を複数持つことができて、 それらの設定を素早く切り替えたりできるのがメリットらしい。

デスクトップ・サーバマシンでそんな頻繁にネットワーク設定を切り替えることがあるとも思えない(自分がそういう経験無いだけかもだが)ので、 どちらかというと持ち運んでいろんなネットワークに繋げて使うノート PC とかを想定した設計だろうか。

設定作業

既存設定の確認

以下の様な感じでネットワークデバイスと、現在有効な connection などを確認できる。

# ネットワークデバイスの一覧とそれに紐付いている connection
❯ nmcli device status
DEVICE           TYPE      STATE         CONNECTION         
eno1             ethernet  connected     Wired connection 1 
wlp58s0          wifi      disconnected  --                 
p2p-dev-wlp58s0  wifi-p2p  disconnected  --                 
lo               loopback  unmanaged     --                 

# 作成されている connection の一覧
❯ nmcli connection show
NAME                UUID                                  TYPE      DEVICE 
Wired connection 1  255ba1f6-55f2-322e-8fa0-701bcf4cecc3  ethernet  eno1

NetworkManager の初回起動時と思われるが、デフォルトで Wired connection 1 という DHCP 接続する connection がすでに作成されている。 今回はこれには手を加えず、新しく connection を作成・切り替える形で設定を行う。

新規 connection の作成

ひとまず connection を作成。

# connection 作成
❯ sudo nmcli connection add con-name wired-static type ethernet
Connection 'wired-static' (7cfee609-e3a0-4853-b69e-a2a9d3b20fee) successfully added.

# connection が作成されたことの確認
❯ nmcli connection show
NAME                UUID                                  TYPE      DEVICE 
Wired connection 1  255ba1f6-55f2-322e-8fa0-701bcf4cecc3  ethernet  eno1   
wired-static        7cfee609-e3a0-4853-b69e-a2a9d3b20fee  ethernet  --     

show や status といった確認コマンドなら不要だが、 add のような変更を伴う場合は root 権限が必要になる。 2 (権限が足りない状態で実行しようとすると Insufficient privileges と言われて失敗する)

パラメータの補足としてはこの辺り

  • con-name
    • コネクションの名前
      • nmcli でコネクションを指定するときは一応 UUID がキーにはなるが、名前で一意に決まるなら名前でも指定できる
      • 同じ名前でコネクションを作成することもできるが、毎回 UUID コピペするのも面倒だし間違いの元なので基本的には被らせないようにするのが無難だろうと思う
    • 省略した場合は type に指定した値が使われるっぽい( ethernet とか)
  • type
    • 接続タイプ( ethernet, wifi, 等)を指定する。 nmcli connection add help とかすると色々あるのが分かる。

作成する接続タイプによってはもう少し必須パラメータがあったりするが、今回作成する ethernet ではひとまずこのくらい。

IPv4 関連の設定

IP アドレス等、各種設定を connection に追加していく。

# IPv4 アドレスの設定
❯ sudo nmcli connection modify wired-static ipv4.addresses 192.168.2.15/24

# IPv4 デフォルトゲートウェイの設定
❯ sudo nmcli connection modify wired-static ipv4.gateway 192.168.2.1

# DNS サーバの設定
❯ sudo nmcli connection modify wired-static ipv4.dns 8.8.8.8
❯ sudo nmcli connection modify wired-static +ipv4.dns 192.168.2.1

# IPv4 の設定方法を auto ( DHCP ) から manual に変更
❯ sudo nmcli connection modify wired-static ipv4.method manual

パラメータの補足

  • ipv4.addresses
    • addresses とある通り複数設定できる
    • CIDR 形式じゃなくても( 192.168.2.15 でも)設定は可能だが 、その場合 /32 として設定される
  • ipv4.dns
    • 値が複数ある場合、今回のようにひとつ設定して + で追加していく形でも設定できるが、 8.8.8.8,192.168.2.1 のようにカンマ区切りでまとめて設定もできる
    • 複数の値を持つパラメータから一部削除する場合は、 -ipv4.dns 8.8.8.8 のように削るか、カンマ区切りで全部列挙して上書きする
  • ipv4.method
    • auto (DHCPで取得) から manual に変更している
    • manual を設定する場合 ipv4.address 等いくつかパラメータが設定されている必要がある

また、今回はパラメータをひとつずつ設定したかったので分けているが、以下の様に複数のパラメータを1行でまとめて設定することもできる。

❯ sudo nmcli connection modify wired-static ipv4.addresses 192.168.2.15/24 ipv4.gateway 192.168.2.1 ipv4.dns 8.8.8.8,192.168.2.1 ipv4.method manual

設定としてはシンプルだが今回はこのくらい。

作成した connection の設定確認

一応作成した connection 設定値を眺めてみる。

PAGER=cat nmcli connection show wired-static
connection.id:                          wired-static
connection.uuid:                        7cfee609-e3a0-4853-b69e-a2a9d3b20fee
connection.stable-id:                   --
connection.type:                        802-3-ethernet
connection.interface-name:              --
connection.autoconnect:                 yes
connection.autoconnect-priority:        0
connection.autoconnect-retries:         -1 (default)

...(中略)...

ipv4.method:                            manual
ipv4.dns:                               8.8.8.8,192.168.2.1
ipv4.dns-search:                        --
ipv4.dns-options:                       --
ipv4.dns-priority:                      0
ipv4.addresses:                         192.168.2.15/24
ipv4.gateway:                           192.168.2.1
ipv4.routes:                            --
ipv4.route-metric:                      -1
ipv4.route-table:                       0 (unspec)
ipv4.routing-rules:                     --

...(後略)...

明示的に設定した部分についてはちゃんと反映されてそうではあるが、 すでに通信できている既存の DHCP 接続( Wired connection 1 )の設定と比較する形でも見てみる。

PAGER=cat diff -U0 <( nmcli connection show "Wired connection 1" ) <( nmcli connection show wired-static )
--- /dev/fd/63	2023-02-04 09:23:23.013572608 +0900
+++ /dev/fd/62	2023-02-04 09:23:23.013572608 +0900
@@ -1,2 +1,2 @@
-connection.id:                          Wired connection 1
-connection.uuid:                        255ba1f6-55f2-322e-8fa0-701bcf4cecc3
+connection.id:                          wired-static
+connection.uuid:                        7cfee609-e3a0-4853-b69e-a2a9d3b20fee
@@ -5 +5 @@
-connection.interface-name:              eno1
+connection.interface-name:              --
@@ -7 +7 @@
-connection.autoconnect-priority:        -999
+connection.autoconnect-priority:        0
@@ -11 +11 @@
-connection.timestamp:                   1675469256
+connection.timestamp:                   0
@@ -43,2 +43,2 @@
-ipv4.method:                            auto
-ipv4.dns:                               --
+ipv4.method:                            manual
+ipv4.dns:                               8.8.8.8,192.168.2.1
@@ -48,2 +48,2 @@
-ipv4.addresses:                         --
-ipv4.gateway:                           --
+ipv4.addresses:                         192.168.2.15/24
+ipv4.gateway:                           192.168.2.1
@@ -101,52 +100,0 @@
-GENERAL.NAME:                           Wired connection 1
-GENERAL.UUID:                           255ba1f6-55f2-322e-8fa0-701bcf4cecc3
-GENERAL.DEVICES:                        eno1
-GENERAL.IP-IFACE:                       eno1
-GENERAL.STATE:                          activated
-GENERAL.DEFAULT:                        yes
-GENERAL.DEFAULT6:                       no
-GENERAL.SPEC-OBJECT:                    --
-GENERAL.VPN:                            no
-GENERAL.DBUS-PATH:                      /org/freedesktop/NetworkManager/ActiveConnection/1
-GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/Settings/1
-GENERAL.ZONE:                           --
-GENERAL.MASTER-PATH:                    --
-IP4.ADDRESS[1]:                         192.168.2.206/24
-IP4.GATEWAY:                            192.168.2.1
-IP4.ROUTE[1]:                           dst = 192.168.2.0/24, nh = 0.0.0.0, mt = 100
-IP4.ROUTE[2]:                           dst = 0.0.0.0/0, nh = 192.168.2.1, mt = 100
-IP4.DNS[1]:                             8.8.8.8
-IP4.DNS[2]:                             192.168.2.1
-DHCP4.OPTION[1]:                        broadcast_address = 192.168.2.255
-DHCP4.OPTION[2]:                        dhcp_client_identifier = 01:1c:69:7a:0c:f9:89
-DHCP4.OPTION[3]:                        dhcp_lease_time = 86400
-DHCP4.OPTION[4]:                        dhcp_server_identifier = 192.168.2.1
-DHCP4.OPTION[5]:                        domain_name_servers = 8.8.8.8 192.168.2.1
-DHCP4.OPTION[6]:                        expiry = 1675555656
-DHCP4.OPTION[7]:                        host_name = nuc
-DHCP4.OPTION[8]:                        ip_address = 192.168.2.206
-DHCP4.OPTION[9]:                        next_server = 192.168.2.1
-DHCP4.OPTION[10]:                       requested_broadcast_address = 1
-DHCP4.OPTION[11]:                       requested_domain_name = 1
-DHCP4.OPTION[12]:                       requested_domain_name_servers = 1
-DHCP4.OPTION[13]:                       requested_domain_search = 1
-DHCP4.OPTION[14]:                       requested_host_name = 1
-DHCP4.OPTION[15]:                       requested_interface_mtu = 1
-DHCP4.OPTION[16]:                       requested_ms_classless_static_routes = 1
-DHCP4.OPTION[17]:                       requested_nis_domain = 1
-DHCP4.OPTION[18]:                       requested_nis_servers = 1
-DHCP4.OPTION[19]:                       requested_ntp_servers = 1
-DHCP4.OPTION[20]:                       requested_rfc3442_classless_static_routes = 1
-DHCP4.OPTION[21]:                       requested_root_path = 1
-DHCP4.OPTION[22]:                       requested_routers = 1
-DHCP4.OPTION[23]:                       requested_static_routes = 1
-DHCP4.OPTION[24]:                       requested_subnet_mask = 1
-DHCP4.OPTION[25]:                       requested_time_offset = 1
-DHCP4.OPTION[26]:                       requested_wpad = 1
-DHCP4.OPTION[27]:                       routers = 192.168.2.1
-DHCP4.OPTION[28]:                       subnet_mask = 255.255.255.0
-DHCP4.OPTION[29]:                       wpad = 
-
-IP6.ADDRESS[1]:                         fe80::4b2:8103:9857:8c55/64
-IP6.GATEWAY:                            --
-IP6.ROUTE[1]:                           dst = fe80::/64, nh = ::, mt = 1024

差分としては、

  • connection.* 辺りの値は NetworkManger での管理上の値っぽいので問題無し
  • ipv4.* 辺りは今回明示的に設定した部分なので問題無し
  • GENERAL.* 辺りは connection.* と似たようなモノっぽいので問題無し
  • IPV4.* DHCP.* IP6.* 辺りは DHCP で取得したものっぽいので多分問題無し

ということで大丈夫そう。

眺めた感じ小文字部分が connection の設定値で、 大文字部分が DHCP 等動的に取得したもの等も含めた最終的な値って感じだろうか。

connection の切替

最後にネットワーク設定を切り替える。

切替前の状態を見ておく。

# ネットワークデバイスと設定されている connection
❯ nmcli device status
DEVICE           TYPE      STATE         CONNECTION         
eno1             ethernet  connected     Wired connection 1 
wlp58s0          wifi      disconnected  --                 
p2p-dev-wlp58s0  wifi-p2p  disconnected  --                 
lo               loopback  unmanaged     --                 

# 今のIPアドレス等
❯ ip address show eno1
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 1c:69:7a:0c:f9:89 brd ff:ff:ff:ff:ff:ff
    altname enp0s31f6
    inet 192.168.2.206/24 brd 192.168.2.255 scope global dynamic noprefixroute eno1
       valid_lft 85068sec preferred_lft 85068sec
    inet6 fe80::4b2:8103:9857:8c55/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

実際に切り替える

# 今回作成した connection を有線ネットワークデバイス( eno1 )に紐付ける
❯ sudo nmcli connection modify wired-static ifname eno1

# wired-connection を有効化する(同じネットワークデバイスに紐付いた別の connection が active になっている場合はこのタイミングで自動で inactive になる)
❯ sudo nmcli connection up wired-static
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/2)

ちゃんと切り替わったか確認

# 有線ネットワークデバイス( eno1 ) に今回作成した connection ( wired-static ) が適用されている
❯ nmcli device status
DEVICE           TYPE      STATE         CONNECTION   
eno1             ethernet  connected     wired-static 
wlp58s0          wifi      disconnected  --           
p2p-dev-wlp58s0  wifi-p2p  disconnected  --           
lo               loopback  unmanaged     --           

# connection 一覧からも確認
❯ nmcli connection show
NAME                UUID                                  TYPE      DEVICE 
wired-static        7cfee609-e3a0-4853-b69e-a2a9d3b20fee  ethernet  eno1   
Wired connection 1  255ba1f6-55f2-322e-8fa0-701bcf4cecc3  ethernet  --     

# IP アドレスも想定通りになっている
❯ ip address show eno1
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 1c:69:7a:0c:f9:89 brd ff:ff:ff:ff:ff:ff
    altname enp0s31f6
    inet 192.168.2.15/24 brd 192.168.2.255 scope global noprefixroute eno1
       valid_lft forever preferred_lft forever
    inet6 fe80::339e:3e8f:5bc9:ff5/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

# インターネット上の適当なところへ疎通確認
❯ ping google.com
PING google.com (172.217.26.238) 56(84) bytes of data.
64 bytes from nrt12s51-in-f14.1e100.net (172.217.26.238): icmp_seq=1 ttl=116 time=2.89 ms
64 bytes from nrt12s51-in-f14.1e100.net (172.217.26.238): icmp_seq=2 ttl=116 time=3.14 ms
64 bytes from nrt12s51-in-f14.1e100.net (172.217.26.238): icmp_seq=3 ttl=116 time=3.29 ms
^C
--- google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 2.889/3.105/3.288/0.164 ms

ということで設定完了。

コマンドまとめ

補足や出力結果で間延びした感があるので、改めて設定コマンドのみを抜粋

nmcli device status
nmcli connection show

sudo nmcli connection add con-name wired-static type ethernet

sudo nmcli connection modify wired-static ipv4.addresses 192.168.2.15/24
sudo nmcli connection modify wired-static ipv4.gateway 192.168.2.1
sudo nmcli connection modify wired-static ipv4.dns 8.8.8.8
sudo nmcli connection modify wired-static +ipv4.dns 192.168.2.1
sudo nmcli connection modify wired-static ipv4.method manual

sudo nmcli connection modify wired-static ifname eno1
sudo nmcli connection up wired-static

余談

自動で作成される connection ( Wired connection 1 )について

作業時点で既に作成されていた Wired connection 1 (日本語ロケールだと 有線接続1 )という connection だが、 今回の wired-static を作成した後でシステムを再起動すると消えていた。 ( NetworkManager.service の再起動では残っていた)

❯ nmcli connection show
NAME                UUID                                  TYPE      DEVICE 
wired-static        7cfee609-e3a0-4853-b69e-a2a9d3b20fee  ethernet  eno1   

で、試しに作った connection を削除して NetworkManager を再起動してみるとまた現れた。

こんな感じ。

# connection を削除
❯ sudo nmcli connection delete wired-static
Connection 'wired-static' (7cfee609-e3a0-4853-b69e-a2a9d3b20fee) successfully deleted.

# connection が一つも無いのを確認
❯ nmcli connection show

# device の方でも確認
❯ nmcli device status
DEVICE           TYPE      STATE         CONNECTION 
eno1             ethernet  disconnected  --         
wlp58s0          wifi      disconnected  --         
p2p-dev-wlp58s0  wifi-p2p  disconnected  --         
lo               loopback  unmanaged     --         

# NetworkManager.service を再起動
❯ sudo systemctl restart NetworkManager.service

# 改めて connection を確認すると勝手にできている
❯ nmcli connection show
NAME                UUID                                  TYPE      DEVICE 
Wired connection 1  255ba1f6-55f2-322e-8fa0-701bcf4cecc3  ethernet  eno1   

また、 nmcli connection add 〜 で connection を作成した場合は以下の様に設定ファイルが作られるが、 自動で設定された Wired connection 1 のファイルは作られない。

❯ nmcli connection show
NAME                UUID                                  TYPE      DEVICE 
wired-static        f7d3fe23-2c70-4025-aa59-38f65a365f8b  ethernet  eno1   
Wired connection 1  255ba1f6-55f2-322e-8fa0-701bcf4cecc3  ethernet  --     

❯ sudo ls -lh /etc/NetworkManager/system-connections/
total 4.0K
-rw------- 1 root root 252 Feb  4 11:38 wired-static.nmconnection

この辺りを考えると自動で設定を作成しているというよりは、一時的な設定を行っているという理解が正しそう。

GUI で設定してた時は特に意識せずこの Wired connection 1 を直接弄ったりしていたが、 設定を弄るなら別で connection を作って設定した方が良いのかもしれない。 (これまで GUI で弄っていて突然設定が飛んだみたいな記憶は無いので、 connection ひとつで使っている分には実際に困ることは無いのかもだが気分的に)

この辺りはもう少しドキュメント追うなり試すなりしても良いかもしれない。

自動接続設定について

今回の作業の中では特に必要なかったので省略したが、 自動接続するかどうかや、自動接続する connection が複数ある場合にどの connection を優先して使うかはこの辺りのパラメータで制御できるっぽい。 (明示的に設定しなかった場合は以下の値になる)

❯ nmcli connection show wired-static | grep autoconnect
connection.autoconnect:                 yes
connection.autoconnect-priority:        0
connection.autoconnect-retries:         -1 (default)
connection.autoconnect-slaves:          -1 (default)

ノートPC の Wi-Fi の設定は NetworkManager の GUI で設定したが、 どの SSID に優先して繋ぐとかも細かく設定できそうなので眺めてみても良さそう。 (特に意識せず設定した場合にどうなるかというのを見る意味も含めて)

おわりに

やったこと自体は「固定 IP アドレスを設定した」だけなので大したことはやってないのだが意外と学びはあった。 (具体的に今後何かの役に立つかは微妙だが)


  1. IOS とかのコマンドが似たような操作だが Linux のコマンドだとあんまりこのスタイル見ない気がする。 ↩︎

  2. 今回記事の中で設定したマシンとは別のマシン(普段デスクトップとして使っているヤツ)では sudo 無しで connection の作成などができていた。そちらではデスクトップ環境として Xfce をインストールしているのでその辺りの関係な気はするが。 ↩︎