【第4回】LVS (Linux Virtual Server) によるADFS/WAPの超高可用性負荷分散の実装

前回の第3回では、M365とオンプレミスを結ぶ中枢である「ADFS(Active Directory Federation Services)」と「WAP(Web Application Proxy)」の役割、そしてバックエンドデータベース(WID)の設計について解説しました。これで認証のコアとなるコンポーネントは揃いました。

しかし、エンタープライズの現場では「サーバーが1台動いているだけ」ではシステムとは呼べません。認証基盤はネットワークの新しい境界であり、ここがダウンすれば全社員がM365(Teams、Outlook、SharePointなど)へ一切アクセスできなくなる「単一障害点(SPOF:Single Point of Failure)」となります。
連載第4回となる今回は、このADFSおよびWAPに対して、我々Linuxエンジニアの最強の武器である LVS (Linux Virtual Server) と Keepalived を組み合わせた「超高可用性ロードバランシング」を実装するプロフェッショナルな手法を徹底解説します。

Windows標準のNLB(ネットワーク負荷分散)が抱える限界や、レイヤー7リバースプロキシのオーバーヘッドを排除し、数百万パケットをカーネルレベルで処理するLayer4(DSR方式)のアーキテクチャ設計から、Windows Server側のARPフラックス回避というOSを跨いだ高度なチューニングまで、パケットの動きを追いながら深く解剖していきます。

コウ君

リナックス先生!ADFSサーバーを複数台立ててファームにするのは分かったんですが、その前のロードバランサーって、NginxやHAProxyじゃダメなんですか?普段のWebアプリ開発ではNginxのリバースプロキシで十分負荷分散できているんですけど……。

リナックス先生

コウ君、WebアプリとADFSのようなIdP(Identity Provider)では、トラフィックの性質が全く異なるのよ。ADFSは自身で強固なTLS処理とクライアント証明書認証を行うから、NginxのようにL7で一度暗号化を解いてしまう構成はオーバーヘッドが大きすぎるし、証明書の二重管理になるわ。だからこそ、暗号化パケットを解読せず、MACアドレスの書き換えだけで超高速にルーティングするLayer4の「LVS(IPVS)」が最適な解になるの。今日はLinuxのカーネルモジュールの奥深くまで潜るわよ!

📚 本連載のカリキュラム(全8回)


1. ADFS/WAPにおける負荷分散の要件とLVSの圧倒的優位性

ADFS(Active Directory Federation Services)およびWAP(Web Application Proxy)を複数台のファーム構成にした場合、クライアントからのトラフィックを各ノードに均等に振り分ける必要があります。Windows Serverには標準で「NLB(ネットワーク負荷分散)」という機能が備わっていますが、プロの現場でこれが採用されることは稀です。

Windows NLBの限界とネットワーク機器との相性問題

Windows NLBは、全ノードで同じ仮想MACアドレスを共有し、スイッチからのパケットを全ノードが受信してソフトウェア的に破棄・処理を判断する仕組み(ユニキャスト/マルチキャストモード)を取ります。これは、CiscoやJuniperなどのエンタープライズ向けL2/L3スイッチの「MACアドレステーブルの学習機能」や「IGMPスヌーピング」と相性が悪く、フラッディング(通信の溢れ)を引き起こす原因となります。また、処理能力にも限界があります。

なぜL7プロキシ(Nginx/HAProxy)ではなくL4(LVS)なのか

Linuxエンジニアであれば、NginxやHAProxyを思い浮かべるでしょう。これらはLayer 7(アプリケーション層)で動作する素晴らしいプロキシです。しかし、ADFS環境においては以下の理由から推奨されません。

  1. SSL/TLSオフロードの弊害: ADFSはクライアント(ブラウザ)との間で、SAMLアーティファクトバインディングや証明書ベースの認証(デバイス認証)を行うため、途中でロードバランサーがTLSを解読(オフロード)してしまうと、認証プロトコルが破綻します。
  2. TCPコネクションのオーバーヘッド: L7プロキシは、クライアントとのTCPコネクションを一度終端し、バックエンドのADFSに対して「別のTCPコネクション」を張り直します。朝9時の始業時など、数万人の社員が一斉にM365にログインする際、このL7空間でのソケット消費とCPU処理が巨大なボトルネック(SPOF)となります。

