다음을 수행하여 인터페이스를 표시할 수 있다는 것을 알고 있습니다 ip a show
. 여기에는 호스트가 볼 수 있는 인터페이스만 표시되며, 컨테이너에서 구성된 가상 인터페이스는 이 목록에 표시되지 않습니다. 또한 사용해 보았지만 ip netns
둘 중 하나도 나타나지 않습니다. 다른 버전을 다시 컴파일해야 합니까 iproute2
? /proc/net/fb_trie
로컬/브로드캐스트 주소가 포워딩 데이터베이스로 사용되는 것을 볼 수 있습니다 .
이 정보나 모든 인터페이스(컨테이너 포함)를 나열하는 명령은 어디에서 찾을 수 있습니까?
이를 테스트하려면 컨테이너를 시작하세요. 내 경우에는 스냅의 lxc 컨테이너였습니다. ip a
또는 을 만드세요 ip l
. 호스트 보기는 표시되지만 컨테이너 구성에 대한 인터페이스는 표시되지 않습니다. 컨테이너가 단지 cgrouped 프로세스이기 때문에 greping 중이지만 procfs
arp 항목 외에는 아무것도 얻지 못합니다. fib_trie
나는 이것이 netns 네임스페이스 혼란 때문일지도 모른다고 생각했지만, ip netns
그것도 아무것도 표시되지 않습니다.
conntrack -L
lxd에는 패킷 전달을 위한 연결 추적이 필요하므로 설정된 모든 들어오고 나가는 연결을 표시하는 데 사용할 수 있지만 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 &
그리고lo
Firefox는 연결되지 않은 네트워크 네임스페이스(모든 다운스트림 인터페이스) 에 격리된 각 "웹 콘텐츠" 스레드를 사용하여 실행됩니다 .
알 수 없음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 무선랜0 꺼짐 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/*
: 모든 스레드별 네임스페이스와 바인드 마운트 또는 열린 파일 설명자를 통해 유지되는 네임스페이스를 무시하고 파일을 통해 액세스할 수 있는 네임스페이스 만 나열합니다 .
다음 데모 스크립트는 한 가지 더 나은 작업을 시도합니다. 파일을 통해 바인드 마운트를 찾고 /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;
}