問題解説: Packet Filtering 実技

問題文

とある部署に配属されたあなたは上司に以下のように言われました。

Webサーバ落ちてるんだけど。
僕さ、あんまりLinuxとかよくわかんないんだよね。
前任の人がいい感じにしてくれたんだけど、壊しちゃってさ。
まぁ、いい感じにしてくれ!

上記のトラブルを解決してください。

ゴール

http://192.168.0.1 が200 OKを返すようにすること。

トラブルの概要

  • nginxが起動していない。
  • 80/tcpのパケットがフィルタリングされている。

この2つによって応答が返ってこなくなってしまった。

解説

Webサーバから何の応答が返ってこない場合、次の様な理由が考えられます。

  • Clientのファイアウォールの設定が適切でない。

Clientは踏み台サーバになっていて特別にフィルタリングをするような設定は入れられていないので、この点に関しては問題はありません。

  • ClientとServer間の通信経路に異常がある。

ClientとServerは直接つながっているため問題はありません。これはsshが正常に使えることからも判断ができます。

  • Serverのファイアウォールの設定が適切でない。

Serverでiptables -Lを実行しても1つもルールが入っていないので問題はなさそうです。

  • Server上でWebサーバが動いていない。

lsofnetstatなどのコマンドを用いて、80/tcpをlistenしているプロセスを調べてみても、そのようなプロセスは存在しません。なので、この点は問題がありそうです。

ですが、ここで1度考えてみましょう。もしファイアウォールに何もルールがなく、80/tcpをlistenしているプロセスもないのであれば、以下のようなメッセージが表示されるでしょう。

curl: (7) Failed to connect to 192.168.0.1 port 80: Connection refused

ですが、今回、踏み台サーバからwgetなどでリクエストを送信してもすぐに応答は返ってこなかったと思います。これは、Linuxがiptablesで表示されないような方法でパケットをフィルタリングしているからです。Serverでは、nftablesを用いてパケットをフィルタリングしていました。なので、現在のnftablesのファイアウォールの設定を表示させてみます。

nft list ruleset

すると、以下のような出力が得られます。

    table inet filter {
        chain input {
            type filter hook input priority 0; policy drop;
            icmp type echo-request accept
            tcp dport ssh accept
            ct state established accept
        }

        chain forward {
            type filter hook forward priority 0; policy accept;
        }

        chain output {
            type filter hook output priority 0; policy accept;
        }
    }

このinputチェインを見てみると、80/tcpはACCEPTされていないことが分かります。

ここまでの考察を整理すると、Serverは以下の事柄が原因で正常にレスポンスが返せていなかった事が分かります。

  • 80/tcpをlistenしているプロセスがいない。
  • 80/tcpがnftablesによってフィルタリングされている。

この2つの問題を解決すれば正解になります。

解答例

Serverに入り、lsof -i :80で80/tcpをlistenしているプロセスを調べてみても、どのプロセスも80/tcpをlistenしていなかった。なので、/etc等を調べてnginxを起動・有効化した。

systemctl enable nginx
systemctl start nginx

その次に、nft list rulesetをしてみると、httpがdropされていることが分かった。

なので、nft add rule inet filter input tcp dport http acceptを実行して、ルールを追加した。

nft list ruleset
nft add rule inet filter input tcp dport http accept

これだけではルールが永続化されていないので、以下のコマンドを実行した。

nft list ruleset > /etc/nftables.conf

採点基準

nginxを起動させたことに言及していれば50点。ちゃんと192.168.0.1から応答が返ってくることが確認できた場合、満点です。ですが、本来動いていたnftablesを停止させた場合、減点しています。

講評

少しこの問題はエスパー的な能力が無いと解くのが難しい問題だったかもしれません。解答提出率も20%と割と低かったです。まず、「Webサーバが何なのか」という問題と「誰がフィルタリングしているのか」という問題がありました。Linuxに触れたことが多い人間でないと、nginxやnftablesに目がいかなかったかも知れません。

個人的には、「iptables -Lを見て、ルールが入っていないのに誰かがfilteringしている」というのは初見だとびっくりする人もいるんじゃないのかなと思いました。私はよく、代替のソフトや技術を調べる際に「alternative」をつけて検索することが多いのですが、「iptables alternative」と検索するとすぐにnftablesが出てくるので、焦らずに調べれば解くことができたんじゃないかなと思います。