ElasticBeansTalkで立てたインスタンスが80番をLISTENしている仕組み(node.jsの場合)


先日、同僚からElasticBeansTalkで立てたインスタンスにログインした時に、80番をLISTENしてないように見えるんだけど、何故かリクエストは受け付けるんだよね。これどういうことですかね？

という質問を頂きました。

不思議に思って調査したので、その時のメモをまとめました。

## 前提

ElasticBeansTalkは、環境枠が`Web Server` で 環境タイプが`Load balancing, auto scaling` をVPCで動かしてます。アプリは、`node.js`のサンプルアプリケーションを使ってます。

## 検証

まずは、LISTENの状態を確認します。おー、ホントだ。80番はLISTENしてないように見えます。

```shell-session
[ec2-user@ip-172-20-21-59 ~]$ ss -nlt
State      Recv-Q Send-Q      Local Address:Port        Peer Address:Port 
LISTEN     0      128                     *:8080                   *:*     
LISTEN     0      128                    :::22                    :::*     
LISTEN     0      128                     *:22                     *:*     
LISTEN     0      10              127.0.0.1:25                     *:*     
```

次にnginxの設定、これも80番でLISTENするような設定はありません。
nginxは8080でLISTENしてますね。

```shell-session
[ec2-user@ip-172-20-21-59 ~]$ grep -r listen /etc/nginx | grep -v .default
/etc/nginx/conf.d/00_elastic_beanstalk_proxy.conf:    listen 8080;
/etc/nginx/conf.d/virtual.conf:#    listen       8000;
/etc/nginx/conf.d/virtual.conf:#    listen       somename:8080;
```

確かに、これだけだとパッと見で80番をLISTENしてないように見えます。

じゃ、どうなっているのかっていうと。

## 答え

実はNATが動いています。PREROUTINGチェインで、80番ポートを8080番ポートにリダイレクトする設定になってました。

```shell-session
[ec2-user@ip-172-20-21-59 ~]$ sudo iptables -t nat -S PREROUTING -v
-P PREROUTING ACCEPT -c 3 216
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -c 7124 427440 -j REDIRECT --to-ports 8080
```

## まとめ

EBでトラフィックを流すために、裏側でいろいろがんばっている姿が垣間見れた気がしました。ありがたいですね。

では、なぜこのような形をとっているのでしょうか？

予想ですが、EBのようなマネージドサービスの場合、リソース間の依存性を解決するのがめんどくさいのは容易に想像できます。そこで、AWSのリソースについてはある程度共通の形にしておいて、アプリケーション(とミドルウェア)依存のものはインスタンスに隠ぺいすることで責任の範疇をわけたかったとか、たぶんそんな感じなんじゃないかなと思いました。

誰か詳しいことをご存知の方いらっしゃいましたら教えて下さいm(_ _)m

### 追記
thakyuuさんから、特権ポートのセキュリティリスク回避が理由では？とコメント頂きました。
ありがとうございました。

## おまけ

EnvironmentTypeが `Go(Preconfigured - Docker)` の場合、
node.jsの時と同様にnatの機能を使っているようでした。(DOCKERチェインに流しているが確認できますね。)

```shell-session
[ec2-user@ip-172-20-17-101 ~]$ sudo iptables -t nat -S PREROUTING -v
-P PREROUTING ACCEPT -c 1757 105428
-A PREROUTING -m addrtype --dst-type LOCAL -c 1757 105428 -j DOCKER

[ec2-user@ip-172-20-17-101 ~]$ sudo iptables -t nat -L -v
Chain PREROUTING (policy ACCEPT 1835 packets, 110K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1835  110K DOCKER     all  --  any    any     anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 1835 packets, 110K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 2233 packets, 158K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  any    any     anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 2233 packets, 158K bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  any    !docker0  172.17.0.0/16        anywhere            

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination 
```