コンテナのインターフェイスを含む、Linuxで設定されているすべてのインターフェイスを見つける方法は?

コンテナのインターフェイスを含む、Linuxで設定されているすべてのインターフェイスを見つける方法は?

次の手順でインターフェイスを表示できることがわかりますip a show。これにはホストが表示できるインターフェイスのみが表示され、コンテナで構成された仮想インターフェイスはこのリストには表示されません。また、試してみましたが、ip netnsどちらも表示されません。別のバージョンを再コンパイルする必要がありますかiproute2/proc/net/fb_trieローカル/ブロードキャストアドレスが転送データベースとして使用されていることがわかります。

この情報またはすべてのインターフェイス(コンテナを含む)を一覧表示するコマンドはどこにありますか?

これをテストするには、コンテナを起動してください。私の場合は、スナップのlxcコンテナでした。ip aまたはを作成してくださいip l。ホストビューは表示されますが、コンテナ構成へのインターフェイスは表示されません。コンテナは単にcgroupedプロセスなので、grepingしていますが、procfsarpエントリ以外には何も得られません。fib_trie私はこれがnetns名前空間の混乱のためかもしれないと思いましたが、ip netnsそれも何も表示されません。

conntrack -Llxdはパケット転送のための接続追跡を必要とするので、確立されたすべての着信および発信接続を表示するために使用できますが、またはを使用してわかるnetstat方法など、システムに設定されているすべてのIPアドレスを一覧表示したいと思いますlsof

答え1

与えられた時間のインタフェースは次のとおりです。ネットワークネームスペースそしてただ一つだけです。 init(初期)ネットワークネームスペースには、破壊されたネットワークネームスペースの物理インターフェイスを継承する以外に、他のネットワークネームスペースの特別な機能はありません。インターフェイスを直接表示できません。 initのpidおよびmountネームスペースにある限り、利用可能な他の情報を使用してネットワークネームスペースを見つけることができ、/proc最終的にそのネットワークネームスペースを入力してそのインターフェースを表示できます。

