逸般の誤家庭ネットワーク事情

X (旧:Twitter)でリポストに反響が結構あったため現在の自宅ネットワーク事情を紹介します

Summary

昨日、 X をさまよっていると下記のポストを見たのでリポストで反応しました。その後じわじわと反応があったため弊宅はいまネットワーク更改中でありますが現状の構成を共有します。

構成

こちらが現在の弊宅構成図です。

L2

  • 仮想マシンクラスターでは 1GbE で痛い目をみたため 10GbE 通信できるようし、 MLAG で 20Gbps を帯域幅を確保しています
  • LAG を多様し LACP(802.3ad) が喋れない機器はリストラしすべて喋れる子に入れ替えました。

構成図 L2

L3

  • シンプルに拠点毎にネットワークを分け VPN で接続しています
  • 弊宅はネットワークが乏しい場面と Global IP が降ってこない CGN 配下の ISP しか利用できないため弊宅クラウドとして Vultr を採用しました
  • ほぼリモートワークで仕事をしているためインターネットが死ぬのはすなわち「死」を意味するので docomo, Softbank, Rakuten Mobile の3キャリアで冗長化、 Act-Act で利用しています

構成図 L3

弊宅は制約上光回線を引かない縛りをしているためすべて LTE 通信で賄っています。そのため LTE の契約帯域を均等に利用する仕組みが必要になり Vultr と WireGuard を張り eBGP ECMP をすることでバランシングしています。

Internet Breakout

default route を Vultr から広報することで宅内のパケットは WireGuard を通って Vultr の IP から Internet へ抜けます。その時 Netflix, Line, ニコニコなどはホスティング事業者からのアクセスを制限しているためアクセスできません。

一般に Internet Breakout と言われますが、企業で使われるような機器では Microsoft 365, Zoom, Windows Update などの比較的回線帯域を食いつぶす可能性があるトラフィックをセンター拠点に流さずに支店のインターネットにブレークアウトする方法がとれます。

この方法はいくつか手法はあるようで最初に試みたのは FQDN 単位で route を曲げる方式です。この方法はサービスで利用する FQDN(www.exsample.com など) をすべて把握できれば定期的に DNS 名前解決をし結果得られた IP Address を機器の route でロンゲストマッチするように経路注入することで支店側のインターネット出口に経路を捻じ曲げます。前述した通りサービスが利用する FQDN が把握しきれないと設定できないため弊宅では面倒くさくなったため取りやめました。

弊宅では、インターネットの経路交換に使われいる BGP の公開経路情報を定期巡回し route を注入することで対応することにしました。宅内 Router に exabgp で現在は home 5G の経路を next-hop とする経路を注入(インジェクション)することで Vultr を経由せず home 5G 経由 docomo 回線でアクセスができるようにしています。

exabgp に食わせる設定は、 bgpview.io, bgp.tools, Public IP list などで検索した公開情報を元に設定しています。これの情報を GitHub Actions で毎日11時に自動的に更新しコンテナを再起動することで反映を行ってます。

下記の例は AWS が公開している IP Address range の json から S3, EC2, CloudFront, Global Accelerator の経路を取り出す例です。

as16509_aws.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/env python3
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
"""aws."""
import requests
import ruamel.yaml

# %%
yaml = ruamel.yaml.YAML(typ="safe")
yaml.indent(sequence=4, offset=2)
yaml.default_flow_style = False
yaml.explicit_start = True  # type: ignore


def get_as16509() -> None:
    """Get AS16509."""
    try:
        ip_ranges_res = requests.get(
            "https://ip-ranges.amazonaws.com/ip-ranges.json",
        )
        ip_ranges_res.raise_for_status()
        ip_ranges = ip_ranges_res.json()
        print("asn: 16509, ip_ranges: {}".format(ip_ranges_res.status_code))
    except requests.exceptions.RequestException as err:
        print("HTTP response error: ", err)

    else:
        service_ips: list = []
        for service in ["S3", "EC2", "CLOUDFRONT", "GLOBALACCELERATOR"]:
            for item in ip_ranges["prefixes"]:
                if item["service"] == service:
                    service_ips.append(
                        {
                            "ip": item["ip_prefix"],
                            "region": item["region"],
                            "service": item["service"],
                            "network_border_group": item["network_border_group"],
                        },
                    )

        yml: dict = {
            "asn": 16509,
            "asn_name": "AMAZON-02",
            "category": "internet",
            "name": "AMAZON",
            "routes": service_ips,
        }

        with open("routes/AS{}_{}.yml".format(yml["asn"], yml["name"]), "w") as file:
            yaml.dump(yml, file)

上記を実行すると yml で経路情報が吐かれるのでこれをまとめて exabgp の起動時に食わせれば宅内で Internet Breakout を実現しています。

AS_16509.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- asn: 16509
  asn_name: AMAZON-02
  category: internet
  name: AMAZON
  routes:
  - ip: 3.0.0.0/15
    network_border_group: ap-southeast-1
    region: ap-southeast-1
    service: EC2
  - ip: 3.2.0.0/24
    network_border_group: us-east-1-iah-1
    region: us-east-1
    service: EC2
  - ip: 3.2.2.0/24
    network_border_group: us-east-1-mia-1
    region: us-east-1
    service: EC2
  - ip: 3.2.3.0/24
    network_border_group: us-east-1-bos-1
    region: us-east-1
    service: EC2
  - ip: 3.2.8.0/21
    network_border_group: GLOBAL
    region: GLOBAL
    service: GLOBALACCELERATOR

# ...(snip)...

また、 GitHub Actions で自動更新しているため AWS の広報経路などを後から追えたりします。(誰得w)

GitHubに上がる経路更新の pull req

インターネットからのアクセス

逸般の誤家庭ではインターネットから宅内にアクセスしたいケースがほとんどの場合発生します(それが目的だったしますから)この場合 ISP が Global IP を借用ルーターに付与してくれれば話が早いですが、 IPv4 の枯渇問題など色々あり最近では NAT の超巨大版である CGN(Carrier Grade NAT) 配下の場合が増えてきました。

そのため、弊宅では前述の通り VPS サービスの Vultr と WireGuard を張り VPN することで Global IP を入手し外部からアクセスが必要な物はその IP で受けて HAProxy でバックエンドにいるサーバー郡にリバースプロキシと HTTPS 終端をして対応しました。

現在進行系でこの箇所の更改を実施しており CloudFlare Access に置き換えも検討してます。

おわりに

ネットワークの更改が完了したらもう少しちゃんとかきたい.

Built with Hugo
テーマ StackJimmy によって設計されています。