Armadilloフォーラム

独自DHCPクライアントでのIPアドレス取得

yhashi1977

2024年6月10日 15時49分

Armadillo-610(ABOS)のコンテナを作成し、独自のDHCPクライアントを動作させて、
ホスト側のIPアドレスを設定させたいです。

ホスト側のDHCPを無効にして、
コンテナからDHCPDISCOVERをソケットで送信しようとしましたが、
sendto()でエラーとなりました。
エラーメッセージ:Network is unreachable

コンテナのconfファイルにてネットワークは
set_network host
としています。

ホスト側のDHCPを有効にすると
DHCPDISCOVERを送信できるようになり、ルーターからDHCPOFFERが返ってきますが、
コンテナ側で、DHCPのポート68を受信する処理を入れると、
bind()でエラーとなります。
エラーメッセージ:Address already in use

コンテナを使って、独自DHCPクライアントによるホスト側のIPアドレス設定は
できないのでしょうか?

ABOSを使用しなければ、上記目的は達成できますでしょうか?

コメント

at_dominique.m…

2024年6月10日 16時19分

yhashi1977さん

お世話になっています、
マルティネです。

> Armadillo-610(ABOS)のコンテナを作成し、独自のDHCPクライアントを動作させて、
> ホスト側のIPアドレスを設定させたいです。

好奇心で聞きますが、NetworkManager で設定できない dhcp のオプションがありますでしょうか?
コンテナで独自の DHCP クライアントは使えますが、
標準のソフトでできればそちらの方がいいと思いますので、
説明が面倒でなければ聞きます。

> ホスト側のDHCPを無効にして、
> コンテナからDHCPDISCOVERをソケットで送信しようとしましたが、
> sendto()でエラーとなりました。
> エラーメッセージ:Network is unreachable

NET_RAW の権限をコンテナに渡していますか?
IP を取得できてインタフェースに設定するには NET_ADMIN も必要になりますので、
まだ設定されてなかったらコンテナの conf ファイルにこれを追加してみてください:

add_args --cap-add NET_RAW
add_args --cap-add NET_ADMIN

試しに、このコンフィグで busybox udhcpc をコンテナから起動できました。

ちなみに、 DNS サーバーの設定も面倒になりますが、/etc/dnsmasq.d/custom.conf 等に
「resolv-file=/var/app/volumes/dnsmasq/resolv.conf」等にして、
/var/app/volumes/dnsmasq をコンテナのボリュームとしてマウントすれば dnsmasq はそれを編集する時に拾ってくれます。
/etc/dnsmasq.d/dns.conf の設定に NetworkManager が管理する別の resolv.conf が入ってますが、
NetworkManager が別のインターフェスでサーバーを取得しなければ更新されないのでファイルが無視されます。
仕組みとしては、最新のファイルが使用されます。
/etc/dnsmasq.d/dns.conf を編集してもいいですが、その場合は preserve_file -P (Armadillo Base OS 更新の際に
armadillo側のファイルを優先する) で保存してください。分かりにくい実装ですみません…)

> ホスト側のDHCPを有効にすると
> DHCPDISCOVERを送信できるようになり、ルーターからDHCPOFFERが返ってきますが、
> コンテナ側で、DHCPのポート68を受信する処理を入れると、
> bind()でエラーとなります。
> エラーメッセージ:Address already in use

これは仕方ないですね、できたとしてもホスト側かコンテナ側が返事をもらう側を選べないので、
そういう2重起動を推奨できません。

よろしくお願いします。

yhashi1977

2024年6月12日 16時11分

マルティネさん
ご返信ありがとうございます。

結論から言うと自己解決しました。

> 好奇心で聞きますが、NetworkManager で設定できない dhcp のオプションがありますでしょうか?
> コンテナで独自の DHCP クライアントは使えますが、
> 標準のソフトでできればそちらの方がいいと思いますので、
> 説明が面倒でなければ聞きます。

NetworkManagerでDHCPのオプションエリアの変更ができるのですね。
DHCPサーバに対して送らないオプションもあったので、
独自で作成する必要があると思いチャレンジしています。

