こんにちは、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.html)elb-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の可能性がこれでまた広がりましたね。


