このコンテンツは自動機械翻訳サービスによる翻訳版であり、皆さまの便宜のために提供しています。原本の英語版と異なる誤り、省略、解釈の微妙な違いが含まれる場合があります。ご不明な点がある場合は、英語版原本をご確認ください。
Linuxのネットワーク機能は、CloudflareがDDoS攻撃に直面する際の数十億ものリクエストに対処するための重要な部分です。Cloudflareが提供するツールは非常に貴重で有用であり、世界中の開発者からの絶え間ない貢献により、絶えず能力とパフォーマンスが向上し続けています。
当社がモバイルファーストのパフォーマンスおよびセキュリティアプリであるWARPを開発した際、新たな課題に直面しました。何百万ものモバイルクライアント向けの任意のユーザーパケットをエッジマシンから安全かつ効率的に転送する方法です。この記事では、Linuxネットワークスタックを使って独自の高パフォーマンスVPNを構築するという私たちの最初のソリューションについて探ります。既存のネットワークに統合する必要がありました。 CDNサービスに直接リンクするだけでなく、Cloudflareマシンから任意のユーザーパケットを安全にエグレスする方法も提供します。ここで学んだ教訓は、新製品や機能の開発に役立ち、その他にも未知のものを発見するのに役立ちました。まず、どこから始めたのでしょうか?
WARPの初期実装は、インターネットアクセスを可能にする仮想プライベートネットワーク(VPN)に似ていました。具体的には、レイヤー3 VPN – IPパケットのためのトンネルです。
IPパケットはインターネットの構成要素です。インターネット経由でデータを送信すると、データは小さな塊に分割され、パケットで別々に送信されます。それぞれには、宛先アドレス(パケットの宛先)と送信元アドレス(返信の送信先)がラベル付けされます。インターネットに接続しているならIPアドレスがあります。
ただし、一意のIPアドレスがないかもしれません。これはIPv4に確実に当てはまります。IPv4は、世界中でIPv6に移行するための長年の努力にもかかわらず、依然として広く使われています。IPv4に可能なアドレスは40億個しかなく、すべて割り当てられており、共有しなければなりません。
自宅や職場、コーヒーショップでWi-Fiを使うと、ローカルネットワークに接続することになります。お使いのデバイスにはローカルIPアドレスが割り当てられ、アクセスポイントやネットワーク内の他のデバイスと通信します。ただし、そのアドレスはローカルネットワーク外では意味を持ちません。そのアドレスは、インターネット経由で送信されるIPパケットで使うことはできません。それは、すべてのローカルIPv4ネットワークが同じいくつかのアドレスセットを使用するためです。
では、インターネットアクセスはどのように機能するのでしょうか?ローカルIPv4ネットワークは通常、ネットワークアドレス変換(NAT)を実行するための機器であるルーターを採用しています。NATは、ローカルエリアネットワーク上のデバイスに割り当てられたプライベートIPv4ネットワークアドレスを、インターネットサービスプロバイダーから与えられた小さなパブリックにルーティング可能なアドレスセットに変換するために使用されます。ルーターは、2つのネットワーク間で適用される変換テーブルを作成して記録します。一方のネットワークでパケットが受信されると、ルーターは変換テーブルを参照して適切な変換を適用してから、反対のネットワークにパケットを送信します。
NATを使用してプライベートネットワーク上のデバイスからパブリックインターネットへの接続をブリッジするルーターの図
インターネットアクセスを提供するVPNも、この点ではLANと同じです。唯一違う点は、VPNのユーザーがパブリックインターネット経由でVPNサーバーと通信することです。モデルはシンプルです。プライベートネットワークのIPパケットは、VPNサーバーにアドレス指定されたパブリックIPパケットにトンネリングまたはカプセル化されます。
VPNクライアントとサーバー間でHTTPSパケットがカプセル化される図式
ほとんどの場合、VPNソフトウェアはパケットのカプセル化とカプセル化の解除だけを実行し、VPN上でパケットを送受信するための仮想ネットワークデバイスを提供します。これにより、VPNを自由に設定することができます。WARPでは、当社のサーバーがVPNクライアントとインターネット間のルーターとして機能する必要があります。
サーバーを支えているOSであるLinuxは、NetfilterサブシステムでNATを使ったルーティングを実行するように設定することができます。ネットフィルタは、nftablesルールまたはiptablesルールを通じて設定されることが多いです。発信パケットのソースIPを書き換える「ソースNAT」の設定は、次の1つのルールで実現されます。
nft addrule ip nat postrouting oifname "eth0" ip saddr 10.0.0.0/8 snat to 198.51.100.42
このルールにより、NetfilterのNAT機能が、次の基準に一致するパケットのソースアドレス変換を実行します。
送信元アドレスは10.0.0.0/8プライベートネットワークのサブネットです。この例では、VPNクライアントがこのサブネットのアドレスを持つとします。
パケットは、「eth0」インターフェースに送信されます。この例では、サーバーの物理的なネットワークインターフェースであるため、パブリックインターネットへのルートです。
これら2つの条件がそろった場合、「snat」アクションが適用され、VPNクライアントが使用しているアドレスから、サンプルサーバーのパブリックIPアドレス198.51.100.42にソースIPパケットを書き換えます。元のアドレスと書き換えられたアドレスは書き換えテーブルで追跡します。
VPNサーバーによってカプセル化されたパケットが解除され、書き換えられる図式
ディストリビューションがnftablesを出荷する方法によっては、追加の設定が必要な場合があります。nftablesは、非推奨のiptablesよりも柔軟ですが、使用できる「暗黙の」テーブルは少ないです。
また、デフォルトでは2つの異なるネットワークに接続されているマシンが認識なしに転送を行うことは避けたいため、一般的にIPフォワーディングを有効にする必要があるかもしれません。
前に、ルーターは2つのネットワーク内のアドレス間のコンバージョンを追跡すると述べました。上の図では、その状態は書き換えテーブルで保持されています。
実際には、どのデバイスもTCPおよびUDPプロトコル、特にポート番号を使用して複数の独立したデータフローを単一のIPアドレスでサポートする方法を理解している場合にのみ、NATを有用に実装できます。NATデバイス(この場合はLinuxの場合は)は、各接続に一意の送信元ポートとアドレスが使用されることを保証し、必要に応じてポートを再割り当てします。また、TCP接続のライフサイクルを理解して、ポート番号を再利用しても安全である理由を把握する必要があります。可能なポートは65,536しかありませんが、ポートの再利用は不可欠です。
Linux Netfilterには、conntrackモジュールがあり、なりすましパケットや予期せぬパケットからサーバーを保護し、正当な接続への干渉を防ぐステートフルファイアウォールの実装に広く使用されています。この保護が可能なのは、TCPと接続の有効な状態を理解しているからです。この機能は、NATを実装するのにも最適な位置にあります。実際、パケットの書き換えはすべてconntrackによって実装されます。
conntrackがパケットを検証し、書き換えるための手順を示す図
ステートフルファイアウォールとして、connecttrackモジュールはこれが確認したすべての接続のテーブルを保持します。アクティブな接続のすべてを把握できれば、使用されていないポートへの新しい接続を書き換えることができます。
上記の「snat」ルールでは、Netfilterは書き換えテーブルにエントリを追加しますが、パケットはまだ変更しません。nftables内では、基本的なパケット変更のみが許可されます。パケット処理がconntrackモジュールに到達するのを待つ必要があります。conntrackモジュールは、アクティブな接続で未使用のポートを選択し、その後でパケットを書き換えます。
NATをトラフィックに適用する場合のネットフィルタと接続の役割を示す図
接続の別のモードは、接続に属するパケットに永続的なマークを割り当てることです。マークは、nftablesルールで参照され、異なるファイアウォールポリシーの実装や、ルーティング決定の制御に使用されます。
特定のアドレス(ゲストネットワークからなど)が、マシン上の特定のサービスにアクセスするのを防ぎたいとします。各サービスに対して、これらのアドレスへのアクセスを拒否するファイアウォールルールを追加できます。ただし、ブロックするアドレスのセットを変更する必要がある場合は、それに応じてすべてのルールを更新する必要があります。
あるいは、1つのルールを使用して、ブロックしたいアドレスからのパケットにマークを適用し、ブロックを実装するすべてのサービスルールでそのマークを参照することもできます。ここで、アドレスを変更する場合、1つのルールを更新するだけで、そのパケットマークのスコープを変更できます。
ルーティングルールはNetfilterほど多くのパケットの属性を決定できないため、これはルーティングの動作を制御するのに最も有益です。マークを使用すると、強力なネットフィルタルールに基づいてパケットを選択することができます。
特定のパケットにマーキングして特別なルーティングルールを適用するネットフィルターを示す図
WARPサービスを支えているコードは、Cloudflareがセキュリティ重視のシステムプログラミング言語であるRustで書いたものです。WireGuardの実装であるboringtunと、MASQUEの実装には、細心の注意を払いました。しかし、たとえ正面玄関が通過できないと考えたとしても、多層防御を採用することは、良いセキュリティ対策なのです。
その一例として、クライアントから来たIPパケットと、当社のネットワークの他の場所から発信されたパケットを区別することが挙げられます。一般的な方法として、WARPトラフィックに一意のIP空間を割り当て、IPアドレスに基づいて区別する方法がありますが、内部ネットワークの番号を振り分ける必要がある場合、脆弱になる可能性があります。IPv4のアドレス空間は限られていることを思い出してください!代わりに、もっとシンプルな方法が可能です。
WARPクライアントからのIPパケットをLinuxネットワーキングスタックに取り込むために、WARPはTUNデバイスを使用します。これは、プログラムがIPパケットを送受信するために使用できる仮想ネットワークデバイスのLinuxでの名称です。TUNデバイスは、ファイアウォールやルーティングを含む、EthernetまたはWi-Fiアダプターのような他のネットワークデバイスと同様に構成できます。
nftablesを使用して、WARPのTUNデバイスに出力されるすべてのパケットをマークします。ネットフィルタはconntrackと独立してパケットマークを使用できるため、発信経路上のconntrackの状態テーブルにマークを明示的に格納し、着信パケットのためにそれを取得する必要があります。
table ip mangle {
chain forward {
type filter hook forward priority mangle; policy accept;
oifname "fishtun" counter ct mark set 42
}
chain prerouting {
type filter hook prerouting priority mangle; policy accept;
counter meta mark set ct mark
}
}
また、マークされたパケットをTUNデバイスに返すためのルーティングルールを追加する必要があります。
ip route add fwmark 42 table 100 priority 10
ip route add 0.0.0.0/0 proto static dev warp-tun table 100
これで完了です。WARPからの接続はすべて明確に識別され、ローカルからの接続やネットワーク上の他のノードと分けて、ファイアウォールを設定することができます。ConntrackはNATを処理し、接続マークはWARPクライアントによってどの追跡済み接続が行われたかを示しています。
WARPの最初のバージョンでは、Linuxのネットワークスタックの複数のコンポーネントを組み合わせることで、クライアントが任意のインターネットホストにアクセスできるようにしました。各エッジサーバーは、WARP専用の割り当てから単一のIPアドレスを持ち、標準的で詳細に文書化された方法を用いて、NAT、ルーティング、適切なファイアウォールルールを設定することができました。
Linuxは柔軟で設定が容易ですが、マシンごとに1つのIPv4アドレスが必要です。IPv4アドレスが枯渇するため、このアプローチはCloudflareの大規模ネットワークに拡張できません。WARPサーバーを実行するすべてのマシンに専用のIPv4アドレスを割り当てることにより、アドレスリースの請求額が莫大な額になります。コストを抑えるには、WARPを実行するサーバーの数を制限し、導入の運用をますます複雑化する必要がありました。
アイデアはありましたが、Linuxが与えてくれた簡単な道を諦めなければなりませんでした。IP共有が最も有望なソリューションのように思えましたが、1台のマシンが狭いポート群に向けられたパケットしか受信できない場合、どれだけの変更が必要になるでしょうか?すべてをフォローアップのブログ記事で明らかにしますが、もしあなたがこの問題のソリューションをすでに想像しようとしている、好奇心旺盛な問題解決エンジニアの方であれば、当社の求人情報をご覧ください。ご連絡をお待ちしています!