tcpreplay を使って Raw IP Pcap ファイルに任意の Ethernet Frame を追加する

「とあるインターネットトレースされた Pcap ファイルを再送してインターネットトラフィックを模す」ということをする必要が出たのですが、元の Pcap ファイルはもちろん加工されており、Ethernet Frame と Payload が削除された状態でした。

$ tcpdump -evXnnr sample.pcap
reading from file sample.pcap, link-type RAW (Raw IP)
14:12:02.795288 ip: (tos 0x10, ttl 64, id 11762, offset 0, flags [DF], proto TCP (6), length 1088)
    10.20.22.132.20222 > 10.20.22.15.62585: Flags [P.], seq 3211:4247, ack 3682, win 501, options [nop,nop,TS val 1205061784 ecr 1681210238], length 1036
        0x0000:  4510 0440 2df2 4000 4006 c7fb 0a14 1684  E..@-.@.@.......
        0x0010:  0a14 160f 4efe f479 54ed cb7f 4024 f5da  ....N..yT...@$..
        0x0020:  8018 01f5 44ed 0000 0101 080a 47d3 c898  ....D.......G...
        0x0030:  6435 3b7e 
...

これを tcpreplay で再送すると、Raw IP のまま送信されてしまいます。そこで、以下のことをしたのでその備忘録です。

  • 偽の Ethernet Frame を追加する
  • IPアドレスを任意のものに変更する
  • Header の Length フィールドに従ってパケットの末尾に Padding を追加する

tcpreplay をインストールする

まずは tcpreplay をインストールします。現時点での最新はv4.4.4ですが、このバージョンでは Ethernet Frame 追加の動作が期待通り動かなかったのでv4.3.4を使います。

$ wget https://github.com/appneta/tcpreplay/releases/download/v4.3.4/tcpreplay-4.3.4.tar.gz
$ tar xzvf tcpreplay-4.3.4.tar.gz
$ cd tcpreplay-4.3.4
$ ./configure
$ make
$ sudo make install
$ tcpreplay -V
Warning: May need to run as root to get access to all network interfaces.
tcpreplay version: 4.3.4 (build git:v4.3.4)
Copyright 2013-2018 by Fred Klassen <tcpreplay at appneta dot com> - AppNeta
Copyright 2000-2012 by Aaron Turner <aturner at synfin dot net>
The entire Tcpreplay Suite is licensed under the GPLv3
Cache file supported: 04
Not compiled with libdnet.
Compiled against libpcap: 1.9.1
64 bit packet counters: enabled
Verbose printing via tcpdump: enabled
Packet editing: disabled
Fragroute engine: disabled
Injection method: PF_PACKET send()
Not compiled with netmap

高速に Pcap を再送したい場合などは、より高度なインストールも可能だそうです。

偽の Ethernet Frame を追加する

$ sudo tcprewrite --dlt=enet --enet-smac=55:44:33:22:11:00 --enet-dmac=00:11:22:33:44:55 --infile=sample.pcap --outfile=sample_add_frame.pcap

Data Link Types: DLT が Ethernet になっており、指定した MAC アドレスを含む Ethernet Frame が追加されていることが確認できます。

$ tcpdump -er sample_add_frame.pcap
reading from file sample_add_frame.pcap, link-type EN10MB (Ethernet)
14:12:02.795288 55:44:33:22:11:00 > 00:11:22:33:44:55, ethertype IPv4 (0x0800), length 1102: (tos 0x10, ttl 64, id 11762, offset 0, flags [DF], proto TCP (6), length 1088)
    10.20.22.132.20222 > 10.20.22.15.62585: Flags [P.], seq 3211:4247, ack 3682, win 501, options [nop,nop,TS val 1205061784 ecr 1681210238], length 1036
        0x0000:  4510 0440 2df2 4000 4006 c7fb 0a14 1684  E..@-.@.@.......
        0x0010:  0a14 160f 4efe f479 54ed cb7f 4024 f5da  ....N..yT...@$..
        0x0020:  8018 01f5 44ed 0000 0101 080a 47d3 c898  ....D.......G...
        0x0030:  6435 3b7e                                d5;~
...

IPアドレスを任意のものに変更する

$ tcpprep --auto=first --pcap=sample_add_frame.pcap --cachefile=sample_add_frame.cache
$ tcprewrite --endpoints=192.0.2.254:203.0.113.254 --cachefile=sample_add_frame.cache --infile=sample_add_frame.pcap --outfile=sample_add_frame_rewrite_ip.pcap

IP アドレスが書き換わっていることが確認できます。また、チェックサムは自動で再計算してくれます。