そこで登場するのが LVS(Linux Virtual Server) です。LVSはLinuxカーネルの ip_vs モジュールとして動作し、Layer 4(トランスポート層)でTCP/UDPのポート番号とIPアドレスだけを見てパケットをルーティングします。ユーザー空間(アプリケーション)にパケットを引き上げないため、F5 BIG-IPのような数百万円の専用ハードウェアロードバランサーに匹敵するワイヤーレート(物理回線の限界速度)でのパケット転送を実現します。

2. ルーティング方式の最適解:DR(DSR)方式のネットワーク解剖

LVSにはパケットの転送方式として主に「NAT方式」「TUN(トンネリング)方式」「DR(Direct Routing)方式」の3つがあります。M365ハイブリッド認証の内部ネットワーク(ADFS向け)において、プロのインフラエンジニアが選択するのは圧倒的に DR方式(DSR:Direct Server Return とも呼ばれます) です。

DR(Direct Routing)方式のパケットフロー

DR方式は、ネットワークの常識を覆す非常にトリッキーかつエレガントな仕組みです。パケットは以下のように流れます。

  1. クライアントからの要求(行き): ユーザーのブラウザからのHTTPSリクエスト(宛先IPはLVSのVIP:仮想IPアドレス)がLVSに到達します。
  2. LVSのMACアドレス書き換え: LVSはIPヘッダ(送信元IP・宛先IP)を一切変更せず、イーサネットフレーム(L2)の「宛先MACアドレス」だけを、バックエンドのADFSサーバーの物理MACアドレスに書き換えてスイッチに転送します。
  3. ADFSでの処理: ADFSサーバーは自身のループバックインターフェースにVIPを設定しているため、このパケットを自分宛てだと認識し、SSLを解読して認証処理を行います。
  4. ADFSからの応答(戻り): ADFSはSAMLトークンを含んだ大容量のレスポンスパケットを生成します。この時、送信元IPは「VIP」、宛先IPは「クライアントの実IP」となります。このパケットは、LVSを経由せずに、デフォルトゲートウェイを通じて直接クライアントへ返されます。

⚠️ インフラエンジニア視点でのポイント:DR方式の絶大なメリット
Web通信の特性として、HTTPのリクエスト(行き)は数百バイトと非常に小さく、レスポンス(戻り:HTMLやSAML XML)は数キロ〜数十キロバイトと大きくなります。DR方式では大容量の戻りパケットがロードバランサー(LVS)を経由しないため、LVSのネットワーク帯域がボトルネックになることが物理的にあり得ません。これがエンタープライズでDR方式が愛される理由です。

3. LVSとKeepalivedのプロ仕様コンフィグ設計(IaC)

LVS単体ではバックエンド(ADFS)の死活監視や、LVSノード自体の冗長化(マスター/バックアップ構成)ができません。これを制御するデーモンが Keepalived です。
VRRP(Virtual Router Redundancy Protocol)を利用してVIPを動的に付け替え、/adfs/probe という専用エンドポイントを用いた高度なL7ヘルスチェックを行う、エンタープライズ本番環境向けのプロ仕様のコンフィグレーションを解説します。

LinuxカーネルのIP転送チューニング

LVSを稼働させるUbuntu/RHELサーバーにおいて、IPフォワーディングの有効化と、DR方式特有のICMPリダイレクト無効化を行います。

# /etc/sysctl.d/99-lvs.conf
# パケットの転送を許可
net.ipv4.ip_forward = 1
# LVSがICMPリダイレクトパケットを送信するのを防ぐ(DR方式の必須設定)
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0

Keepalived.confの実装(マスターノード用)

M365認証において最も重要なのは persistence_timeout(セッション維持)設定です。ADFSのフォームベース認証やMFA(多要素認証)では、複数回のHTTP遷移が発生します。途中で別のADFSノードに振り分けられると、セッション(Cookie)が途切れて認証エラー・ループに陥ります。これを防ぐため、IPVSのコネクショントラッキング機能を用いて、同一クライアントからの通信を一定時間同じノードへ固定します。

# /etc/keepalived/keepalived.conf (LVS マスターサーバー用)

global_defs {
    router_id LVS_ADFS_MASTER
}

# VRRPによるLVS自体の冗長化設定 (VIPの管理)
vrrp_instance VI_ADFS {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 150             # バックアップ機は100などに設定
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass SecretP@ss
    }
    virtual_ipaddress {
        10.0.10.50/24 dev eth0 label eth0:vip # ADFS用仮想IP(VIP)
    }
}

