Amazon Linux2でネットワーク帯域制御と遅延追加をやってみた

# 目的
ネットワーク上で制約のある環境を疑似的に再現し、通信の挙動を確認したい。
* 通信帯域の上限を設定する
* 通信の遅延を設定する

# やってみた方法
* AmazonLinux2でip forwardを有効にし、ルーターとして利用。
* 通信帯域の上限設定
    * iptablesのlimit(hashlimit)
    * iprouteのtcコマンド
* 通信の遅延
    * iprouteのtcコマンド

# ネットワーク構成
![bandwidth_diagram.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309202/7482ed38-dcb6-fd28-4b08-bd46474316b1.png)

　EC2(A)---EC2(NAT)(ルーター用)---EC2(B)

* VPCを作成
* サブネットを2つ作成
* EC2(A), EC2(B)をそれぞれのサブネットへ配置
* EC2(NAT)をEC2(A)と同じサブネットで作成。
* EC2(NAT)にENIを追加し、(B)と同じサブネットへ接続
* 各サブネット向けのルートテーブルを作成、相互にルートを追加しておく
* EC2(NAT)のネットワーク設定で「ソース/宛先チェック」を停止しておく
* セキュリティグループは必要なものを空けておく
* EC2(NAT)の基本設定
```
#IP Forwadingを有効にしておく
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
sudo sh -c "echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf"

#iptablesをインストール・サービスを有効化
sudo yum -y install iptables-services
sudo yum iptables -F
sudo systemctl start iptables
sudo systemctl enable iptables

#tcコマンドを利用するためiproute-tcをインストール
sudo yum -y install iproute-tc

#通信状況を確認するため、dstatをインストール
sudo yum -y install dstat
```

# 通信帯域の上限設定1 (最初に検索で見つけた方法)

iptablesのhashlimitを利用。(SCPでの転送確認をやりつつ、EC2(B)にSSHアクセスも行いたかったため、ソースIP単位で制御されるhashlimitを利用。)

limit / limit-burstの考え方の解説は以下参照
https://atmarkit.itmedia.co.jp/ait/articles/1007/14/news102.html

```
sudo iptables -I FORWARD -p tcp -m tcp --dport <ポート番号> -j REJECT
sudo iptables -I FORWARD -p tcp -m tcp --dport <ポート番号> -m hashlimit --hashlimit-name <設定の名称> --hashlimit <単位あたりのパケット数>/s --hashlimit-burst <バーストするまでの上限> -j ACCEPT
sudo service iptables save
```
先にREJECTを設定しているのは、hashlimitを超えたときに、この行の条件に合致してREJECTされるようにしているらしい。（本来はDoS攻撃の対策機能の模様。)

(例)
```
sudo iptables -I FORWARD -p tcp -m tcp --dport 22 -j REJECT
sudo iptables -I FORWARD -p tcp -m tcp --dport 22 -m hashlimit --hashlimit-name sshscplimit --hashlimit 100/s --hashlimit-burst 1 -j ACCEPT
```
( 100 packet/sec × 1500byte(MTU) ＝ 150,000byte/sec = 約150Kbps )

設定状況確認
```
$ sudo iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22 limit: up to 100/sec burst 1
REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22 reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
```
SCPでEC2(A)からEC2(B)へ100MByteのファイルをコピー。EC2(NAT)にて「dstat 1」で帯域を確認。
recvは150kbps前後ですが、sendは60-80kbpsになっていました。受け側での制御なので、こんなものなのでしょうか・・・。
![スクリーンショット 2022-11-08 231733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309202/0233acae-2e31-40d5-6eeb-0abf5ae44e17.png)

# tcによる制御

参考にさせていただいたページ
https://qiita.com/shirok/items/f57e0ecd86abec33a087
https://pig-log.com/tcp-segmentation-offload/
# 通信帯域の上限設定2
EC2(NAT)のeth1へ設定。(EC2(A)⇒EC2(B)方向へ転送するため、EC2(NAT)の出口側へ設定)
```
#1Mbpsに上限を設定
#※再起動しても消えないようにするためには、起動スクリプトへの組み込みが必要。
sudo tc qdisc add dev eth1 root tbf limit 1Mb buffer 200Kb rate 1Mbps
sudo ethtool -K eth1 gso off
```
gso off はセグメンテーションのオフロードをオフにしている。
ネットワークアダプタで処理しないようにするため（・・・と理解している。）
```
# 設定前のデフォルト状況確認
$ sudo ethtool -k eth1 | grep segmentation-offload
tcp-segmentation-offload: off
generic-segmentation-offload: on
# gsoのみonであったため、offに変更
$ sudo ethtool -K eth1 gso off
# 設定後の状況確認
$ sudo ethtool -k eth1 | grep segmentation-offload
tcp-segmentation-offload: off
generic-segmentation-offload: off
```
![スクリーンショット 2022-11-08 233656.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309202/d4978010-87b7-2b9c-b456-f99394939c8f.png)


# 通信の遅延追加
帯域制御と遅延追加は、どうやら排他的になっているようなので、遅延はEC2(NAT)のeth0に設定。
```
設定の追加
$ sudo tc qdisc add dev eth0 root netem delay <遅延時間>

設定の変更
$ sudo tc qdisc change dev eth0 root netem delay <遅延時間>

設定状況の確認
$ sudo tc qdisc show dev eth0
qdisc netem 8001: root refcnt 3 limit 1000 delay <遅延時間>
```
(例)
```
$ sudo tc qdisc add dev eth0 root netem delay 200ms
$ sudo tc qdisc change dev eth0 root netem delay 500ms
$ sudo tc qdisc show dev eth0
qdisc netem 8001: root refcnt 3 limit 1000 delay 500ms
```