Wiresharkを使った通信監視(後編)――コマンドラインベースでのパケットキャプチャ

ネットワークパケット解析ツール「Wireshark」はさまざまな環境で使える便利なツールだが、GUIが利用できない場合は使いにくい。そこで今回はWiresharkのコマンドライン版である「tshark」や、パケットキャプチャツール「tcpdump」の使い方やWiresharkとの連携について紹介する。

※前編はこちらです。

コマンドラインベースでパケットキャプチャを実行する

前回はWiresharkを使った基本的なパケットキャプチャやパケット解析の流れについて紹介した。Wiresharkでは単純にネットワークを流れるパケットを観測するだけでなく、プロトコルに応じた解析やその中身の確認も行えるが、コンソールからしかアクセスできないLinuxサーバーなどでは利用しにくいケースもある。そういった環境で有用なのが、Wiresharkのコマンドライン版とも言える「tshark」だ。

tsharkではコマンドラインベースでWiresharkとほぼ同様のパケットキャプチャを実行でき、かつWiresharkで読み込める形式でキャプチャ結果をファイルに保存できる。そのため、たとえばLinuxサーバー上でtsharkを使ってパケットキャプチャを実行し、その結果を保存したファイルをWindows上のWiresharkで開いて分析する、といったことが行える。

また、Windows環境でもtsharkは利用可能だ。基本的にはGUIが使えるWindows環境であえてtsharkが必要となるケースは少ないが、たとえばバッチ処理と組み合わせて定期的にパケットキャプチャを実行する、といった用途で利用できる。

UNIX/Linux環境では同様のパケットキャプチャツールとして「tcpdump」というものも有名だ。tcpdumpもWiresharkで読み込める形式のファイルでキャプチャ結果を保存できるので、こちらについても紹介しよう。

なお、tcpdumpはWindowsでは利用できないが、Windows向け移植版とも言えるWinDumpというツールが公開されている。

tsharkのインストール

tsharkは、Windows版であればWiresharkに同梱されており、Wiresharkのインストール先ディレクトリに「tshark.exe」としてインストールされている。

また、Red Hat Enterprise Linuxやその互換Linuxディストリビューションにおいてもtsharkはwiresharkパッケージに同梱されている。いっぽうDebianやUbuntuでは、「tshark」というパッケージ名でWiresharkとは別に配布されているので、こちらをインストールする必要がある。

tsharkの基本的な使い方

tsharkには多くのオプションが用意されているが、主に使用するのは表1のオプションになる。

表1 tsharkの主要オプション
オプション名 説明
-f <キャプチャフィルタ> キャプチャフィルタを指定する
-i <インターフェイス> キャプチャ対象のネットワークインターフェイスを指定する
-w <ファイル名> 出力ファイル名を指定する
-a <条件> 時間/ファイルサイズ/ファイル数などの条件を満たしたらパケットキャプチャを終了する
-r <ファイル名> 指定したファイルを読み込む
-D キャプチャ対象として指定できるネットワークインターフェイス一覧を表示して終了する
-V キャプチャしたパケットの詳細を標準出力に表示する
-Y <表示フィルタ> 表示フィルタを指定する

フィルタ関係では「-f」オプションと「-Y」オプションの2つが用意されているが、前者はWiresharkのキャプチャフィルタに、後者は表示フィルタに相当するものだ。表示フィルタで表示対象外に設定したパケットについても、キャプチャフィルタでフィルタリングされていなければファイルには保存される。また、tsharkの実行には通常はroot権限が必要だ。

tsharkでキャプチャを行うには、まず-Dオプション付きでtsharkを実行し、利用できるネットワークインターフェイスを確認する。

# tshark -D
1. eth0
2. docker0
3. veth9803aed
4. eth1
5. veth6f5ff7a
6. vethd6ff2e7
7. vethebacd45
8. vethc81a304
9. veth1977258
10. any
11. lo (Loopback)
12. nflog
13. nfqueue
14. usbmon1
15. usbmon2

ここで表示されるネットワークインターフェイスからパケットキャプチャ対象とするものを選び、「-i」オプションでそれを指定してtsharkコマンドを実行すると、Wiresharkと似たような形式で標準出力にパケットキャプチャ結果が出力される。