$ tcpdump -evXnnr sample_add_frame_rewrite_ip.pcap
reading from file sample_add_frame_rewrite_ip.pcap, link-type EN10MB (Ethernet)
14:12:02.795288 55:44:33:22:11:00 > 00:11:22:33:44:55, ethertype IPv4 (0x0800), length 1102: (tos 0x10, ttl 64, id 11762, offset 0, flags [DF], proto TCP (6), length 1088)
    192.0.2.254.20222 > 203.0.113.254.62585: Flags [P.], seq 3211:4247, ack 3682, win 501, options [nop,nop,TS val 1205061784 ecr 1681210238], length 1036
        0x0000:  4510 0440 2df2 4000 4006 08b9 c000 02fe  E..@-.@.@.......
        0x0010:  cb00 71fe 4efe f479 54ed cb7f 4024 f5da  ..q.N..yT...@$..
        0x0020:  8018 01f5 85aa 0000 0101 080a 47d3 c898  ............G...
        0x0030:  6435 3b7e  
...

IPv6 の場合は、--endpoints=[2001:db8::dead:beef]:[::ffff:0:0:ac:f:0:2]のように指定することができます。

Header の Length フィールドに従ってパケットの末尾に Padding を追加する

$ tcprewrite --fixlen=pad --infile=sample_add_frame_rewrite_ip.pcap --outfile=sample_add_frame_rewrite_ip_pad.pca

0x00 の Padding が追加されていることが確認できます。

$ tcpdump -evXnnr sample_add_frame_rewrite_ip_pad.pcap
reading from file sample_add_frame_rewrite_ip_pad.pcap, link-type EN10MB (Ethernet)
14:12:02.795288 55:44:33:22:11:00 > 00:11:22:33:44:55, ethertype IPv4 (0x0800), length 1102: (tos 0x10, ttl 64, id 11762, offset 0, flags [DF], proto TCP (6), length 1088)
    192.0.2.254.20222 > 203.0.113.254.62585: Flags [P.], cksum 0x26b3 (correct), seq 3211:4247, ack 3682, win 501, options [nop,nop,TS val 1205061784 ecr 1681210238], length 1036
        0x0000:  4510 0440 2df2 4000 4006 08b9 c000 02fe  E..@-.@.@.......
        0x0010:  cb00 71fe 4efe f479 54ed cb7f 4024 f5da  ..q.N..yT...@$..
        0x0020:  8018 01f5 26b3 0000 0101 080a 47d3 c898  ....&.......G...
        0x0030:  6435 3b7e 0000 0000 0000 0000 0000 0000  d5;~............
        0x0040:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0050:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0060:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0070:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0080:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0090:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00a0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00c0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00d0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00e0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00f0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0100:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0110:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0120:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0130:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0140:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0150:  0000 0000 0000 0000 0000 0000 0000 0000  ................
...

JANOG50 NETCON 問題解説 Level2-1, Level2-5

Level2-1

問題文

デフォルトゲートウェイ冗長化すべくVRRPを導入したが,MasterのGi0/1に障害が発生した場合に経路が切り替わってくれないようです。この場合でも経路が切り替わるように設定をしてください。

確認方法

  • Clientから192.168.2.2にpingを打ち続ける
  • MasterのGi0/1をshutdownする
  • 経路が切り替わってpingが継続して届いていれば確認完了

解答・解説

オブジェクトトラッキングを設定する問題です。
初期状態はVRRPを有効にし,VIPとPriorityの設定をした状態です。MasterのPriorityを200,BackupのPriorityはデフォルト値(100)に設定しています。
この状態では,ダウンリンク側の障害に対しては経路が切り替わってくれますが,アップリンク側の障害には経路が切り替わってくれません。
そこでオブジェクトトラッキングの設定をしてあげることにより,アップリンク側に障害が発生した場合にダウンリンク側のPriorityを意図的に下げてあげます。これによりアップリンク側に障害が発生した場合でも経路が切り替わってくれます。
設定における注意点として,Backup側のPriorityはデフォルト値(100)でMaster側のPriorityは200なので,オブジェクトトラッキングによるdecrement値は100より大きくする必要があります。

!
hostname Master
!
track 1 interface GigabitEthernet0/1 line-protocol     ## 追加設定(1)
!
interface GigabitEthernet0/0
 ip address 191.168.1.2 255.255.255.0
 vrrp 1 ip 192.168.1.1
 vrrp 1 priority 200
 vrrp 1 track 1 decrement 150     ## 追加設定(2)
 no shutdown
!
interface GigabitEthernet0/1
 ip address 192.168.2.1 255.255.255.0
 no shutdown
!

Level2-5

問題文

iBGPフルメッシュを避けるためにBGPルートレフレクタを導入しました。(RR1,RR2)
しかしながらRouter1,Router2から10.200.1.0/24のネットワークにpingを打つと不安定な現象が見られました。
何が起きているのかを簡単に説明し,iBGPのピアを正しく設定してください。
なお,初期状態ではRouter2,Router3はRR1のクライアントで,Router1,Router4はRR2のクライアントです。また,RR1とRR2はiBGPピアを張っています。

参考:

解答・解説

ルートリフレクタに対するクライアントが不適切なため,Router1 <-> Router2でルーティングループが発生しています。
Router1はRR2とピアを張っているため,10.200.1.0/24への経路として10.100.255.4をBGPから学習しています。

