NLB (Network Load Balancer) が Proxy Protocol に対応しました

2017.11.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

現地時間の 11/17、NLB (Network Load Balancer) の Proxy Protocol サポートが発表されました。

CLB の頃は Proxy Protocol v1 だったんですが、NLB は v2 のみになります。

また CLB の頃と違い、実装時からマネジメントコンソールで手軽に設定できるようになっています。動作含め検証してみました。

はじめに : Proxy Protocol とは

すごく乱暴にいえば、「HTTP でいうところの X-Forwarded-for を HTTP 以外で使いたい」時のためのプロトコルです。

例えばこんな構成を考えます。

通常ロードバランサ (LB) やリバースプロキシが間にはいると、その裏側のサービスはクライアント IP アドレスを知ることが出来ません。通信相手は LB になるからです。

ただそれだと、アクセス元(クライアント)の IP アドレスによってアクセス制御したり、動作を変えたりすることが出来ません。

NLB はその動作の特性上、ターゲットをインスタンス ID で指定した場合は、直接クライアントの IP アドレスがターゲット(EC2 インスタンス)に伝わります。しかし IP アドレスで指定した場合は一般的な LB と同じように、NLB のプライベート側の IP アドレスが通知されてしまうので、そのような際には必要になる機能・プロトコルかと思われます。

IPアドレスによるターゲット指定が必要なケースとしては、例えば VPN 経由でオンプレミスサーバを指定したりといったものが考えられます。下記の記事を参照いただくのがはやいかと思いますので、あわせてご覧下さい。

NLBでプライベートなEC2やRDSの負荷分散が可能に!

なお、CLB での Proxy Protocol v1 対応についての記事はこちらになります。

【AWS】ELBがProxy Protocolをサポート 〜 RubyでEchoサーバ作って確かめてみた

動作検証

EC2 インスタンスを1台建て、NLB を二つ作ってターゲットに指定します。

NLB名 ターゲットグループ名 ターゲットの種類
nlb-ip t2-ip IPアドレス
nlb-instance t2-instance インスタンスID

nlb-ip が検証の本命ですが、比較のためにインスタンス ID でターゲット指定した nlb-instance も用意しました。

IPアドレス
サーバ側(Private IP) 172.31.xxx.160
クライアント側(AWS 外) 59.nnn.nnn.152

検証 1 : Proxy Protocol が無効(OFF)の場合

まずこれまでの場合を試してみます。

ターゲットの EC2 インスタンス上で nc で簡易的にサーバを立てて、クライアントから送信された通信内容を確認してみます。Proxy Protocol v2 は v1 と違ってバイナリデータになるので、od を使ってダンプします。

クライアント側

$ echo '何かしらのメッセージ' | nc <NLBのDNS名> 8081

サーバ側(nc)

$ nc -l 172.31.xxx.160 8081 | od -tx1 -ta

また同時に、サーバ側では tcpdump でキャプチャもしておきました。届いた IP パケットの source / destination がどうなっているかを見るためです。

サーバ側(tcpdump)

$ sudo tcpdump -nn port 8081

nlb-ip の場合

Proxy Protocol が無効の場合、入力したメッセージがそのまま届きます。

クライアント側

$ echo 'ip, no ppv2' | nc nlb-ip-NNNNNNNN.elb.ap-northeast-1.amazonaws.com 8081

サーバ側(nc)

0000000  69  70  2c  20  6e  6f  20  70  70  76  32  0a
          i   p   ,  sp   n   o  sp   p   p   v   2  nl

ただし、アクセス元はクライアントの IP アドレスではなく、NLB の内側の IP アドレスになります。

サーバ側(tcpdump)

06:53:42.596603 IP 172.31.xxx.153.32457 > 172.31.xxx.160.8081: Flags [SEW], ...
06:53:42.596617 IP 172.31.xxx.160.8081 > 172.31.xxx.153.32457: Flags [S.E], ...
  :

nlb-instance の場合