# tshark -i eth0
  1 0.000000000 BrocadeC_63:5c:01 -> Broadcast    ARP 60 Who has ***.***.5.154? Tell ***.***.5.2
  2 0.053197061  ***.***.0.3 -> ***.***.5.210 DNS 84 Standard query response 0x1d6a Server failure A slashdot.feedsportal.com
  3 0.053341119 ***.***.5.210 -> ***.***.0.4  DNS 84 Standard query 0x1d6a A slashdot.feedsportal.com
  4 0.055277274      fe80::1 -> ff02::12     VRRP 94 Announcement (v3)
  5 0.101919149 BrocadeC_63:5c:01 -> Broadcast    ARP 60 Who has ***.***.5.17? Tell ***.***.5.2
  6 0.102591985 BrocadeC_63:5c:01 -> Broadcast    ARP 60 Who has ***.***.5.137? Tell ***.***.5.2
  7 0.184864935 IETF-VRRP-VRID_68 -> Broadcast    ARP 60 Who has ***.***.5.212? Tell ***.***.5.1
  8 0.200384825 BrocadeC_63:5c:01 -> Broadcast    ARP 60 Who has ***.***.5.166? Tell ***.***.5.2
  
  

パケットキャプチャを終了するには、Ctrl-Cを入力すれば良い。

また、「-Y」オプションで表示フィルタを指定することで、表示するパケットを絞り込むことができる。指定できるフィルタ文字列は、Wiresharkの表示フィルタと同じルールで指定できる。次の例は、「http」という表示フィルタを指定してHTTPパケットだけを表示させたものだ。

# tshark -i eth0 -Y http
368 11.608519118 126.15.218.69 -> ***.***.5.210 HTTP 587 GET / HTTP/1.1 
377 11.925472438 ***.***.5.210 -> 126.15.218.69 HTTP 1468 HTTP/1.1 200 OK [Malformed Packet]
405 12.017359830 126.15.218.69 -> ***.***.5.210 HTTP 494 GET /jquery/jquery-1.3.2.js?2015-07-03 HTTP/1.1 
406 12.017391654 126.15.218.69 -> ***.***.5.210 HTTP 498 GET /classic.css?2015-07-03 HTTP/1.1 
409 12.017754053 ***.***.5.210 -> 126.15.218.69 HTTP 1468 HTTP/1.1 200 OK  (application/javascript)
413 12.017784062 ***.***.5.210 -> 126.15.218.69 HTTP 1468 HTTP/1.1 200 OK  (text/css)
  
  

tsharkではこのように簡易的にネットワークインターフェイスを流れるパケットの内容をリアルタイムで確認できるが、詳しく分析を行いたい場合は一度分析データをファイルに保存する必要がある。保存先ファイル名は「-w」オプションで指定可能だ。また、「-a」オプションでは時間やファイルサイズ、ファイル数などの条件を指定してキャプチャを終了できる。たとえば10秒間のパケットキャプチャを行う場合、「-a duration:10」と指定すれば良い。

次の例は、10秒間のキャプチャを実行し、キャプチャ結果を「./capture1」というファイルに保存するものだ。

# tshark -i eth0 -w ./capture1 -a duration:10
Capturing on 'eth0'
1661 

「-w」オプションを指定した場合、標準出力にはパケットキャプチャ結果は表示されず、キャプチャしたパケット数のみがリアルタイムで表示される。このときキャプチャフィルタを指定しないと、短時間のキャプチャでもそれなりにファイルサイズが大きくなるので注意したい。

# ls -lh capture1 
-rw------- 1 root root 1.6M 10月 14 21:31 capture1

もし長時間のキャプチャを行いたい場合、「-f」オプションでキャプチャフィルタを設定すると良いだろう。指定できるキャプチャフィルタの内容や書式はWiresharkの場合と同じだ。たとえばHTTPで使われる80番ポートを使用するパケットのみを10秒間キャプチャするには、以下のように実行する。

# tshark -i eth0 -w ./capture2 -f "port 80" -a duration:10