> NET_RAW の権限をコンテナに渡していますか?
> IP を取得できてインタフェースに設定するには NET_ADMIN も必要になりますので、
> まだ設定されてなかったらコンテナの conf ファイルにこれを追加してみてください:
>

> add_args --cap-add NET_RAW
> add_args --cap-add NET_ADMIN
> 

NET_RAWとNET_ADMINは設定済みでした。
> sendto()でエラーとなりました。
> エラーメッセージ:Network is unreachable
この原因はネットワークが接続状態になっていなかったためのようです。
nmcliでipv4.methodをdisableに設定していましたが、
ipv4.methodをmanualに設定し、固定IPを設定することで
このエラーは出なくなりました。

> > ホスト側のDHCPを有効にすると
> > DHCPDISCOVERを送信できるようになり、ルーターからDHCPOFFERが返ってきますが、
> > コンテナ側で、DHCPのポート68を受信する処理を入れると、
> > bind()でエラーとなります。
> > エラーメッセージ:Address already in use
固定IPにすることで、このエラーも出なくなりました。

ipv4.gatewayのアドレスをDHCPサーバのIPアドレスにすることで、
DHCPDISCOVERがDHCPサーバ(ルーター)に到達し、
DHCPOFFERを受信することが確認できました。

以上、ありがとうございました。

yhashi1977

2024年7月2日 15時20分

マルティネさん

先日、コンテナ上の独自DHCPクライアントを作成し
DHCPサーバからDHCPACKの受信までできたのですが、
その後の処理として、ホストのIPアドレス、サブネットマスクの設定は
ioctlソケットにより設定しました。
但しこの状態ではpingが通らない状況なので、ルーティングの設定が必要かと認識していますが
Linuxとネットワークの知見が足らず、どうコーディングして良いかわからない状況です。

代案として、独自DHCPクライアントがIPアドレスを取得したら
NetworkManagerを介して、ネットワークの設定をさせたいと思い、
独自DHCPクライアントが動作するコンテナからnmcliコマンドを実行できるか試しました。

結果として、コンテナにNetworkManagerをインストール後コンテナに入り、
nmcliコマンドを実行したところ下記エラーが表示されました。

# nmcli
Error: Could not create NMClient object: Could not connect: No such file or directory.

このエラーは/etc/NetworkManager/system-connections/に何もファイルが無い状態
(コンテナ上でnmcli con addをしていない状態)という認識ですが、
コンテナとホストOSで、NetworkManagerのconnectionsを共有することは可能でしょうか?

または、コンテナからホストOSのconnectionsの設定を変更する方法はありますでしょうか?

以上、よろしくお願いいたします。

at_dominique.m…

2024年7月2日 16時06分

yhashi1977さん

マルティネです。

> このエラーは/etc/NetworkManager/system-connections/に何もファイルが無い状態
> (コンテナ上でnmcli con addをしていない状態)という認識ですが、
> コンテナとホストOSで、NetworkManagerのconnectionsを共有することは可能でしょうか?
>
> または、コンテナからホストOSのconnectionsの設定を変更する方法はありますでしょうか?

コンテナにホストの /run/dbus/system_bus_socket を共有すれば理論上はコンテナからもアクセスできますが、その場合は networkmanager のバージョンが変わると動かなくなる可能性がありますので、あまり推奨していません。

ABOS Web でよろしければそちらの Rest API でネットワーク設定を変更できます:
https://manual.atmark-techno.com/armadillo-iot-g4/armadillo-iotg-g4_pro…
「 ネットワーク接続の変更」を検索(ちょうど IP アドレスを設定していますが、今回は ipv4.gateway も設定する必要があります)

問題点としては、ABOS Web で設定を行うと設定がホストに保存されてしまって、再起動すれば再び ip が設定されてしまいますので、lease ない状態で ip アドレスが設定される恐れがあります。

なので、結果てきには NetworkManager でインターフェースを無効化したままにして、
実装自体はコマンドでできるようですので 「ip route add default via [gateway] dev [interface]」で
route を直接に追加した方がリスクが低いと思います。

複雑な routing 情報が必要でしたら ip コマンドも多少複雑になりますが、nmcli の設定でも似たような内容になりますので、
実装としてはそれほど変わらないと思います。