ターゲットをインスタンス ID で指定した場合も、届くメッセージは同様。ただしアクセス元 IP アドレスにはクライアントのものになります。

クライアント側

$ echo 'instance, no ppv2' | nc nlb-instance-XXXXXXXX.elb.ap-northeast-1.amazonaws.com 8081

サーバ側(nc)

0000000  69  6e  73  74  61  6e  63  65  2c  20  6e  6f  20  70  70  76
          i   n   s   t   a   n   c   e   ,  sp   n   o  sp   p   p   v
0000020  32  0a
          2  nl

サーバ側(tcpdump)

06:54:30.791103 IP 59.nnn.nnn.152.61062 > 172.31.xxx.160.8081: ...
06:54:30.791124 IP 172.31.xxx.160.8081 > 59.nnn.nnn.152.61062: ...
  :

検証 2 : Proxy Protocol が有効(ON)の場合

Proxy Protocol の有効化は、ターゲットグループのほうで行います。

有効化したあと実際に反映されるまで、すこし(十数秒程度)かかるようです。

nlb-ip の場合

クライアント側

$ echo 'ip, with ppv2' | nc nlb-ip-NNNNNNNN.elb.ap-northeast-1.amazonaws.com 8081

メッセージの前にバイナリデータが挿入されているのがわかるでしょうか。

最初の 0d 0a 0d 0a 00 0d 0a 51 55 49 54 0a が Proxy Protocol v2 の protocol signature になり、2行目の冒頭から 4 バイトがクライアント IP アドレス(の 16進数表示)になります。

(0x3b = 59、 0x98 = 152 )

tcpdump の結果ですと、相変わらず通信相手は NLB です。

サーバ側(tcpdump)

07:19:51.405220 IP 172.31.xxx.153.17273 > 172.31.xxx.160.8081: ...
07:19:51.405237 IP 172.31.xxx.160.8081 > 172.31.xxx.153.17273: ...
  :

つまり Proxy Protocol を認識できるサーバソフトウェアであれば、クライアントの IP アドレスが何なのか、このプロトコル経由で知ることができるわけです。

nlb-instance の場合

クライアント側

$ echo 'instance, with ppv2' | nc nlb-instance-XXXXXXXX.elb.ap-northeast-1.amazonaws.com 8081

サーバ側(nc)

0000000  0d  0a  0d  0a  00  0d  0a  51  55  49  54  0a  21  11  00  54
         cr  nl  cr  nl nul  cr  nl   Q   U   I   T  nl   ! dc1 nul   T
0000020  3b  **  **  98  ac  1f  18  c6  f9  aa  1f  91  03  00  04  ad
          ; *** *** can   ,  us can   F   y   *  us dc1 etx nul eot   -
0000040  fa  2f  5f  04  00  3e  00  00  00  00  00  00  00  00  00  00
          z   /   _ eot nul   > nul nul nul nul nul nul nul nul nul nul
0000060  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
        nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul
*
0000140  00  00  00  00  69  6e  73  74  61  6e  63  65  2c  20  77  69
        nul nul nul nul   i   n   s   t   a   n   c   e   ,  sp   w   i
0000160  74  68  20  70  70  76  32  0a
          t   h  sp   p   p   v   2  nl

サーバ側(tcpdump)

07:20:24.616730 IP 59.nnn.nnn.152.61078 > 172.31.xxx.160.8081: ...
07:20:24.616745 IP 172.31.xxx.160.8081 > 59.nnn.nnn.152.61078: ...

こちらの場合も同様に Protocol Proxy のバイナリデータが挿入されています。クライアント IP アドレスが分かっているので重複ではあるのですが、同じ I/F で値が取れるのはいいですね。

まとめ

NLB も着々と機能が増えていきます。外部と完全に切り離した EC2 インスタンスや、VPN接続されたオンプレミス環境と組み合わせた場合でも、NLB の利用が選択肢に入ってくるかと思います。

参考