シェルで例を提供します。

  • ネットワークネームスペースの列挙

    これを行うには、リソースが名前空間を維持できる限り、これらの名前空間がどのように存在するかを知る必要があります。ここで、リソースはプロセス(実際にはプロセスのスレッド)、マウントポイント、またはオープンファイル記述子(fd)です。これらのリソースは、すべての名前空間を列挙し、/proc/抽象擬似ファイルを指す擬似ファイルシステムで参照されます。nsfsファイルに関する唯一の意味のある情報は、ネットワーク名前空間を表す対応するinodeです。ただし、inodeはそれ自体では機能できず、ファイルでなければなりません。そのため、後でinode値(で提供)のみを維持することはできませんstat -c %i /proc/some/file。重複エントリを削除できるように inode を維持します。そしてまだ利用可能な参照を持つファイル名nsenter後。

    • プロセス(実際にはスレッド)

      最も一般的な場合:一般的なコンテナの場合。各スレッドのネットワーク名前空間は参照として知られています/proc/pid/ns/net。これをインポートして、stat固有の名前空間をすべて列挙するだけです。一時プロセスが見つからない場合は非2>/dev/null表示にします。stat

      find /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do
              stat -L -c '%20i %n' $procpid/ns/net
      done 2>/dev/null
      

      特化したスキルでより速くできます。lsnsこのコマンドは名前空間を処理しますが、プロセスのみを処理するようです(以下に示すように、マウントポイントやオープンfdではありません)。

      lsns -n -u -t net -o NS,PATH
      

      (後で再フォーマットする必要がありますlsns -n -u -t net -o NS,PATH | while read inode path; do printf '%20u %s\n' $inode "$path"; done

    • マウントポイント

      これは、マウントを介して永続ネットワーク名前空間を生成するコマンドに主に使用されます。ip netns addこれにより、それを保持するプロセスやfdリソースがない場合に消えるのを防ぎ、たとえばネットワーク上でルーター、ファイアウォール、またはブリッジを実行することもできます。関連付けられたプロセスがない名前空間です。

      マウントされた名前空間(マウント処理とpid名前空間処理はより複雑になるかもしれませんが、とにかくネットワーク名前空間にのみ興味がある)は、ファイルシステム/proc/mountsタイプの他のマウントポイントと似ていますnsfs。シェルでは、ネットワーク名前空間と異なる種類の名前空間を区別する簡単な方法はありませんが、nsfs同じファイルシステム(ここ)の両方の擬似ファイルは同じinodeを共有しないため、両方を選択して後で無視するだけです。ネットワーク以外の名前空間参照をネットワーク名前空間ステップとして使用しようとしたときのインタフェース。申し訳ありません。以下は、特殊文字(スペースを含む)を含むマウントポイントを正しく処理しません。これはすでに/proc/mounts出力からエスケープされているためです(他の言語では簡単になります)。したがって、null 出口を使用しません。ワイヤー。

      awk '$3 == "nsfs" { print $2 }' /proc/mounts | while read -r mount; do
              stat -c '%20i %n' "$mount"
      done
      
    • オープンファイル記述子

      名前空間の作成時に一時的に除外される場合を除き、マウントポイントよりもまれですが、複数の名前空間を処理する一部の特殊アプリケーション(一部のコンテナ化技術を含む)で保持して使用できます。

      /proc/pid/fd/すべてで利用可能なすべてのfdを検索し、statを使用してそれがネームスペースを指していることを確認しnsfs、それが実際にネットワークネームスペースであるかどうかをもう気にしないよりも良い方法を考案することはできません。より最適化されたループがあると確信していますが、少なくとも前後に移動したり、最大プロセス制限を想定していないループです。

      find /proc/ -mindepth 1 -maxdepth 1 -name '[1-9]*' | while read -r procpid; do
              find $procpid/fd -mindepth 1 | while read -r procfd; do
                      if [ "$(stat -f -c %T $procfd)" = nsfs ]; then
                              stat -L -c '%20i %n' $procfd 
                      fi
              done
      done 2>/dev/null
      

    これで、前の結果から重複したネットワーク名前空間参照をすべて削除します。たとえば、最初の3つの結果の結合出力(特に開かれたファイル記述子セクション)にこのフィルタを使用すると、次のようになります。

    sort -k 1n | uniq -w 20
    
  • 各名前空間のインタフェースを列挙する

    すべての既存のネットワーク名前空間(および無視するネットワークではなく一部の名前空間)への参照があるので、参照を使用して各名前空間を入力してインターフェイスを表示するだけです。

    前のコマンドの出力をこのループへの入力として使用し、前述のようにビネットワークの名前空間に起因するエラーを無視しながらインターフェイスを列挙します(OPの質問に従ってそのアドレスを表示するように選択します)。

    while read -r inode reference; do
        if nsenter --net="$reference" ip -br address show 2>/dev/null; then
                printf 'end of network %d\n\n' $inode
        fi
    done
    

pid 1を参照として使用して、initネットワークのinodeを印刷できます。

echo -n 'INIT NETWORK: ' ; stat -L -c %i /proc/1/ns/net

実行中のLXCコンテナの出力例(実際の編集済み)、ip netns add ...接続されていないブリッジインターフェイスを持つ空の「マウントされた」ネットワークネームスペース、プロセスdummy0によってアクティブに保たれる他のインターフェイスを持つネットワークネームスペースいいえこれはネットワークネームスペースにありますが、次のように作成されたオープンfdを残します。

unshare --net sh -c 'ip link add dummy0 type dummy; ip address add dev dummy0 10.11.12.13/24; sleep 3' & sleep 1; sleep 999 < /proc/$!/ns/net &

そしてloFirefoxは、接続されていないネットワークネームスペース(すべてのダウンストリームインターフェイス)に分離された各「Webコンテンツ」スレッドを使用して実行されます。

不明127.0.0.1/8::1/128
eth0 の 192.0.2.2/24 2001:db8:0:1:bc5c:95c7:4ea6:f94f/64 fe80::b4f0:7aff:fe76:76a8/64
無線LAN0オフ           
dummy0 不明 198.51.100.2/24 fe80::108a:83ff:fe05:e0da/64
lxcbr0 10.0.3.1/24 2001:db8:0:4::1/64 fe80::216:3eff:fe00:0/64
virbr0 ダウン 192.168.122.1/24
virbr0-nic ダウン           
vethSOEPSH@if9 UP fe80::fc8e:ff:fe85:476f/64
ネットワークエンド 4026531992

低い           
ネットワークエンド 4026532418

低い           
ネットワークエンド 4026532518

低い           
ネットワークエンド 4026532618

低い           
ネットワークエンド 4026532718

不明127.0.0.1/8::1/128
eth0@if10 最大 10.0.3.66/24 fe80::216:3eff:fe6a:c1e9/64
ネットワークエンド 4026532822

低い           
ブリッジ0 不明 fe80::b884:44ff:feaf:dca3/64
ネットワークエンド 4026532923

低い           
仮想0が10.11.12.13/24削除されました
ネットワークエンド 4026533021

ネットワーク初期化: 4026531992

答え2

ip netns listユーティリティで設定されたネットワーク名前空間のみが一覧表示されますip-netns(8)

lsns(1)パッケージに含まれるutil-linuxプログラム真剣に足りない/proc/<pid>/ns/*:すべてのスレッド固有の名前空間と、バインドマウントまたは開かれたファイル記述子を介して保持される名前空間を無視し、ファイルを介してアクセスできる名前空間のみを一覧表示します。

次のデモスクリプトは、1つのより良い操作を試みます。ファイルを介してバインドマウントを探し、ファイルを介して/proc/<pid>/task/<tid>/mountinfo開いたfdを見つけます。/proc/<pid>/task/<tid>/fd

各名前空間に対して、その名前空間にアクセスできるパスを印刷します。

# perl ./lsnsx.pl
...
mnt      3
   4026531840  /proc/1/ns/mnt
   4026531860  /proc/30/ns/mnt
   4026532374  /proc/3119/ns/mnt
net      6
   4026531992  /proc/1/ns/net
   4026532376  /proc/25781/fd/9
   4026532465  /proc/28373/fd/7
...

その後、そのパスを使用できますnsenter(1)

nsenter --net=/proc/28373/fd/7 ip link

これを直接実行したり、名前空間を使用したプロセス全体のリストなどの追加情報を表示するようにスクリプトを簡単に変更したりできます。

/proc/<pid>/mountinfoパスにアクセスできない場合は、親/マウントIDとパスを見つけたファイルが続きます。エスケープされた改行、タブ、スペースはそのまま残ります。

net      9
   ...
   4026532732  /v/net\040ns   /proc/3119/mountinfo 60 41

これらすべてのファイルを読み取る必要があるため、/proc/*/task/*マルチスレッドプログラムを使用するすべてのシステムで速度が遅くなる可能性があります。残念ながら、両方のスレッド/タスクが同じ名前空間を共有していることを確認する簡単な方法が見つかりませんkcmp(2)。それらは同じアドレス空間、ファイル記述子テーブルなどを共有し、名前空間とは関係ありません。

lsnsx.pl:

#! /usr/bin/perl
use strict;
my %t2n = (
    # the CLONE_NEW* from sched.h
    0x02000000 => "cgroup", 0x04000000 => "uts", 0x08000000 => "ipc",
    0x10000000 => "user", 0x20000000 => "pid", 0x40000000 => "net",
    0x00020000 => "mnt" # CLONE_NEWNS
);
my (%ns);
my $nsfs_dev = (stat "/proc/self/ns/mnt")[0];
my $type = shift || qr/\w+/;
sub unescape { $_[0] =~ s/\\([0-7]{3})/chr oct $1/ger }
# NS_GET_NSTYPE = 0xb7 << 8 | 3
sub nstype { my $h; open $h, $_[0] and ioctl $h, 0xb7 << 8 | 3, 0 }
for(</proc/[0-9]*/task/[0-9]*/{ns/*,fd/*,mountinfo}>){
    s{/([0-9]*)/task/\1/}{/$1/};
    if(my ($procpid) = m{(.*)/mountinfo$}){
        open my $h, $_ or next;
        LOOP: while(<$h>){
            next unless (my @s = split)[2] eq "0:$nsfs_dev";
            if(my($t, $i) = $s[3] =~ /^($type):\[(\d+)\]$/){
                next if exists $ns{$t}{$i};
                for ("", "$procpid/root"){
                    my ($d, $i1) =
                        (stat $_.unescape $s[4])[0, 1];
                    $ns{$t}{$i} = $_.$s[4], next LOOP
                        if $d == $nsfs_dev && $i == $i1;
                }
                $ns{$t}{$i} = "@s[4, 0, 1] $procpid/mountinfo"
            }
        }
    }elsif(m{/ns/}){
        $ns{$1}{$2} //= $_ if readlink =~ /^($type):\[(\d+)\]$/;
    }else{
        next unless my ($dev, $ino) = stat $_;
        next unless $dev == $nsfs_dev;
        next unless my $t = nstype $_;
        next if ($t = $t2n{$t}) and $t !~ $type;
        $ns{$t // '???'}{$ino} //= $_;
    }
}
for my $type (sort keys %ns){
    my $h = $ns{$type}; my @i = sort {$a<=>$b} keys %$h;
    printf "%-8s %d\n", $type, scalar @i;
    printf "   %-11d %s\n", $_, $$h{$_} for @i;
}

関連情報