キャプチャ結果が保存されたファイルはバイナリ形式となりそのままでは内容を確認することができないが、「-r」オプションでそのファイルを指定してtsharkを実行することで、その内容を表示できる。この際、「-Y」オプションなどで表示フィルタを指定することも可能だ。また、この場合tsharkの実行にroot権限は不要だ。

$ tshark -r ./capture1 -Y http
647 3.017672630 ***.***.5.210 -> 216.58.197.147 HTTP 185 GET /~r/Slashdot/slashdot/~3/O_szcqEayqc/cassandra-rewritten-in-c-ten-times-faster HTTP/1.0 
648 3.017849338 ***.***.5.210 -> 216.58.197.243 HTTP 155 GET /~r/Slashdot/slashdot/~3/elv3tu_wKP8/story01.htm HTTP/1.0 
649 3.018010161 ***.***.5.210 -> 216.58.200.211 HTTP 155 GET /~r/Slashdot/slashdot/~3/HSoNT9MKv6w/story01.htm HTTP/1.0 
650 3.018164743 ***.***.5.210 -> 216.58.197.243 HTTP 196 GET /~r/Slashdot/slashdot/~3/ZGzLyxFUzwg/darpa-funds-a-300-software-defined-radio-for-hackers HTTP/1.0 
651 3.018315681 ***.***.5.210 -> 216.58.197.147 HTTP 190 GET /~r/Slashdot/slashdot/~3/FYI1Dd_13d0/How-Microsoft-Can-Lock-Linux-Off-Windows-8-PCs HTTP/1.0 
662 3.236938464 216.58.197.243 -> ***.***.5.210 HTTP 1311 HTTP/1.0 301 Moved Permanently  (text/html)
  
  

また、前述のようにtsharkでキャプチャしたキャプチャファイルをWiresharkで開くことも可能だ(図1)。Wiresharkでキャプチャしたものとまったく同様に表示フィルタで表示を絞り込んだり、分析や統計処理を行える。

図1 tsharkでキャプチャしたパケットをWiresharkで開いた例
図1 tsharkでキャプチャしたパケットをWiresharkで開いた例

tcpdumpを使ったキャプチャ

UNIX/Linux環境でWiresharkと同様に広く使われているパケットキャプチャツールがtcpdumpだ。tcpdumpは多くのLinuxディストリビューションで標準パッケージとして提供されており、yumコマンドやapt-getコマンドでインストールできる。

↓Debian/Ubuntu等の場合
# apt-get install tcpdump
↓Red Hat Enterprise LinuxやCentOS等の場合
# yum install tcpdump

tcpdumpでは、オプションを指定せずに実行するとアクティブなネットワークインターフェイスの中でそのデバイス番号が最も小さいものを対象にパケットキャプチャを実行する。また、「-i」オプションでインターフェイスを指定できる。そのほか主要なオプションは表2の通りだ。

表2 tcpdumpの主なオプション
オプション名 説明
-i <インターフェイス名> パケットキャプチャ対象のインターフェイスを指定する
-X パケットの内容を表示する
-w <ファイル名> パケットキャプチャ結果を保存するファイルを指定する
-r <ファイル名> ファイルからキャプチャ内容を読み出す
-c <パケット数> キャプチャするパケット数を指定する。ここで指定したパケット数だけキャプチャした後、tcpdumpは終了する
-C <ファイルサイズ> ファイルにキャプチャ結果を保存する場合、ファイルサイズがここで指定したサイズを超えた場合新たなファイルを作成してそこに続きの結果を出力する。単位はメガバイト
-G <秒数> ファイルにキャプチャ結果を保存する場合、指定した秒数を超えた際に新たなファイルを作成してそこに続きの結果を出力する。この場合、ファイル名としてstrftimeで使用できる変数を含める必要がある

次の例は、「eth0」インターフェイスを対象にキャプチャを実行した例だ。

# tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:22:03.048330 IP ubuntu.ssh > softbank126015218069.bbtec.net.56309: Flags [P.], seq 322979394:322979594, ack 799292918, win 403, options [nop,nop,TS val 1439917884 ecr 1144167161], length 200
22:22:03.048675 IP ubuntu.32824 > dns13.sakura.ad.jp.domain: 44222+ PTR? 69.218.15.126.in-addr.arpa. (44)
22:22:03.066653 IP dns13.sakura.ad.jp.domain > ubuntu.32824: 44222 1/0/0 PTR softbank126015218069.bbtec.net. (88)
22:22:03.066785 IP ubuntu.51272 > dns13.sakura.ad.jp.domain: 60006+ PTR? 3.0.242.133.in-addr.arpa. (42)
22:22:03.066848 IP ubuntu.ssh > softbank126015218069.bbtec.net.56309: Flags [P.], seq 200:448, ack 1, win 403, options [nop,nop,TS val 1439917888 ecr 1144167161], length 248
22:22:03.067254 IP dns13.sakura.ad.jp.domain > ubuntu.51272: 60006 1/0/0 PTR dns13.sakura.ad.jp. (74)
22:22:03.067392 IP ubuntu.ssh > softbank126015218069.bbtec.net.56309: Flags [P.], seq 448:1096, ack 1, win 403, options [nop,nop,TS val 1439917889 ecr 1144167161], length 648
  
  

tsharkの場合と同様、Ctrl-Cを入力するとキャプチャは終了される。

また、次のように「-X」オプションを指定するとパケットの中身も確認できる。ただしこの場合パケットの内容が16進数で表示されるだけで、Wiresharkやtsharkと比較すると不親切な表示となっている。

# tcpdump -i eth0 -X
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:23:58.480556 IP ubuntu.ssh > softbank126015218069.bbtec.net.56309: Flags [P.], seq 323029922:323030042, ack 799294230, win 403, options [nop,nop,TS val 1439946742 ecr 1144282136], length 120
	0x0000:  4510 00ac 3e96 4000 4006 178d 85f2 05d2  E...>.@.@.......
	0x0010:  7e0f da45 0016 dbf5 1341 0ba2 2fa4 4316  ~..E.....A../.C.
	0x0020:  8018 0193 e4b7 0000 0101 080a 55d3 d7f6  ............U...
	0x0030:  4434 5c18 0000 0060 ae6a 8256 cb26 438a  D4\....`.j.V.&C.
	0x0040:  7a68 e80d 0ad8 70d8 8d7c 4d16 ef84 5e0b  zh....p..|M...^.
	0x0050:  198e a965 258f 4d9b af85 f8ac f725 087b  ...e%.M......%.{
	0x0060:  a0c0 c5d3 a6fd c2e8 5dd7 05b3 f321 16e7  ........]....!..
	0x0070:  30d0 1695 8723 dcff 07ba 4de1 db7e 9110  0....#....M..~..
	0x0080:  2587 57bf e9a2 27df 84f0 3dd9 3677 caa4  %.W...'...=.6w..
	0x0090:  bc0e 68cc b718 6e48 58ce d4cc e06f f360  ..h...nHX....o.`
	0x00a0:  0472 26a8 d97e 8a7f 77c4 b160            .r&..~..w..`
22:23:58.480594 IP ubuntu.ssh > softbank126015218069.bbtec.net.56309: Flags [P.], seq 120:240, ack 1, win 403, options [nop,nop,TS val 1439946742 ecr 1144282136], length 120
	0x0000:  4510 00ac 3e97 4000 4006 178c 85f2 05d2  E...>.@.@.......
	0x0010:  7e0f da45 0016 dbf5 1341 0c1a 2fa4 4316  ~..E.....A../.C.
	0x0020:  8018 0193 e4b7 0000 0101 080a 55d3 d7f6  ............U...
	0x0030:  4434 5c18 0000 0060 d31a 461d 899f dad8  D4\....`..F.....
	0x0040:  6cd5 e5b5 0dc7 9562 209f 9ef3 376c 19c6  l......b....7l..
	0x0050:  2b74 a570 f42c 5c09 766e 4345 7dc9 c9f7  +t.p.,\.vnCE}...
	0x0060:  4ebb 3767 4016 38cc f387 495e 6a91 de84  N.7g@.8...I^j...
	0x0070:  a449 6e75 7f88 ff13 c51c 19bd fa2e 1780  .Inu............
	0x0080:  3113 5143 e0a6 17c2 dc83 5106 466f 5ec7  1.QC......Q.Fo^.
	0x0090:  3f52 b3ff 8cf7 addd a810 6552 e2bb 0b89  ?R........eR....
	0x00a0:  2196 f5e8 de65 9f73 4df8 80b4            !....e.sM...
