無差別モードが有効になっていなくても、すべての着信パケットをキャプチャできるのはなぜですか?

無差別モードが有効になっていなくても、すべての着信パケットをキャプチャできるのはなぜですか?

インターフェイスからバイパスパケットをキャプチャするには、次のコマンドを使用しますens160

tcpdump -i ens160 -w test.pcap

その間、次のコマンドを使用して無差別モードが有効になっていることを確認しますens160

ifconfig ens160 | grep -i promisc 
ip a show ens160 | grep -i promisc
netstat -i | grep ens160

このコマンドのすべての出力は、無差別モードを指していますが、ens160ens160に属していないens160からのパケットを見ることができますtest.pcap

tcpdump無差別モードではデフォルト値が機能することがわかりますが、ens160この間、無差別モードは無効になります。

無差別モードが有効になっていなくても、すべての着信パケットをキャプチャできるのはなぜですか?

ベストアンサー1

長い話を短く

最新のLinuxでは、インターフェイスはカウンタを使用して、promiscuity動作状態が無差別(> 0)かどうか(= 0)を識別します。インタフェースPROMISC属性フラグは、カウンタをインクリメントする唯一の方法ですpromiscuity

tcpdumpPROMISCインターフェイスのフラグを変更しませんが、このインターフェイスのネイティブパケットソケットから無差別トラフィックを受信するように要求し、自動的にカウンタをインクリメントしてインターフェイスpromiscuityを無差別モードに設定します。

ifconfigは廃止され(Linuxでは)カウンタを表示できませんpromiscuity。そうではありませんnetstat -i

代わりに使用してください:

ip -details link show dev ens160

またはJSONを使用してjq:

ip -d -j link show dev ens160 | jq '.[].promiscuity'

イベントスキーマ(JSONを使用しない)やその他のリンク変更でそれらを追跡することもできます。

ip -d monitor link dev ens160

答えが長い

これはLinuxで廃止されたコマンドなので、および/またはどこでもifconfig置き換える必要があります。ip linkip addr

PROMISC設定できるインターフェイス属性(例:廃止ifconfig ens160 promiscまたは無効)はip link set ens160 promisc on変更されず、tcpdump重要な属性ではないため、ここでは重要です。ここでは、カウンターifconfigでのみ利用可能な新機能を表示できません。ip linkpromiscuity

答えは、straceどのようなさまざまなシナリオが発生する可能性があるかを判断することによって異なります。


Linuxで置き換えられていますが、古いバージョンとの互換性のために利用ifconfig ens160 promisc可能な古いベースAPIを使用すると、次のようになります。ioctl(2)strace