Router1#sh ip route 10.200.1.2
Routing entry for 10.200.1.0/24
  Known via "bgp 100", distance 200, metric 0
  Tag 200, type internal
  Last update from 10.100.255.4 01:00:43 ago
  Routing Descriptor Blocks:
  * 10.100.255.4, from 10.100.255.22, 01:00:43 ago
      Route metric is 0, traffic share count is 1
      AS Hops 1
      Route tag 200
      MPLS label: none

IGPからは10.100.255.4への経路として10.100.5.2と10.100.1.1を学習し,マルチパスとして保持しています。
これはRouter2においても同様です。

Router1#sh ip route 10.100.255.4
Routing entry for 10.100.255.4/32
  Known via "ospf 1", distance 110, metric 4, type intra area
  Last update from 10.100.1.1 on GigabitEthernet0/1, 01:01:50 ago
  Routing Descriptor Blocks:
  * 10.100.5.2, from 10.100.255.4, 01:01:50 ago, via GigabitEthernet0/0
      Route metric is 4, traffic share count is 1
    10.100.1.1, from 10.100.255.4, 01:01:50 ago, via GigabitEthernet0/1
      Route metric is 4, traffic share count is 1

Router1で例えば10.200.1.2にpingを実行すると,まず初めに10.100.5.2か10.100.1.2が選択されます。ここで10.100.5.2が選択された場合,同様にRouter2でも10.100.5.1か10.100.2.1が選択されますが,さらにここで10.100.5.1が選択された場合,ルーティングループが発生します。
OSPFのマルチパスによってロードバランシングされているため,ループするパケットとしないパケットが発生しています。

Router1#ping 10.200.1.1 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 10.200.1.1, timeout is 2 seconds:
!!.!.!..!!.!.!..!!.!.!..!!.!.!..!!.!.!..!!.!.!..!!.!.!..!!.!.!..!!.!.!
..!!.!.!..!!.!.!..!!.!.!..!!.!

この現象は,Router1をRR1のクライアント,Router2をRR2のクライアントとすることで解決できます。

# Router1
router bgp 100
 bgp router-id 10.100.255.1
 neighbor 10.100.255.11 remote-as 100
 neighbor 10.100.255.11 update-source Loopback0
# Router2
router bgp 100
 bgp router-id 10.100.255.2
 neighbor 10.100.255.22 remote-as 100
 neighbor 10.100.255.22 update-source Loopback0
# RR1
router bgp 100
 bgp router-id 10.100.255.11
 neighbor 10.100.255.1 remote-as 100
 neighbor 10.100.255.1 update-source Loopback0
 neighbor 10.100.255.3 remote-as 100
 neighbor 10.100.255.3 update-source Loopback0
 neighbor 10.100.255.22 remote-as 100
 neighbor 10.100.255.22 update-source Loopback0
 !
 address-family ipv4
  neighbor 10.100.255.1 activate
  neighbor 10.100.255.1 route-reflector-client
  neighbor 10.100.255.3 activate
  neighbor 10.100.255.3 route-reflector-client
  neighbor 10.100.255.22 activate
 exit-address-family
!
# RR2
router bgp 100
 bgp router-id 10.100.255.22
 neighbor 10.100.255.2 remote-as 100
 neighbor 10.100.255.2 update-source Loopback0
 neighbor 10.100.255.4 remote-as 100
 neighbor 10.100.255.4 update-source Loopback0
 neighbor 10.100.255.11 remote-as 100
 neighbor 10.100.255.11 update-source Loopback0
 !
 address-family ipv4
  neighbor 10.100.255.2 activate
  neighbor 10.100.255.2 route-reflector-client
  neighbor 10.100.255.4 activate
  neighbor 10.100.255.4 route-reflector-client
  neighbor 10.100.255.11 activate
 exit-address-family
!

作問振り返り

リンクパススルー(LPT)

Level2-1作問後のフィードバックで,「物理配線だとMasterのGi0/1をShutdownすると対向であるBackupのGi0/1のLinkもDownするためPingは送くれなくなる」と指摘がありました。
今回は仮想環境でBridgeしているためそうはならないとのことなので,このまま出題しました。

ループが発生したりしなかったり

Level2-5問題を作問するにあたって,初めは安定してループを発生させるために,OSPF Multi-Path Maximumを1にすることで全てのパケットをRouter2へ向かわせようとしていました。
しかしながら,Router1で10.200.255.4へのNexthopとしてGi0/1(Router2側)が選択されてほしかったにも関わらず,Gi0/0(RR1側)が選択されてしまうことがあるという現象に見舞われました。
これは等コストなパスがあったとき,最初に追加されるパスがそのままベストパスになるために発生した現象でした。
フィードバックをいただき,Multi-Pathを2にすることで必ず一定数はRouter2へ向かうようになるため,安定したループを再現することができました。