IBM Cloud: hping3+VPCを使ったIP Spoofingの禁止・有効化の挙動確認


# 1. はじめに

あるサーバーが別のサーバーと通信する際には、一般的にはそのサーバーのインターフェースに紐づいているIPアドレスをsource addressとしてパケットを送信する。逆に自身のIPアドレス以外のパケットをsource addressとして送信する場合（これを`「IP Spoofing（IPアドレスのなりすまし）」`と呼ぶ）は、送信元を誤魔化した攻撃の温床になるため、HypervisorやSwitchなどでIP Spoofingを禁止して**送信側でパケットをブロックしてしまう**ように構成されていることも多い。

IBM CloudのVPCでもIP Spoofingはデフォルトでは禁止しているが、例えば以下のようにVPC上のVSIなどでNFV環境をServer-Bで構築しようとする場合には困ることになる。

```
Server-A <----> Server-B  <----> Server-C
```

この場合、Server-AからServer-B経由でServer-Cにパケットを送信する場合は、Server-Bから送信されるパケットはServer-Aをsource IPアドレスとするパケットであり、(NATなどをしない限りは）Server-BのIPアドレスとはならない。つまり、Server-Bのインターフェースに紐づいているIPアドレス以外のsource addressを送信することができる必要がある。そのため、IBM CloudのVSIのネットワークインターフェースの設定で、IP Spoofingを有効化する機能が提供されている。本稿ではその動作を`hping3`というツールを使って確認してみる。

# 2. hping3の導入

hping3は単なるpingとは違ってとても便利なツールであり、例えば

- TCPのパケットも投げられる
- SoruceやDestinationのポート番号も指定できる
- 送信元アドレスも偽装できる

など非常に有用な機能がある。詳細は[このあたりの記事](http://stacktrace.hatenablog.jp/entry/2016/01/10/040353
)などの解説が詳しい。


```txt:CentOS7での導入方法
# yum install epel-release
# yum install hping3
```


```txt:SourcePortが1234でDestinationPortが5678のSYNパケットを172.16.0.4宛に3回送る
（送信側）
[root@syasuda-tok1-vpc1 ~]# ip a show dev eth0|grep "inet "
    inet 10.0.0.12/24 brd 10.0.0.255 scope global dynamic eth0

[root@syasuda-tok1-vpc1 ~]# hping3 -c 3 -s 1234 -p 5678 -S 172.16.0.4
HPING 172.16.0.4 (eth0 172.16.0.4): S set, 40 headers + 0 data bytes
len=46 ip=172.16.0.4 ttl=64 DF id=37015 sport=5678 flags=RA seq=0 win=0 rtt=0.9 ms
len=46 ip=172.16.0.4 ttl=64 DF id=37733 sport=5678 flags=RA seq=1 win=0 rtt=0.9 ms
len=46 ip=172.16.0.4 ttl=64 DF id=38159 sport=5678 flags=RA seq=2 win=0 rtt=0.8 ms

--- 172.16.0.4 hping statistic ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.8/0.9/0.9 ms
```

```
（受信側）
[root@syasuda-vsi172 ~]# ip a show dev eth0|grep "inet "
    inet 172.16.0.4/24 brd 172.16.0.255 scope global dynamic eth0

[root@syasuda-vsi172 ~]# tcpdump -i any port 5678 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
08:13:21.541223 IP 10.0.0.12.1234 > 172.16.0.4.5678: Flags [S], seq 525622852, win 512, length 0
08:13:21.541254 IP 172.16.0.4.5678 > 10.0.0.12.1234: Flags [R.], seq 0, ack 525622853, win 0, length 0
08:13:22.541218 IP 10.0.0.12.1235 > 172.16.0.4.5678: Flags [S], seq 1567660891, win 512, length 0
08:13:22.541245 IP 172.16.0.4.5678 > 10.0.0.12.1235: Flags [R.], seq 0, ack 1567660892, win 0, length 0
08:13:23.541190 IP 10.0.0.12.1236 > 172.16.0.4.5678: Flags [S], seq 1049172683, win 512, length 0
08:13:23.541217 IP 172.16.0.4.5678 > 10.0.0.12.1236: Flags [R.], seq 0, ack 1049172684, win 0, length 0
```

# 3. IP Spoofingが禁止されていることの確認

```txt:送信側（送信元を192.168.10.10に偽装）
[root@syasuda-tok1-vpc1 ~]# ip a show dev eth0|grep "inet "
    inet 10.0.0.12/24 brd 10.0.0.255 scope global dynamic eth0

[root@syasuda-tok1-vpc1 ~]# hping3 -c 3 -s 1234 -p 5678 -S 172.16.0.4 --spoof 192.168.10.10
HPING 172.16.0.4 (eth0 172.16.0.4): S set, 40 headers + 0 data bytes

--- 172.16.0.4 hping statistic ---
3 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
```

```txt:受信側
[root@syasuda-vsi172 ~]# ip a show dev eth0|grep "inet "
    inet 172.16.0.4/24 brd 172.16.0.255 scope global dynamic eth0

[root@syasuda-vsi172 ~]# tcpdump -i any port 5678 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
（パケットが届いていない）
```

# 4. IP Spoofingの有効化

1. IAMでVPCにおける`IP Spoofing Operator`ロールを有効化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/317d19db-e0b3-9928-58dd-f0ce5c389dc1.png)

2. 送信元を偽装する予定のVSIにて、Network Interfaceに移動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/d1faed53-20dc-73c6-c758-49888aff2858.png)

3. `Allow IP Spoofing`を`Enabled`にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62127/e8ab778d-8348-35b5-a9fa-f024a7306413.png)

# 5. IP Spoofing有効化後の動作確認

```txt:送信側（送信元を192.168.10.10に偽装。当然、返りのパケットは届かない）
[root@syasuda-tok1-vpc1 ~]# ip a show dev eth0|grep "inet "
    inet 10.0.0.12/24 brd 10.0.0.255 scope global dynamic eth0

[root@syasuda-tok1-vpc1 ~]# hping3 -c 3 -s 1234 -p 5678 -S 172.16.0.4 --spoof 192.168.10.10
HPING 172.16.0.4 (eth0 172.16.0.4): S set, 40 headers + 0 data bytes

--- 172.16.0.4 hping statistic ---
3 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
```

```txt:受信側（偽装されたパケットが届くようになった）
[root@syasuda-vsi172 ~]# ip a show dev eth0|grep "inet "
    inet 172.16.0.4/24 brd 172.16.0.255 scope global dynamic eth0

[root@syasuda-vsi172 ~]# tcpdump -i any port 5678 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
08:16:53.291176 IP 192.168.10.10.1234 > 172.16.0.4.5678: Flags [S], seq 469481234, win 512, length 0
08:16:53.291208 IP 172.16.0.4.5678 > 192.168.10.10.1234: Flags [R.], seq 0, ack 469481235, win 0, length 0
08:16:54.291163 IP 192.168.10.10.1235 > 172.16.0.4.5678: Flags [S], seq 192574352, win 512, length 0
08:16:54.291191 IP 172.16.0.4.5678 > 192.168.10.10.1235: Flags [R.], seq 0, ack 192574353, win 0, length 0
08:16:55.291348 IP 192.168.10.10.1236 > 172.16.0.4.5678: Flags [S], seq 45153754, win 512, length 0
08:16:55.291378 IP 172.16.0.4.5678 > 192.168.10.10.1236: Flags [R.], seq 0, ack 45153755, win 0, length 0
```