先日、同僚からElasticBeansTalkで立てたインスタンスにログインした時に、80番をLISTENしてないように見えるんだけど、何故かリクエストは受け付けるんだよね。これどういうことですかね?
という質問を頂きました。
不思議に思って調査したので、その時のメモをまとめました。
前提
ElasticBeansTalkは、環境枠がWeb Server
で 環境タイプがLoad balancing, auto scaling
をVPCで動かしてます。アプリは、node.js
のサンプルアプリケーションを使ってます。
検証
まずは、LISTENの状態を確認します。おー、ホントだ。80番はLISTENしてないように見えます。
[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してますね。
[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番ポートにリダイレクトする設定になってました。
[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チェインに流しているが確認できますね。)
[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