ルーティングについて整理しています。

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 に自分自身を表す 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

参考

第13回 IPとルーティング

例:EC2 Ubuntu 22.04.1 LTS

前提

ホスト

  • 10.0.0.10 ホストのEC2インスタンス
  • 10.0.0.1 サブネット10.0.0.0/16のデフォルトゲートウェイ
  • 10.0.0.2 AmazonProvidedDNS(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