ルーティング
ルーティングについて整理しています。
AS(Autonomous System)
「Autonomous System」の略で、「自律システム」とも呼ばれます。 ASは、 統一された運用ポリシーによって管理されたネットワークの集まりを意味し、 BGPというプロトコルにより接続される単位となります。 AS間で経路情報の交換を行うことにより、 インターネット上での効率的な経路制御を実現します。 通常、規模の大きいISPのネットワークは固有のASを形成しております。
ASは16ビット※の数字を用いたAS番号によってインターネット上で一意に識別され、 日本ではJPNICがその割り当てと管理を行っています。
ルーティングの調査
前提
OS:Ubuntu 20.04
準備
sudo apt install inetutils-traceroute
sudo apt install traceroute
sudo apt install tcptraceroute
traceroute
traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 64 hops max
1 54.150.128.95 6.434ms 8.215ms 8.177ms
2 100.65.25.144 2.059ms 8.283ms 8.258ms
......
14 * * *
15 54.239.53.245 2.367ms 2.690ms 2.354ms
......
19 8.8.8.8 2.517ms 2.532ms 2.555ms
* * * はPing(ICMP Request:8)に対して応答(ICMP Reploy:0)を返さないルータです。
tcptraceroute
tcptraceroute example.com
Selected device eth0, address 10.3.0.183, port 56587 for outgoing packets
Tracing the path to example.com (93.184.216.34) on TCP port 80 (http), 30 hops max
1 * * *
2 * * *
3 * * *
4 * * *
5 241.0.8.1 0.329 ms 0.258 ms 0.318 ms
6 240.1.52.22 0.307 ms 0.252 ms 0.284 ms
7 242.3.91.17 0.298 ms 0.280 ms 0.362 ms
......
23 93.184.216.34 108.754 ms 108.768 ms 108.831 ms
24 93.184.216.34 [open] 109.808 ms 109.750 ms 109.741 ms
tracerouteに対してリプライを返さない場合でもtcptracerouteに対してはリプライを返す場合があります。
ルーティングテーブル
- ルーターのルーティングテーブル
- ホストのルーティングテーブル
コマンド
- route:「show / manipulate the IP routing table」(
$ man route)-e:「-e use netstat(8)-format for displaying the routing table. -ee will generate a very long line with all parameters from the routing table.」($ man route)-n:「show numerical addresses instead of trying to determine symbolic host names.」
- netstat -r:「Display the kernel routing tables. See the description in route(8) for details. netstat -r and route -e produce the same output.」(
$man netstat) - ip route:ip-route - 「routing table management」(
$man ip route)
Amazon VPC を使ってホストのルーティングテーブルを確認
Amazon VPC のルーターアドレス
各サブネット CIDR ブロックの最初の 4 つの IP アドレスと最後の IP アドレスは使用できず、EC2 インス タンスなどのリソースに割り当てることができません。例えば、CIDR ブロック 10.0.0.0/24 を持つサ ブネットの場合、次の 5 つの IP アドレスが予約されます。
• 10.0.0.0.: ネットワークアドレスです。
• 10.0.0.1: AWS が VPC ルーター用に予約しています。
• 10.0.0.2: AWS が予約しています。DNS サーバーの IP アドレスは、VPC ネットワーク範囲のベースに プラス 2 したものです。
ref. https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-ug.pdf
EC2 インスタンスのルーティングテーブル
サブネット10.2.0.0/24のEC2インスタンス(例10.2.0.50/24)のルーティングテーブルを確認する
route -en
# or
# netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.2.0.1 0.0.0.0 UG 0 0 0 eth0
10.2.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.169.254 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
- Destination(宛先、送信先)に
0.0.0.0が指定されたルートをデフォルトルートと呼ぶ- デフォルトルートのGatewayは
10.2.0.1(前述した Amazon VPC のルーターアドレスを参照)
- デフォルトルートのGatewayは
- Gateway に自分自身を表す
0.0.0.0を指定した場合はルーティングは無効になる(よって Gateway を使用しない)- 同一サブネット(セグメント)のホスト情報を自分が知っているために直接通信ができるため
- Destinationの
169.254.169.254はメタサーバと決まっているのでGatewayは0.0.0.0(無効)169.254.169.254はインスタンスメタデータを返す
Hは Host、Gは Gateway、なしはネットワークを表す
最初の列は宛先ネットワーク、2 番目の列はパケットを転送するルーターを示しています。U フラグは送信経路が up 状態であること、G フラグは送信経路がゲートウェイへのものであることを示します。H フラグは、宛先がネットワークではなく、完全指定のホストアドレスであることを示します。
ref. https://docs.oracle.com/cd/E19620-01/805-5857/troubleshoot6-19973/index.html
参考
例:EC2 Ubuntu 22.04.1 LTS
前提
ホスト
10.0.0.10ホストのEC2インスタンス10.0.0.1サブネット10.0.0.0/16のデフォルトゲートウェイ10.0.0.2AmazonProvidedDNS(Amazon Route 53 Resolver サーバー)
各サブネット CIDR ブロックの最初の 4 つの IP アドレスと最後の IP アドレスは使用できず、EC2 インスタンスなどのリソースに割り当てることができません。例えば、CIDR ブロック 10.0.0.0/24 を持つサブネットの場合、次の 5 つの IP アドレスが予約されます。
• 10.0.0.0.: ネットワークアドレスです。
• 10.0.0.1: AWS が VPC ルーター用に予約しています。
• 10.0.0.2: AWS が予約しています。DNS サーバーの IP アドレスは、VPC ネットワーク範囲のベースにプラス 2 したものです。
Docker
EC2インスタンス10.0.0.10のDockerでデフォルトのブリッジネットワークとカスタムのブリッジネットワークでそれぞれコンテナを稼働。
- デフォルトのブリッジネットワーク
- ネットワークインターフェース
docker0 - アドレス
172.17.0.1
- ネットワークインターフェース
- カスタムのブリッジネットワーク
- ネットワークインターフェース
br-xxxxxxxx - アドレス
172.18.0.1
- ネットワークインターフェース
ルーティングテーブル
ルーティングテーブルはip routeコマンドで確認できます。
下記はip routeコマンドの結果です。
# ホスト 10.0.0.10 で実行
$ ip route
default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.10 metric 100
10.0.0.2 via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.10 metric 100
10.0.0.0/16 dev eth0 proto kernel scope link src 10.0.0.10 metric 100
10.0.0.1 dev eth0 proto dhcp scope link src 10.0.0.10 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.18.0.0/16 dev br-xxxxxxxx proto kernel scope link src 172.18.0.1
- default via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.10 metric 100
- 送信元
10.0.0.10から宛先がルートに一致しないものに適用(つまりルートテーブルにない宛先はすべて10.0.0.1に転送) 10.0.0.10のeth0(デバイス dev)から10.0.0.1(デフォルトゲートウェイ)に転送10.0.0.1(デフォルトゲートウェイ)がルーティング。どのようにルーティングするかは、10.0.0.1(デフォルトゲートウェイ)のルートテーブルよる
- 送信元
- 10.0.0.2 via 10.0.0.1 dev eth0 proto dhcp src 10.0.0.10 metric 100
- 送信元
10.0.0.10から宛先10.0.0.2に適用されるルート 10.0.0.10のeth0(デバイス dev)から10.0.0.1(デフォルトゲートウェイ)に転送10.0.0.1から10.0.0.2へ配送
- 送信元
- 10.0.0.0/16 dev eth0 proto kernel scope link src 10.0.0.10 metric 100
- 送信元
10.0.0.10から宛先10.0.0.0/16に適用されるルート 10.0.0.10のeth0(デバイス dev)から直接unicast/broadcastで通信
- 送信元
- 10.0.0.1 dev eth0 proto dhcp scope link src 10.0.0.10 metric 100
- 送信元
10.0.0.10から宛先10.0.0.1に適用されるルート 10.0.0.10のeth0(デバイス dev)から10.0.0.1(デフォルトゲートウェイ)に転送
- 送信元
- 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
- 送信元
172.17.0.1から宛先172.17.0.0/16に適用されるルート 10.0.0.10のdocker0(デバイス dev)から直接unicast/broadcastで通信
- 送信元
- 172.18.0.0/16 dev br-xxxxxxxx proto kernel scope link src 172.18.0.1
- 送信元
172.18.0.1から宛先172.18.0.0/16に適用されるルート 10.0.0.10のbr-xxxxxxxx(デバイス dev)から直接unicast/broadcastで通信
- 送信元
viaはネクストホップ、devは10.0.0.10のネットワークインターフェースを表す。
proto kernel/dhcp、scope linkは以下の記事で詳しく解説されている。
ref. https://qiita.com/testnin2/items/7490ff01a4fe1c7ad61f
metricは経路が複数あるときの判断基準になる(値が小さいものが優先)。
※ Docker から外部への通信は NAT を使用。
iptables -t nat -nL -v で確認。
※ Ubuntu、 Debian 基本コマンドインストール。
apt update && apt install -y iproute2 iputils-ping net-tools tcpdump traceroute lsof
備考
net.ipv4.ip_forward
外部からきたアクセスのdockerネットワークへの転送はnet.ipv4.ip_forward=1で実行される。
host$ sudo sysctl --all | grep net.ipv4.ip_forward
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_update_priority = 1
net.ipv4.ip_forward_use_pmtu = 0
※ 設定ファイルは /etc/sysctl.conf 。
ref. IPフォワード(IP Forward)
以下本文の構成は異なるが EC2 インスタンスに Docker コンテナが稼働している状況の ルートテーブルとNAT テーブル。
host$ ip route
default via 10.1.0.1 dev eth0 proto dhcp src 10.1.0.81 metric 100
10.1.0.0/24 dev eth0 proto kernel scope link src 10.1.0.81 metric 100
10.1.0.1 dev eth0 proto dhcp scope link src 10.1.0.81 metric 100
10.1.0.2 dev eth0 proto dhcp scope link src 10.1.0.81 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.18.0.0/16 dev br-xxxxxxxx proto kernel scope link src 172.18.0.1
外部からのDocker コンテナへの接続は IP フォワード(net.ipv4.ip_forward) によって 172.18.0.1に転送される。
sudo iptables -t nat -nL -v
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
25 1216 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
10 600 MASQUERADE all -- * !br-xxxxxxxx 172.18.0.0/16 0.0.0.0/0
33 1994 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:3306
0 0 MASQUERADE tcp -- * * 172.18.0.3 172.18.0.3 tcp dpt:8080
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- br-xxxxxxxx * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !br-xxxxxxxx * 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.18.0.2:3306
0 0 DNAT tcp -- !br-xxxxxxxx * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.18.0.3:8080