# IPVS(LVS)の負荷分散・死活監視ルール
virtual_server 10.0.10.50 443 {
    delay_loop 5             # ヘルスチェックのインターバル(5秒)
    lb_algo rr               # 負荷分散アルゴリズム:ラウンドロビン(Round Robin)
    lb_kind DR               # 転送方式:Direct Routing (DSR)
    persistence_timeout 300  # ★超重要:セッション維持(5分間)
    protocol TCP

    # ADFS Node 1 (物理IP: 10.0.10.11)
    real_server 10.0.10.11 443 {
        weight 100
        # TCPの443ポートが開いているかだけでなく、L7レベルでプローブを確認する
        SSL_GET {
            url {
              path /adfs/probe
              status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }

    # ADFS Node 2 (物理IP: 10.0.10.12)
    real_server 10.0.10.12 443 {
        weight 100
        SSL_GET {
            url {
              path /adfs/probe
              status_code 200
            }
            connect_timeout 3
            retry 3
            delay_before_retry 3
        }
    }
}

この設定により、Keepalivedは5秒間隔で https://10.0.10.11/adfs/probe に対してSSL接続を行い、200 OKが返ってこなければ自動的にカーネルの ip_vs ルーティングテーブルからそのノードを切り離し、トラフィックのブラックホール化(通信断)を防ぎます。

4. Windows Serverの罠:DR方式における「ARPフラックス」の完全解決

DR方式を成立させるための最大の難関が、バックエンドとなるWindows Server(ADFSノード)側の設定です。
LVSがIPヘッダを変えずにパケットを転送してくるため、ADFSサーバーは「VIP(10.0.10.50)宛てのパケット」を受け取らなければなりません。そのため、Windowsのネットワーク設定に「Microsoft KM-TEST Loopback Adapter(ループバックインターフェース)」を追加し、そこにVIPを設定します。

しかし、WindowsのデフォルトのTCP/IPスタック仕様では、インターフェースにIPを設定した瞬間、LAN上に対して「私が 10.0.10.50 です!」という Gratuitous ARP (GARP) をブロードキャストしてしまいます。さらに、ルーターからのARPリクエストに対しても応答してしまいます。
こうなると、クライアントからのパケットがLVSではなく直接ADFSサーバーに向かってしまい、負荷分散が完全に崩壊します。これを 「ARPフラックス(ARP Flux)問題」 と呼びます。

コウ君

えっ、Linux側でいくら綺麗にルーティング設定をしても、Windows側が勝手にARPを返してしまったら全部台無しじゃないですか!Windows ServerでARPの応答だけを無効にするなんて、そんな高度なカーネル制御ができるんですか?

リナックス先生

その通りよ。Linuxなら arp_ignore や arp_announce のカーネルパラメータ(sysctl)を弄るだけで一発なんだけどね。Windows Server 2025の場合は、「Strong Host Model」というTCP/IPの送受信ポリシーをPowerShellで厳密にコントロールすることで、このARPフラックスを完全に封じ込めることができるのよ。

PowerShellによるループバックアダプタとStrong Host Modelの構成

以下のスクリプトを、バックエンドとなるすべてのADFSサーバー(Node 1およびNode 2)の管理者PowerShellで実行します。これにより、ARPのブロードキャストを封じつつ、LVSからのVIP宛パケットをサイレントに処理(受信・送信)できる「プロ仕様のDSRバックエンド」が完成します。

# 1. ループバックアダプタが作成されている前提で、インターフェース名を変数に格納
$LoopbackName = "Loopback" # (環境に合わせて変更してください)
$VIP = "10.0.10.50"

# 2. ループバックインターフェースにVIPを設定 (サブネットマスクは/32に設定し、ルーティングの混乱を防ぐ)
New-NetIPAddress -InterfaceAlias $LoopbackName -IPAddress $VIP -PrefixLength 32

# 3. DNSへの動的登録を無効化(DNSレコードが汚染されるのを防ぐ)
Set-DnsClient -InterfaceAlias $LoopbackName -RegisterThisConnectionsAddress $false

# 4. 【超重要】Strong Host Modelの設定変更(ARPフラックス対策)
# ループバックアダプタに対して、他のNIC経由で来たパケットの受信(WeakHostReceive)と送信(WeakHostSend)を許可する
Set-NetIPInterface -InterfaceAlias $LoopbackName -WeakHostReceive Enable -WeakHostSend Enable -DadTransmits 0

# 物理NIC (例: "Ethernet") 側にも受信許可を設定
Set-NetIPInterface -InterfaceAlias "Ethernet" -WeakHostReceive Enable

# 5. インターフェースメトリックの調整(物理NICを優先させ、デフォルトルートがループバックに吸い込まれないようにする)
Set-NetIPInterface -InterfaceAlias $LoopbackName -InterfaceMetric 254

この設定により、ADFSサーバーは「VIP宛てのパケットを処理できるが、自らARP応答はしない」という、LVSのDR方式にとって完璧な状態になります。

5. トラブルシューティング:IPVSテーブルとパケットの追跡

構築完了後、M365へのログイン認証が通らない場合、我々LinuxエンジニアはGUIのエラー画面を見て立ち止まることはしません。カーネルのテーブルとネットワーク上に流れる真実(パケット)を確認します。

1. IPVSルーティングテーブルとコネクション状態の確認

LVSサーバー上で ipvsadm コマンドを実行し、クライアントからのリクエストが正しく各ADFSノードに分散され、パーシステンス(セッション維持)が機能しているかを確認します。

# リアルタイムでのコネクション振り分け状況の確認
sudo ipvsadm -L -n --stats

# コネクションのステート(ESTABLISHED, FIN_WAITなど)とパーシステンス(NONE)の追跡
sudo ipvsadm -L -n -c

ここでコネクションが全く増えていない場合は、クライアントからLVSのVIPへの到達性に問題があります(ファイアウォールやルーターのルーティング)。

2. tcpdumpによるDRパケットフローの完全解析

DR方式で最も多いトラブルは「行き(SYN)は到達しているが、戻り(SYN+ACK)が返ってこない」という事象です。
LVS上でパケットキャプチャを実行し、MACアドレスの書き換えが行われているかを検証します。

# LVS上でVIP(10.0.10.50)に関するトラフィックをMACアドレス含めてキャプチャ
sudo tcpdump -e -n -i eth0 host 10.0.10.50

正常なフローの証拠: クライアントのMACアドレスからLVSのMACアドレスへ送信されたパケット(宛先IPはVIP)が、LVSによって「送信元MAC:LVS、宛先MAC:ADFSサーバー」に書き換えられてスイッチへ転送されていれば、LVSの役割は完璧に果たされています。
もしこれでブラウザに画面が表示されない場合、原因は「Windows Server側(ADFS)のWindows Defender Firewallがブロックしている」か、「ループバックのStrong Host Model設定に不備があり、ADFSがパケットを破棄している」かのどちらかであると、自信を持って切り分けることができます。

6. 第4回の総まとめと次回予告

本記事では、Linuxの究極のパケット処理技術である「LVS(IPVS)」を用いて、Windowsベースの認証基盤(ADFS/WAP)を超高可用性で負荷分散するプロフェッショナルなアーキテクチャを構築しました。

  • LVSの採用理由: ADFSの強固なTLS処理やクライアント証明書認証を妨げず、L7のオーバーヘッドなしにワイヤーレートで処理できるLayer 4ロードバランサーが最適である。
  • DR(DSR)方式の美学: 大容量のSAMLレスポンストラフィックがロードバランサーを経由せず直接クライアントへ返るため、LVSがネットワークのボトルネックにならない。
  • Keepalivedによる高度な監視: /adfs/probe を用いたL7レベルのSSLヘルスチェックと、MFAのセッション切れを防ぐ persistence_timeout の設計が不可欠。
  • OSを跨ぐチューニング(ARPフラックス対策): Windows ServerのループバックアダプタとStrong Host Model(WeakHostReceive / WeakHostSend)をPowerShellで厳密に制御することで、DR方式のパケットフローを完成させる。

ここまでで、オンプレミス環境における最強の「高可用性IdP基盤」が完成しました。
しかし、M365(クラウド)側にはまだ、この社内にあるユーザー情報が届いていません。次回の【第5回】では、オンプレミスのADDSとクラウドのEntra IDを統合する架け橋となる 「Entra ID Connect」 を構築し、ハイブリッドアイデンティティとパスワードハッシュ同期(PHS)の仕組みを実装する手順を解説します。いよいよオンプレミスとクラウドが完全に融合する瞬間です。ご期待ください!

▼ 【インフラ環境を構築しよう!スキルアップを目指すエンジニアへ】 ▼

Windows/Linux両対応!検証に最適な
「高コスパおすすめVPS」

VPSランキングを見る

ハイブリッド環境の知見を活かそう
「ITエンジニア専門転職」

転職エージェントを見る

コメント