ELBが Proxy Protocol に対応したので検証してみた

記事タイトルとURLをコピーする

こんにちは、AWSテクニカルグループの山田です。

ELBで新たにProxy Protocol のサポートが加わり、HTTP(S)以外の接続でも接続元のIPが取得出来るようになったので早速検証してみました。

 

構成

今回は、新たに追加されたProxyProtocolPolicyを有効にしたELBに、ProxyProtocolモジュールを組み込んだNode.jsのWebサーバをアタッチして、接続元IP・接続元ポート・ELBのIPを表示するような構成にしています。

 

確認手順

まず、ELBのProxyProtocolを有効化するためにPolicyを作成します。

$ elb-create-lb-policy ELB名 --policy-name EnableProxyProtocol --policy-type ProxyProtocolPolicyType  --attribute "name=ProxyProtocol, value=true"

次に作成したPolicyをELBに適用します。

$ elb-set-lb-policies-for-backend-server ELB名 --instance-port 8080 --policy-names EnableProxyProtocol

Policyが適用されているかどうか確認します。

$ elb-describe-lb-policies ELB名 --headers
POLICY  NAME                 TYPE_NAME
POLICY  EnableProxyProtocol  ProxyProtocolPolicyType

これでELBの準備は完了です。

 

次にELBの配下で待ち受ける、node.jsサーバを用意します。

まず、node.jsに必要なパッケージをインストールします。

$ sudo yum install gcc-c++ make openssl-devel
$ sudo yum install git

nvmのgithubのリポジトリをクローンしてsourceします。

$ git clone git://github.com/creationix/nvm.git .nvm
$ . .nvm/nvm.sh

nvmからnode.jsをインストールします。

$ nvm install v0.10.13

proxy protocol用のモジュールをnpmでインストールします。

$ npm install proxy-protocol

次に、node.jsのWebサーバを作成します。
このサーバは、ELBから8080番ポートへのTCP接続に対して、Proxy Protocol データを解析し、送信元IPとポートとELBのIPを表示するだけの、単純なNode.jsのサーバです。

$ vim server.js


var net = require('net');
var proxy_protocol = require('node-proxy-protocol');

var response = 'HTTP/1.1 200 OKn
Content-Type: text/htmln
n
<!doctype html>n
<html lang="en">n
<head>n
<meta charset="utf-8" />n
<title>New Feautre: Proxy Protocol Support for Elastic Load Balancing</title>n
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />n
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>n
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>n
<script>n
$(function() {n
$( "#dialog" ).dialog({ width: 500, top: 200 });n
});n
</script>n
</head>n
<body>n
<div id="dialog" title="Connection Details" style="width:400px">n
<p><b>Source IP:</b> {SOURCE_ADDRESS}</p>n
<p><b>Source Port:</b> {SOURCE_PORT}</p>n
<p><b>ELB IP:</b> {PROXIED_BY}</p>n
</div>n
</body>n
</html>';

net.createServer(function(socket) {
    var clientDetails = {};
    proxy_protocol.parse(socket, function(error, obj) {
        if (error) {
            clientDetails.sourceAddress = socket.remoteAddress;
            clientDetails.sourcePort = socket.remotePort;
            clientDetails.proxiedBy = "Not detected";
            clientDetails.proxiedPort = "";
        } else {
            console.log(obj);
            clientDetails.sourceAddress = obj.srca;
            clientDetails.sourcePort = obj.srcp;
            clientDetails.proxiedBy = socket.remoteAddress;
            clientDetails.proxiedPort = socket.remotePort;
        }
        socket.end(response.replace("{SOURCE_ADDRESS}", clientDetails.sourceAddress)
                            .replace("{SOURCE_PORT}", clientDetails.sourcePort) 
                            .replace("{PROXIED_BY}", clientDetails.proxiedBy));
    });
}).listen(8080);

上記のソースコードは、こちらのページにある(http://aws.typepad.com/aws/2013/07/elastic-load-balancing-adds-support-for-proxy-protocol.htmlelb-pp-app.zip の中の server.js を参考にしました。

Node.jsのサーバを起動します。

$ node server.js


最後に、作成したNode.jsのWebサーバをELBへアタッチして、Listener Configurationを設定します。
Node.jsのWebサーバは8080ポートで待ち受けているので Instance Port は TCP:8080 にします。

 

確認

ELBにアクセスすると、Node.jsのWebサーバ が ProxyProtocol を解析して、送信元IP・ポート・ELBのIPが取得出来ているのが分かります。

最後に

Proxy Protocol はTCP上の任意のプロトコルで使うことが出来るので、これから様々な場面で活用できると思います。
ELBの可能性がこれでまた広がりましたね。