...
ioctl(4, SIOCGIFFLAGS, {ifr_name="ens160", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
ioctl(4, SIOCSIFFLAGS, {ifr_name="ens160", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_PROMISC|IFF_MULTICAST}) = 0
...

ip link set dev ens160 promisc on交換で使用(rt)netlink(7)ソケットAPI(読みやすくするために1行が分割されています(ARPHRD_NETROMはstrace値0から始まるデコードエラーである可能性があります)):

...
sendmsg(3, {msg_name={sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000},
            msg_namelen=12,
            msg_iov=[{
                iov_base={
                    {len=32, type=RTM_NEWLINK, flags=NLM_F_REQUEST|NLM_F_ACK, seq=1684784897, pid=0},
                    {ifi_family=AF_UNSPEC, ifi_type=ARPHRD_NETROM,
                     ifi_index=if_nametoindex("ens160"),
                     ifi_flags=IFF_PROMISC, ifi_change=0x100}},
                iov_len=32}],
            msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0) = 32
...

両方とも2つの異なるAPIを使用して有効にします。エンス160インタフェース属性 IFF_PROMISC。

tcpdumpデフォルトでは、無差別モードを使用します(以下の説明のために、「インターフェース属性を有効にする」を使用せずに「無差別モードを使用」と書いています)。これを防ぐには、以下を使用する必要があります。-pオプション:

-p
--no-promiscuous-mode

インターフェイスを無差別モードに設定しないでください。インタフェースは他の理由で無差別モードになる可能性があるため、省略形として -p使用することはできませんether host {local-hw-addr} or ether broadcast

これは、インターフェイス属性を無差別に設定するのではなく、このインターフェイスで使用されているパケットソケットから無差別トラフィックを受信するように要求することによって行います。

...
socket(AF_PACKET, SOCK_RAW, htons(0 /* ETH_P_??? */)) = 4
...
bind(4, {
         sa_family=AF_PACKET,
         sll_protocol=htons(0 /* ETH_P_??? */),
         sll_ifindex=if_nametoindex("ens160"),
         sll_hatype=ARPHRD_NETROM,
         sll_pkttype=PACKET_HOST, sll_halen=0
     }, 20) = 0
getsockopt(4, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
setsockopt(4, SOL_PACKET, PACKET_ADD_MEMBERSHIP, {
               mr_ifindex=if_nametoindex("ens160"),
               mr_type=PACKET_MR_PROMISC,
               mr_alen=0, mr_address=ca:de:8a:4a:1c:38},
           }, 16) = 0
...

違いは、Linuxがこれを処理する方法です。無差別モードで各リソースの使用量を計算します。これらのリソースの1つがある限り、インターフェイスの動作状態は無差別です。カウンタがゼロに下がると、インターフェイスの動作状態はもはや無差別になりません。再構成自体(実際のハードウェアNICで物理ハードウェアの再構成をトリガーする)は、0から> 0または> 0から0に変更した場合にのみ発生します。

そのようなリソースは何に使用できますか?

  • 明らかにインターフェースプロパティPROMISCの設定
  • インターフェイスをブリッジポートとして設定
  • 以前と同様に、tcpdump要求はインターフェイスで開かれた生のパケットソケットからすべて/その他のトラフィックを受信します。積み重ねて使用できます。各同時ユーザーはカウンターを 1 ずつインクリメントします。
  • このインターフェイスに接続されたMACVLANインターフェイスを作成します。
  • 他の場合は? ...

これらの各目的は、インターフェイスが表示されるとタスクカウンタに追加されます。このカウンタは、以前のioctl APIには適用されず、新しい開発のための最新のnetlink APIにのみ適用されます。ifconfig表示できませんip -details link。表示できます。いいえ-detailsこのプロパティは、役に立つタスクを実行するのにほとんど必要ないため、表示されません。


仮想 veth インターフェイスの例test0:

# ip link add name test0 up type veth
# ip -details link show dev test0
14: test0@veth0: <NO-CARRIER,BROADCAST,MULTICAST,UP,M-DOWN> mtu 1500 qdisc noqueue state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
    link/ether ca:de:8a:4a:1c:38 brd ff:ff:ff:ff:ff:ff promiscuity 0  allmulti 0 minmtu 68 maxmtu 65535 
    veth addrgenmode eui64 numtxqueues 4 numrxqueues 4 gso_max_size 65536 gso_max_segs 65535 tso_max_size 524280 tso_max_segs 65535 gro_max_size 65536 

それは考慮されます:promiscuity 0

またはJSON出力を使用してjq:

# ip -details -json link show dev test0 | jq '.[].promiscuity'
0

今:

# ip link set dev test0 promisc on
# ip -d -j link show dev test0 | jq '.[].promiscuity'
1
# ip link add name br0 type bridge
# ip link set dev test0 master br0
# ip -d -j link show dev test0 | jq '.[].promiscuity'
2
# tcpdump -n -i test0 src 192.0.2.2 and dst 198.51.100.2 &
[1] 128657
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on test0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
# ip -d -j link show dev test0 | jq '.[].promiscuity'
3
# tcpdump -n -i test0 src 192.0.2.2 and dst 198.51.100.2 &
[2] 128670
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on test0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
# ip -d -j link show dev test0 | jq '.[].promiscuity'
4

したがって、4つのリソース使用量があります。つまり、カーネルで 2 つ、ユーザー空間の raw パケットソケットで 2 つです。

インターフェイスが 0 より大きい場合、promiscuity無差別モードに設定されます。単純なフラグに比べて利点はリソース計算を提供するので、完了時にインターフェイスを非無差別にリセットする必要があるか、またはクリーンアップする機会がある前に中断されるかどうかを推測する必要がないことですkill -9 %1。管理者は、インターフェイスが無差別モードになってはいけないか、維持する必要があるか(ブリッジされたポートなど)、考慮する必要があります。

おすすめ記事