SSL и открытые порты в Docker — как защитить соединение?

В случае, когда за SSL сертификаты для докеризированных приложений отвечает внешний веб-сервер (например, Caddy), нужно очень внимательно отнестись к тому, как вы открываете порты в своем docker-compose.

Обычная практика такая:

  nginx:
    build: ./nginx
    ports:
      - 8888:80
    volumes:
      - static_sp2:/code/static
      - media_sp2:/code/media
    depends_on:
      - web
    restart: "on-failure"

Но здесь есть серьезная проблема. Ваш nginx теперь доступен не только по адресу localhost или 127.0.0.1, но и всему миру, если у сервера есть публичный адрес.

Мы же выпускаем сертификат с помощью Caddy, значит доступ к сайту будет защищен только если пользователь придет по доменному имени. А что если он забьет ip адрес и добавить в конце порт 8888? Так он получит доступ к сайту без SSL, и может воспользоваться данной возможностью множеством неприятных способов.

Поэтому мы будем создавать контейнеры правильно, мы будем их показывать только приложениям, которые крутятся на нашем сервере:

  nginx:
    build: ./nginx
    ports:
      - "127.0.0.1:8888:80"
    volumes:
      - static_sp2:/code/static
      - media_sp2:/code/media
    depends_on:
      - web
    restart: "on-failure"

Обратите внимание, что с появлением локального айпи адреса нам пришлось взять все выражение в кавычки, иначе докер не сможет достойно распарсить данную строку.

Смотрим, что показывает нам nmap:

user@server:~$ nmap 127.0.0.1
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-24 06:42 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00011s latency).
Not shown: 993 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
443/tcp  open  https
5000/tcp open  upnp
5432/tcp open  postgresql
8000/tcp open  http-alt
8888/tcp open  sun-answerbook

Видим, что внутри порт 888 открыт. Сканируем порты по внешнему доменному имени:

matakov@matacoder:~$ nmap site.ru
Starting Nmap 7.91 ( https://nmap.org ) at 2021-02-24 06:44 UTC
Nmap scan report for site.ru (178.154.254.176)
Host is up (0.0011s latency).
Not shown: 997 filtered ports
PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https

Все, уязвимость ушла, наружу смотрит только SSH, HTTP и HTTPS.