22:23:58.480984 IP ubuntu.51806 > dns13.sakura.ad.jp.domain: 48282+ PTR? 69.218.15.126.in-addr.arpa. (44)
	0x0000:  4500 0048 6ec8 4000 4011 ba23 85f2 05d2  E..Hn.@.@..#....
	0x0010:  85f2 0003 ca5e 0035 0034 11ff bc9a 0100  .....^.5.4......
	0x0020:  0001 0000 0000 0000 0236 3903 3231 3802  .........69.218.
	0x0030:  3135 0331 3236 0769 6e2d 6164 6472 0461  15.126.in-addr.a
	0x0040:  7270 6100 000c 0001                      rpa.....

Wiresharkやtsharkと同様にキャプチャ対象をフィルタリングすることも可能だ。tcpdumpでは引数の最後にフィルタ文字列を指定することでキャプチャフィルタを設定できる。こちらも指定できる文字列はWiresharkのキャプチャフィルタと同様だ。たとえばHTTPで使われる80番ポートを使用するパケットのみをキャプチャ対象とするには、「port 80」というフィルタを指定すれば良い。

# tcpdump -i eth0 port 80 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:30:31.933922 IP ubuntu.55651 > nrt12s02-in-f19.1e100.net.http: Flags [S], seq 2177923095, win 29200, options [mss 1460,sackOK,TS val 1440045105 ecr 0,nop,wscale 7], length 0
22:30:31.951332 IP nrt12s02-in-f19.1e100.net.http > ubuntu.55651: Flags [S.], seq 2007324304, ack 2177923096, win 42540, options [mss 1430,sackOK,TS val 1319376115 ecr 1440045105,nop,wscale 7], length 0
22:30:31.951407 IP ubuntu.55651 > nrt12s02-in-f19.1e100.net.http: Flags [.], ack 1, win 229, options [nop,nop,TS val 1440045110 ecr 1319376115], length 0
22:30:31.952807 IP ubuntu.38895 > nrt12s12-in-f19.1e100.net.http: Flags [S], seq 1449378035, win 29200, options [mss 1460,sackOK,TS val 1440045110 ecr 0,nop,wscale 7], length 0
22:30:31.973696 IP nrt12s12-in-f19.1e100.net.http > ubuntu.38895: Flags [S.], seq 3993499406, ack 1449378036, win 42540, options [mss 1430,sackOK,TS val 1785830447 ecr 1440045110,nop,wscale 7], length 0
22:30:31.973769 IP ubuntu.38895 > nrt12s12-in-f19.1e100.net.http: Flags [.], ack 1, win 229, options [nop,nop,TS val 1440045115 ecr 1785830447], length 0
22:30:31.975208 IP ubuntu.55653 > nrt12s02-in-f19.1e100.net.http: Flags [S], seq 756155668, win 29200, options [mss 1460,sackOK,TS val 1440045116 ecr 0,nop,wscale 7], length 0
  
  

キャプチャ結果をファイルに保存するには「-w」オプションを指定する。たとえば「dump01」というファイルに出力するには、以下のようにする。

# tcpdump -i eth0 -w dump01
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C29 packets captured
54 packets received by filter
0 packets dropped by kernel

また、「-G」オプションで指定した秒数ごとにファイルを分割する指定が可能だ。「-G」オプションの後には分割する秒数を指定する。また、この場合ファイル名にstrftimeで利用できる変数を指定することで、ファイル名に取得時刻を付けることができる。たとえば次のように実行すると、「test<年-月-日-時:分:秒>」というファイルにキャプチャ結果が保存される。

# tcpdump -i eth0 -G 5 -w 'test%F-%T'

保存されたファイルはtsharkの場合と同様バイナリファイルとなり、そのままでは内容を確認することはできないが、「-r」オプションでファイル名を指定してtcpdumpコマンドを実行することで、その内容を出力できる。

