公開ホストのセキュリティがガバガバだった話

会社のお金でセキュリティ講習を受けている時に紹介された、OSINT検索エンジンのShodanを使って自分の公開ホストを調べてみたら、ufwでブロックしていたはずのポートが公開されていた。
本当にあった怖い話

それの修正ついでにnginxの設定もガバっていたので、併せて修正した。

その1. dockerでpublishしたポートがufwをすり抜ける

構成

ホスト上にリバースプロキシ用のnginxを立て、各サイトはdocker上で走らせている。
また、一部サイトはhttpがホスト上で動作しており、DBのみコンテナ化されている。

ホスト-コンテナ通信のため、コンテナでexposeされているポートをホストにpublishしている。
ただし、外部から直接アクセスされたくないため、これらのポートはufwでブロックしている(厳密にはallowをしていないと言った方が正しい)。

現象

以下のコマンドやdocker-compose.ymlで立ち上げたコンテナが、ufwが起動しているにもかかわらずグローバルからアクセス可能になっている。
httpコンテナはともかく、mysqlが外部に晒されているのは深刻な問題である(幸い MYSQL_RANDOM_ROOT_PASSWORD=yes にしていたので目に見えた被害はなかった)。

$ docker run -d -p 3306:3306 mysql
$ cat docker-compose.yml
version: "3"
services:
  web:
    build: web
    ports:
      - "8000:80"

原因

Dockerもufwも、内部ではiptablesを使用しているため。
docker run -p などでpublishされたポートは、iptablesの DOCKER チェインで ACCEPT されてしまう。
したがってポート番号しか指定していない場合は 0.0.0.0 でpublishすることになってしまい、グローバルでも疎通が可能となる。

誤った対策

適当にググると、dockerにiptablesを使わせない解決策が出てくる( {"iptables": false}/etc/docker/daemon.json に記述する、など)。
最初はこれにしたがっていたが、iptablesのルールが追加できないと、コンテナから外に出る通信が実現しなくなってしまう。
自分はMatterMostのプッシュ通知が来ないことに気づき、調べたところコンテナからTPNS(プッシュ通知サーバ)への通信ができなくなっていた。

対策

ループバックアドレス 127.0.0.0/8 に対してpublishすればよい。

$ docker run -d -p 127.0.0.1:3306:3306 mysql
$ cat docker-compose.yml
version: "3"
services:
  web:
    build: web
    ports:
      - "127.0.0.2:8000:80"

この時、 127.0.0.0/8 なら 127.0.0.1 以外のアドレスにもpublishできるため、用途ごとにIPアドレスを分けておけばポート番号の競合を気にすることなく管理できて楽になる。
もちろん 0.0.0.0 で既に開けているポートは使えないので要注意。
(参考:https://qiita.com/wand_ta/items/fac7de8d6786af8e7fca

なお、コンテナ間通信に限って言えばpublish自体が必要ないので、不用意なpublishをしないことも重要である。
(参考:https://qiita.com/jqtype/items/9574ef74868b73323939

その2. nginx.confに設定していないはずのドメインへのリクエストが処理されてしまう

構成

/etc/nginx/sites-enabled に複数の .conf ファイルをドメインごとに設置している。

現象

過去に実験用に立てたサブドメインのconfigを /etc/nginx/sites-enabled から消したのだが、そのドメインと関係ない別のサブドメインサービスが応答してしまう。
せめてwwwドメインが応答して欲しい。

原因

default_server パラメータがついているサイトが存在しなかった。
(参考:https://tengine.taobao.org/nginx_docs/ja/docs/http/request_processing.html

対策

wwwなしドメインをwwwありドメインにリダイレクトしたり、httpsにリダイレクトするホストを default_server とした。
もっと気にするのであれば、404を返すdefault_server を別に設置すれば良い。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です