でも確かに、DNS の設定なども考えたら networkmanager 経由で設定した方がシンプルになりそうですね…
再起動の際に IP が設定されることで問題なければ ABOS Web を試してみてください。

よろしくお願いします。

yhashi1977

2024年7月2日 20時51分

マルティネさん

ご回答ありがとうございます。

> なので、結果てきには NetworkManager でインターフェースを無効化したままにして、
> 実装自体はコマンドでできるようですので 「ip route add default via [gateway] dev [interface]」で
> route を直接に追加した方がリスクが低いと思います。

現在の状態から一番手っ取り早く試せると思い、上記の方法で試そうと思います。
下記コマンドに相当する固定IPの設定をNetworkManagerを使わないで永続化する方法はありますでしょうか?

ip address add [ip address]/[mask] dev [interface]
ip route add default via [gateway] dev [interface]

以上、よろしくお願いいたします。

at_dominique.m…

2024年7月3日 10時01分

yhashi1977さん

> 現在の状態から一番手っ取り早く試せると思い、上記の方法で試そうと思います。
> 下記コマンドに相当する固定IPの設定をNetworkManagerを使わないで永続化する方法はありますでしょうか?

すみません、DHCP の場合はアドレスの永続化は行いたくないだろうと思い込んでいましたので、ip コマンドを提案していました。
(DHCP の lease が切れた状態でサーバーが別の機械に同じアドレスを割合えた場合に、armadillo が起動して昔のアドレスを使ってしまったらかなり分かりにくいことになります。)

永続化が希望であれば、コンテナのボリュームディレクトリに設定を覚えてコンテナの起動に同じ ip コマンドを実行するか、やはり ABOS Web を使っていただいた方がいいと思います。
eth0 の場合はこういうコマンドで設定かつ永続化されますので、トークンの設定で少しお手数をおかけしますが結果的には楽な方向だと考えています(マニュアルの例にゲートウェイを追加しただけです)

AUTH="Authorization: Bearer 35ac39a8-1eeb-4bb2-84d2-cb542cdbc873"
alias curl_rest='curl -k -H "$AUTH" -w "\nhttp code: %{http_code}\n" '
curl_rest -X PATCH -d ipv4.method=manual -d ipv4.addresses=198.51.100.123/16 -d ipv4.gateway=198.51.100.1 https://armadillo.local:58080/api/connections/Wired%20connection%201

余計なお世話かもしれませんが、個人的な意見としてはやはり永続化はあまりしない方がいいかと思いますが、詳細が分かりませんのでこれ以上言えません。

また、以前の回答では NetworkManager のDHCPクライアントに追加のオプションを設定できないかって聞いていましたが、少し確認してみたところ確かに ABOS で使っている internal の NetworkManager内のクライアントでは設定できなさそうですね…
これも個人の興味に過ぎないですが https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1… に聞いてみました。お差し支えなければ、具体的に設定する必要なオプションを教えていただけますでしょうか?(224 以上の場合は「private」だけでいいです)
そのチケットを作った際に udhcpc で任意のオプションを設定・リクエストできることを気づいたので、network=host + NET_ADMIN のコンテナで udhcpc を使うことも可能だと思いますが、いかがでしょうか?

よろしくお願いします。

yhashi1977

2024年7月3日 11時07分

マルティネさん

ご返信ありがとうございます。

> yhashi1977さん
>
> > 現在の状態から一番手っ取り早く試せると思い、上記の方法で試そうと思います。
> > 下記コマンドに相当する固定IPの設定をNetworkManagerを使わないで永続化する方法はありますでしょうか?
>
> すみません、DHCP の場合はアドレスの永続化は行いたくないだろうと思い込んでいましたので、ip コマンドを提案していました。
> (DHCP の lease が切れた状態でサーバーが別の機械に同じアドレスを割合えた場合に、armadillo が起動して昔のアドレスを使ってしまったらかなり分かりにくいことになります。)
>

やりたいことは、下記ですが、なんとか行けそうな気がしてきました。
1.独自DHCPクライアント(コンテナ)が通信できるように、予めホストは固定IPに設定しておく(永続化)
2.独自DHCPクライアントがDHCPサーバからIPアドレス取得できたら、leaseは/var/app/volumes/にファイルで保存する
3.IPコマンドで、ホスト側のIPアドレス、ゲートウェイを書き換える(この設定は永続化せず起動後毎回実行する)

