IBM Cloud VPCでのFragment動作


:::note warn
VPCはFragmentパケットをサポートしておらず、Fragmentパケットはエッジでdropされる。
:::

VPC does not support fragmented IP packets. Fragmented packets are dropped at the edge.
https://cloud.ibm.com/docs/vpc?topic=vpc-managing-ip-addresses&interface=ui#rip-before-you-begin

今回はLinuxサーバー2台の間でICMPパケットを送信して、Fragmentパケットの動作を確認した。


# Pingテスト結果

LinuxサーバーのMTUが1500(default)の状態で、Data Size 1473 Byte以上を送信したところ、
Linuxサーバーを出る時点でPacketは分割されて出力したが、対向Linuxサーバーへ届かなかった。

|   | Data(Byte)| Packet(Byte) | Fragment| MFbit | Fragment offset |結果 |
|---|-----------|--------------|---------|-------|-----------------|-----|
| 1 | 1472      | 1500         | なし    | なし   | なし            | OK  |
| 2 | 1473      | 1501※分割   | あり 　  | なし   | なし            | drop  |
| 2※| 1472      | 1500         | あり 　  | あり     | なし            | drop  |
| 2※| 1         | 21           | あり 　  | なし   | 1480           | drop  |

# hping3テスト結果

LinuxサーバーのMTUが1500(default)の状態で、`hping3`というツールによりMFbit(More Fragment bit)やFragment offsetを設定して送信したところ、対向Linuxサーバーに届かなかった。

|  | Data(Byte)| MFbit | Fragment offset | 結果 |
|--|-----------|-------|-----------------|------|
| 1| 64        | なし  | なし            | OK　 |
| 2| 64        | なし  | 1480            | drop |
| 3| 64        | あり  | なし            | drop |
| 4| 1472      | なし  | なし            | OK   |
| 5| 1472      | なし  | 1480            | drop |
| 6| 1472      | あり  | なし            | drop |


# テスト環境

|  | OS Version         | IP Address  | Security Group                      | 
|--|--------------------|-------------|-------------------------------------|
| 1| Ubuntu 20.04.4 LTS | 192.168.0.4 | In/Out方向でプロトコル全てに対して許可 |
| 2| Ubuntu 20.04.4 LTS | 192.168.1.4 | In/Out方向でプロトコル全てに対して許可 |
| 3| CentOS 7.9         | 192.168.0.8 | In/Out方向でプロトコル全てに対して許可 |

- 1から2に対してICMPパケットを送信
- 1から3に対してICMPパケットを送信

# Ping送信テストログ

## Ping送信(Data 1472 Byte)

```console: 
$ ping 192.168.1.4 -s 1472
PING 192.168.1.4 (192.168.1.4) 1472(1500) bytes of data.
1480 bytes from 192.168.1.4: icmp_seq=1 ttl=64 time=0.368 ms
```

```console: 送信側Linuxサーバーでのtcpdump
21:28:04.326270 IP 192.168.0.4 > 192.168.1.4: ICMP echo request, id 47550, seq 0, length 1480
21:28:04.326721 IP 192.168.1.4 > 192.168.0.4: ICMP echo reply, id 47550, seq 0, length 1480
```

1500バイトまでの通信はLinuxサーバーで分割されなかった。



## Ping送信(Data 1473 Byte)

```console: 
$ ping 192.168.1.4 -s 1473
PING 192.168.1.4 (192.168.1.4) 1473(1501) bytes of data.
^C
--- 192.168.1.4 ping statistics ---
226 packets transmitted, 0 received, 100% packet loss, time 230385ms
```


```console: 送信側Linuxサーバーでのtcpdump
21:28:08.718277 IP 192.168.0.4 > 192.168.1.4: ICMP echo request, id 48062, seq 0, length 1480
21:28:08.718355 IP 192.168.0.4 > 192.168.1.4: ip-proto-1
```
| MFbit | Fragment Offset |
|--|--------------------|
| <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329464/06551365-ae1d-5ce8-7e4c-4688c1e448de.png">| <img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329464/9a1f7529-ef29-1a1e-9fcc-1f41b9de241f.png"> |

1500バイトまでの通信はLinuxサーバーで分割された。



```console: 受信側Linuxサーバーでのtcpdump
$ tcpdump host 192.168.0.4
```
受信側Linuxサーバーでのtcpdumpでは、送信側LinuxサーバーからのICMPパケットを取得できなかった。



## hping3(Data 64 Byte)

同一セグメントのサーバー間の通信でも、MFbitやFragment Offsetを含んだFragmentパケットは届かなかった。

```console: MFbit/Fragment Offsetなし
$ hping3 -c 1 -1 -C 8 -d 64 192.168.0.8
HPING 192.168.0.8 (ens3 192.168.0.8): icmp mode set, 28 headers + 64 data bytes
len=92 ip=192.168.0.8 ttl=64 id=38490 icmp_seq=0 rtt=7.9 ms

--- 192.168.0.8 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 7.9/7.9/7.9 ms
```

```console: Fragment Offsetあり
$ hping3 -c 1 -1 -C 8 -d 64 -g 1480 192.168.0.8
HPING 192.168.0.8 (ens3 192.168.0.8): icmp mode set, 28 headers + 64 data bytes

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

```console: MFbitあり
$ hping3 -c 1 -1 -C 8 -d 64 -x 192.168.0.8
HPING 192.168.0.8 (ens3 192.168.0.8): icmp mode set, 28 headers + 64 data bytes

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

# (参考) 物理LinuxサーバーでのPing

物理Linuxサーバー間での通信では、送信側LinuxサーバーからFragmentパケットが受信側Linuxサーバーへ届いて応答がある。


```console: 送信側Linuxサーバーでのping
$ ping 192.168.1.2 -s 1473
PING 192.168.1.2 (192.168.1.2) 1473(1501) bytes of data.
1481 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.802 ms
1481 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.653 ms
```

```console: 受信側Linuxサーバーでのtcpdump
07:13:50.218459 IP 192.168.1.1 > 192.168.1.2: ICMP echo request, id 8889, seq 1, length 1480
07:13:50.218507 IP 192.168.1.1 > 192.168.1.2: icmp
07:13:50.218589 IP 192.168.1.2 > 192.168.1.1: ICMP echo reply, id 8889, seq 1, length 1480
07:13:50.218703 IP 192.168.1.2 > 192.168.1.1: icmp
```
受信側LinuxサーバーにFragmentパケットが届き、応答している。



# 考察

IBM Cloud VPCはMFbitやFragment Offsetを含んだFragmentパケットをDropするため、経路途中のNetwork機器でFragmentすると通信不可となる点に注意する。

TCP通信であればTCPセグメンテーションによりOSやNetwork機器でのFragmentを回避できるが、UDP通信の場合はFragmentされてしまうため通信不可となる。

FragmentされてしまうUDP通信を救うためには
・OSおよび経路のMTUを1500から9000(Jumbo)に変更する
・IBM Cloud VPCを経由する通信をUDPからTCPに変更する
・TCP通信でのカプセル化する
といった案を検討する必要がある。

IBM Cloud VPC内のサーバーからSyslog(UDP)をパケットサイズ2KB以上で送信しようとするとDropする。対策としてSyslogのパケットサイズを1KBに設定変更する

# 参考

IBM Cloud: hping3+VPCを使ったIP Spoofingの禁止・有効化の挙動確認
https://qiita.com/testnin2/items/eef96d180583b6a87fda

Azure VM への UDP 接続では IP フラグメンテーションに気をつけよう！
https://qiita.com/tokawa-ms/items/b5ae1be39ecdf011a4e1