# tcpdump -r dump01 
reading from file dump01, link-type EN10MB (Ethernet)
22:34:45.180543 IP ubuntu.ssh > softbank126015218069.bbtec.net.56309: Flags [P.], seq 324923826:324923962, ack 799299494, win 403, options [nop,nop,TS val 1440108417 ecr 1144925834], length 136
22:34:45.207564 IP softbank126015218069.bbtec.net.56309 > ubuntu.ssh: Flags [.], ack 136, win 4091, options [nop,nop,TS val 1144925883 ecr 1440108417], length 0
22:34:45.338532 IP dns14.sakura.ad.jp.domain > ubuntu.58129: 29395 ServFail 0/0/0 (42)
22:34:45.341649 IP ubuntu.55463 > nrt13s38-in-f19.1e100.net.http: Flags [F.], seq 1447875522, ack 3085539268, win 251, options [nop,nop,TS val 1440108457 ecr 933058606], length 0
22:34:45.343140 IP ubuntu.47330 > dns13.sakura.ad.jp.domain: 8745+ A? slashdot.feedsportal.com. (42)
22:34:45.358609 ARP, Request who-has ***.***.5.56 tell ***.***.5.1, length 46
22:34:45.360545 IP nrt13s38-in-f19.1e100.net.http > ubuntu.55463: Flags [.], ack 1, win 333, options [nop,nop,TS val 933059973 ecr 1440108457], length 0

また、tcpdumpでキャプチャしたキャプチャファイルはtsharkやWiresharkにそのまま読み込ませることができる。たとえばtsharkに読み込ませると、次のようにtsharkでパケットキャプチャを行ったのと同じようにキャプチャ内容を確認できる。

# tshark -r dump01
  1   0.000000 ***.***.5.210 -> 126.15.218.69 SSH 202 Server: Encrypted packet (len=136)
  2   0.027021 126.15.218.69 -> ***.***.5.210 TCP 66 56309 → 22 [ACK] Seq=1 Ack=137 Win=4091 Len=0 TSval=1144925883 TSecr=1440108417
  3   0.157989  ***.***.0.4 -> ***.***.5.210 DNS 84 Standard query response 0x72d3 Server failure A slashdot.feedsportal.com
  4   0.161106 ***.***.5.210 -> 216.58.221.19 TCP 66 55463 → 80 [FIN, ACK] Seq=1 Ack=1 Win=251 Len=0 TSval=1440108457 TSecr=933058606
  5   0.162597 ***.***.5.210 -> ***.***.0.3  DNS 84 Standard query 0x2229 A slashdot.feedsportal.com
  6   0.178066 IETF-VRRP-VRID_68 -> Broadcast    ARP 60 Who has ***.***.5.56? Tell ***.***.5.1
  7   0.180002 216.58.221.19 -> ***.***.5.210 TCP 66 80 → 55463 [ACK] Seq=1 Ack=2 Win=333 Len=0 TSval=933059973 TSecr=1440108457
  8   0.181735 BrocadeC_63:5c:01 -> Broadcast    ARP 60 Who has ***.***.5.117? Tell ***.***.5.2
  9   0.325891  ***.***.0.3 -> ***.***.5.210 DNS 84 Standard query response 0x2229 Server failure A slashdot.feedsportal.com
 10   0.326024 ***.***.5.210 -> ***.***.0.4  DNS 84 Standard query 0x2229 A slashdot.feedsportal.com
  
  

また、Wiresharkに読み込ませると、Wiresharkやtsharkでキャプチャした場合と同様にフィルタや分析、統計処理が実行できる(図2)。

図2 tcpdumpでキャプチャしたデータをWiresharkに読み込ませた例
図2 tcpdumpでキャプチャしたデータをWiresharkに読み込ませた例

tsharkとtcpdumpを使い分け

Wiresharkやtsharkとtcpdumpはどちらもよく使われるパケットキャプチャツールだが、tcpdumpの出力はやや不親切であるため、どちらかというとリアルタイムでどの宛先に通信を行っているのかをチェックするような用途に向いている。パケットの中身までをチェックしたいなら、tsharkを利用するほうが良いだろう。

また、tcpdumpでキャプチャしたデータはWiresharkで読み込めるので、tcpdumpでキャプチャを行い、Wiresharkでそれを解析する、といった使い方もおすすめだ。ケースに応じて、これらのツールをうまく使い分けていくと良いだろう。

表示する投稿がありません。