1については調べたところ、OpenRCの設定で、NetworkManagerは無効にして、Networkingを有効にすることでできそうです。
以下コマンドでNetworkManagerを自動起動しないようにして、代わりにNetworkingを自動起動するようにしました。

rc-update del networkmanager boot
rc-update add networking boot

下記コマンドでIP設定と自動起動設定を永続化

persist_file /etc/network/interfaces
persist_file -r /etc/runlevels/boot/networkmanager
persist_file /etc/runlevels/boot/networking

> また、以前の回答では NetworkManager のDHCPクライアントに追加のオプションを設定できないかって聞いていましたが、少し確認してみたところ確かに ABOS で使っている internal の NetworkManager内のクライアントでは設定できなさそうですね…

NetworkManagerを有効にしていた際は、下記設定でオプション設定でき、独自DHCPサーバからIP取得はできました。

nmcli con mod [コネクション名] ipv4.dhcp-client-id [クライアントID]

ですが、今回の仕様では、DHCPACKのDHCPヘッダ内のServer Name(64byte)を保持しなければならず
いろいろ検討した結果、IP取得までは独自DHCPクライアントで行い、インタフェース設定、ルーティングはコマンドで実施する方針で進めています。

以上、よろしくお願いいたします。

at_dominique.m…

2024年7月3日 12時31分

yhashi1977さん

> やりたいことは、下記ですが、なんとか行けそうな気がしてきました。
> 1.独自DHCPクライアント(コンテナ)が通信できるように、予めホストは固定IPに設定しておく(永続化)
> 2.独自DHCPクライアントがDHCPサーバからIPアドレス取得できたら、leaseは/var/app/volumes/にファイルで保存する
> 3.IPコマンドで、ホスト側のIPアドレス、ゲートウェイを書き換える(この設定は永続化せず起動後毎回実行する)

はい、それでいいと思います.

> 1については調べたところ、OpenRCの設定で、NetworkManagerは無効にして、Networkingを有効にすることでできそうです。

はい、それはできますが、ABOS を更新するとまた有効になってしまうので ABOS のコアサービスの部分をあまり変更しない方がいいです。

NetworkManager での eth0 の無効化は /etc/NetworkManager/conf.d/00_disable_podman.conf 等を参考にして、
以下のように無効化すれば更新しても無効化されます:

armadillo:~# vi /etc/NetworkManager/conf.d/50_disable_eth0.conf
[device_eth0]
match-device=interface-name:eth0
managed=0
armadillo:~# persist_file -pv /etc/NetworkManager/conf.d/50_disable_eth0.conf
Added "/etc/NetworkManager/conf.d/50_disable_eth0.conf" to /etc/swupdate_preserve_files
'/mnt/etc/NetworkManager/conf.d/50_disable_eth0.conf' -> '/target/etc/NetworkManager/conf.d/50_disable_eth0.conf'

また NetworkManager を試したい場合はファイルを削除もできますし、一時的な確認であれば「nmcli d set eth0 managed yes」で変更できます。

(今考えたら、自動コネクトになってない接続でもいいかもしれません..)

> NetworkManagerを有効にしていた際は、下記設定でオプション設定でき、独自DHCPサーバからIP取得はできました。
>

> nmcli con mod [コネクション名] ipv4.dhcp-client-id [クライアントID]
> 

> ですが、

なるほど、 duid だけでしたね。

> 今回の仕様では、DHCPACKのDHCPヘッダ内のServer Name(64byte)を保持しなければならず

/etc/NetworkManager/dispatcher.d に新しいスクリプトを追加して、$2 が dhcp4-change の場合に環境変数で返事内容が全て取得できるはずです。
一度 env > /tmp/log 等で変数の名前を確認できます。
(server nameという dhcp option は見つかりませんでしたが、224 で試して「DHCP4_PRIVATE_224」にありました。クライアント側がそのオプションをリクエストせずにサーバーが情報を送ってくれればいいんですが..)

とりあえず別の方向でできそうですので今更無理に切り替えなくていいと思いますが、
またその機会があれば…

よろしくお願いします。