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

Цель статьи - поделиться практиками, которые я применил для защиты данных при поднятии собственного VPS в публичной сети. Всегда, когда твой IP открыт всему Миру напоказ и доступен извне внутренних контуров сети - это означает, что любой прохожий может устроить тебе неприятности: похитить твои данные, завладеть твоим сервером и сломать твое замечательное приложение. Я буду приводить пример атаки, показывать, как ее можно заметить и после этого будем разбирать возможные способы защиты.

Как я представляю злоумышленников
Как я представляю злоумышленников

Начало. NGINX

После покупки VPS и развертывания своего маленького приложения - я не поленился развернуть ELK стэк для мониторинга своей системы и подробно наблюдать за её поведением. Буквально за первые пять минут я заметил нагрузку на NGINX приложения, когда клиентские приложения я еще не включал. Мне показалось это странным и я побежал смотреть в логи внимательно и увидел следующую картинку:

Логи сервиса Nginx
Логи сервиса Nginx

О чем говорят логи? Правильно! Они говорят о том, что кто-то пингует и "дергает" наш IP адрес, подыскивает всяческие уязвимые места. Почему уязвимые? Сейчас покажу список URL, которые в основном приходят в запросе:

  • POST /etc/nginx/html/index.html

  • GET //.well-known/security.txt

  • GET /shopdb/index.php

  • GET /login

  • GET /.env

  • GET /var/log/nginx/data-access.log

  • GET /jenkins/login

  • GET /${jndi:ldap://127.0.0.1

  • GET /MySQLAdmin/index.php

  • POST /axis2/axis2-admin/login

  • GET \x00\x0E8\xA6fd\xDA\xA9\x9Az\x8B\x00\x00\x00\x00\x00"

Как можно заметить: это не безобидные запросы для healthchek. В этих запросах кроется злой умысел, ведь есть и инъекции log4j, и запросы для login страниц, и попытки пробраться к определенным файлам с чувствительной информацией.
В процессе я заметил, что подобные наплывы запросов одинаковые, равномерные и происходят с определенными периодами, но с разных клиентов. Мы можем сделать здесь смелый вывод, что это чьи-то боты-сканнеры, которые ищут Ваши уязвимые места, а не хаккер-одиночка с браузера тыкает все эти запросы.

P.S. В основном все IP данных клиентов принадлежат хостингу google-cloud. Не знаю, как это к чему-либо привязать, но свои догадки пока оставлю при себе.

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

Защищаем NGINX

Для этого нам необходимо иметь доступ к редактированию файла конфигурации nginx. Обычно он находится по пути /etc/nginx/nginx.conf . Подробнее про конфигурирование этого замечательного приложения можно найти здесь.

1) Защищаемся на уровне валидации доменного имени, если таковое имеется. Это необходимо, чтобы явно сказать серверу, что мы не ждем гостей, которые пришли к нам, обращаясь без уважения по IP-адресу

if ($host !~ ^(example.com|www.example.com|docs.example.com)$ ) {
    return 444;
}

2) Если на нашем сервисе не допустимы некоторые HTTP-методы, их лучше исключить. Обычно исключают редкие HEAD, OPTIONS, но для примера укажем любые:

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
         return 444;
}

3) Раз боты к нам ходят по тривиальным путям, то и мы изучаем и видим некоторые закономерности в этих ботах. Я заметил заголовок User-Agents, у них есть такие значения, по которым можно понять, что это за потребитель. Большинство ботов научилось себя маскировать под Safari, Mozila, Chrome браузеры, против такой маскировки наш метод не подойдет.

# Некоторые известные боты носят именно такой user-agent в заголовке. 
# Не скажу, откуда я это знаю :)
if ($http_user_agent ~* msnbot|scrapbot) {
            return 403;
}
# Не позволим тривиальным скриптовым вещам нас трогать
if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
            return 403;
}

4) Хотел поговорить про HTTPS и SSL, но лучше расскажут тут.

5) Если есть смысл определенные Path сервиса запаролить дополнительно - лучше это сделать (ссылка).

6) Маленький совет: мы заметили, что ходят по тривиальным URL для логина и подкидывают тривиальные basic-auth-credentials к ним. Можно защититься банальным использованием нетипичных username, ставить сложные криптостойкие пароли и попробовать сделать так, чтобы аутентификация могла быть только при ручном переходе на страницу, используя GET параметры state, consumer, api_key, etc или токены при редиректе в headers запроса. Тогда даже при брутфорсе одного верного логина и пароля злоумышленнику будет недостаточно. Нужно будет попотеть.

7) Если у вас есть только определенные URL, которые доступны, например приложение только для API, стоит открыть в Nginx только этот путь. Например, хотим выделить только для /api/v1/my_service/:

location /api/v1/my_service/ {
...
}

Полный конфиг, который у меня получился:

server {
    listen 443 ssl;  # открыт только 443
    listen [::]:443 default_server ssl;

    ssl_certificate /ssl/nginx.crt;  # Часть с сертификатами
    ssl_certificate_key /ssl/nginx.key;
    ssl_session_tickets off;
    access_log /var/log/nginx/data-access.log combined; # Обязательно логируем процессы
    return 444;

    location / {
       proxy_pass http://example.com;
       proxy_set_header X-Real-IP  $remote_addr;
       proxy_set_header X-Forwarded-For $remote_addr;
       proxy_set_header Host $host;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_redirect http:// https://;
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection $connection_upgrade;
       proxy_read_timeout 20d;
       proxy_buffering off;
       }
   }

Поехали дальше, не один nginx и http порты подвергаются подобным обстрелам зловредными запросами, которые "что-то ищут" с подстановкой типовых паролей и логинов. У нас есть сервисы, которые открыты по другим протоколам, например TCP. На данном порту могут быть любые соединения: socket proxy, database, redis, ssh, etc.
Чем богаты, тем и рады, продолжим и поговорим о БД.

PostgreSQL. За БД нужен глаз да глаз.

Мой сервис имеет базу данных, до которой тоже дошли злые руки ботов, которые пытаются подобрать пароли. Это видно по следующим логам:

Логи сервиса postgres
Логи сервиса postgres

Изучая логи, можно заметить следующее:

  • IP-адреса злоумышленников

  • Имена баз данных, к которым злоумышленники подключаются.

  • Username базы данных, под которыми злоумышленники хотели проникнуть

    А также, читая логи, вы можете заметить, что у них ничегошеньки не получается. Сейчас расскажу, почему:

Чтобы не было страшно, что наши данные из Базы данных похитят, хочу поделиться советами, как максимально-надежно защитить свою PostgreSQL от таких нападок. В логах видно, что злоумышленники получают отказ на вход в нашу БД. Это достигнуто некоторыми моментами.

Защищаем PostgreSQL

1) Мы не используем стандартные имена для БД. То есть для БД следует исключить очевидные названия: database, postgres, shop, db, sa, psql, mydb, my_database.

2) Мы не используем стандартные имена учетных записей для БД. То есть исключаем очевидные username: root, sa, psql, pgsql, admin, postgres, owner, analyzer, exporter, telegraf, user, some_user, test, etc...

3) Конечно же, защищаем свою БД самым криптостойким паролем на свете. Этого мы добиваемся командой:

# при создании пользователя
CREATE USER my_service_name_user WITH ENCRYPTED PASSWORD 'СамыйСложныйПарольНаЗемле';

# при обновлении пользователя 
ALTER USER my_service_name_user WITH ENCRYPTED PASSWORD 'СамыйСложныйПарольНаЗемле';

4) Этим не ограничиваемся. БД - очень тонкая и дорогая вещь, особенно, когда там есть данные и конфиденциальная информация. Поэтому не стоит позволять, чтобы кто-то снаружи вообще смог достучаться до вашей базы данных.

Для этого нам необходимо конфигурить файл доступов к БД pg_hba.conf. Инструкция по настройке здесь.

Покажу на примере, где до сервера с postgres я разрешил доступ только для приложения, которое находится на другом сервере.

host my_service_name_database my_service_name_user my_app_server.com trust

Тут мы явно говорим нашей СУБД, что мы принимаем подключения только от пользователя my_service_name_user в нашу БД my_service_name_database и только тогда, когда получили соединение с хоста приложения my_app_server.com.

ELK. Логи многое скажут о тебе!

Да, мы используем данный стек технологий для удобства, но его никто не должен видеть, кроме доверенных лиц. Потому что логи приложения дают столько информации, что и представить сложно. Тяжело, прочитав логи, не найти ни единого способа к НСД.

Правила защиты на самом деле просты и банальны:

1) Закрываем elastic и logstash на аутентификацию и тогда следом kibana тоже будет на нее и закрыта.

2) Можно постараться сменить дефолтные порты на какие-нибудь другие. Так будет меньше риска, что у ботов будет работать их сценарий по поводу ELK.

# Для примера:

Для elasticsearch по-умолчанию стоит порт 9200 -> меняем на 9222.

Для kibana по-умолчанию стоит порт 5601 -> меняем на 5611.

Приложение. Беречь надо как зеницу ока!

Каждого программиста всегда наставляют на написание безопасного приложения. Чтобы ключи где попало не валялись, чтобы доступы были только по защищенному соединению, по логину-паролю, не иначе. Долго здесь останавливаться не будем, у каждого свой уникальный рецепт готовить безопасность приложения. Некоторым сервисам это даже не нужно, когда они находятся глубоко за всеми возможными файрволами и замками от внешнего мира и к ним доходят уже валидные запросы. Пробежимся по основному:

1) Контейнеризация. Docker — отличная программа, позволяющая запускать изолированные контейнеры. Поэтому мы должны использовать их для размещения и запуска наших серверных приложений.

Таким образом, все приложения запускаются в своем собственном контейнере, поэтому они могут работать в своей собственной среде. Это означает, что любые двоичные файлы, которым мы не доверяем, не могут работать вне контейнера Docker. Кроме того, любые изменения, которые мы вносим в контейнер Docker, удаляются, если мы перестраиваем контейнер Docker, поэтому, если мы или какая-то атака испортят контейнер, мы можем просто перестроить его и вернуть в рабочее состояние.

Библиотеки и зависимости разных приложений не будут мешать друг другу.
Кроме того, несколько контейнеров, работающих на одном и том же сервере, будут иметь некоторый уровень доступа к другим контейнерам и самому хосту. Поэтому мы должны защищать все хосты и запускать контейнеры с минимальным набором возможностей. Мы можем делать такие вещи, как отключить сетевой доступ к контейнеру, если нам нужно.

Важно: не используйте пользователя root внутри вашего образа. Создавайте пользователей в Dockerfile:

RUN groupadd --gid 2000 node \
  && useradd --uid 2000 --gid node --shell /bin/bash --create-home node

Важно: не пишите в docker-compose.yml пароли, ключи, токены. Доверьте это файлу с переменными окружения через:

env_file:
      - /root/environments.env

Либо через secrets:

secrets:
  my_external_secret: # создание секрета через команду docker secret create
    external: true
  my_file_secret: # секрет лежит в файлике
    file: my_file_secret.txt

2) Набор джентельмена, от которого должен себя обезопасить веб-разработчик сразу: SQL инъекции, межсайтовый скриптинг (XSS), межсайтовая подделка запроса (CSRF). Также использовать механизм кроссдоменных запросов (CORS).

Можно отдельно прорабатывать каждый пункт, но как показывает текущая практика: большинство веб-фраймворков из коробки реализуют данный функционал и не дают разработчику ошибиться и сделать своё детище небезопасным.

3) Всегда помним про шифрование уязвимых данных. Пароли никогда не должны храниться в виде обычного текста. Если нам нужно записывать пароли, то они должны храниться в чем-то, что не показывает пароль. Мы можем использовать асимметричное шифрование для хранения наших паролей, чтобы мы могли хранить их в зашифрованном виде с помощью открытого ключа, а затем расшифровывать их обратно в обычный текст с помощью закрытого ключа. В большинстве случаев пароли следует хранить в виде одностороннего хэша, чтобы их нельзя было расшифровать, даже если злоумышленники войдут в нашу базу данных. Мы шифруем каждый пароль с помощью безопасного hash и salt и просто проверяем хешированный пароль, если нам нужно проверить его для аутентификации.

4) Не храним уязвимые данные в репозитории. Использовать лучше секретные переменные, которые может себе позволить любой CI\CD инструмент, либо просто храним в очень недоступном месте на нашем сервере в файликах.

5) Необходимо вести аудит входов в систему. Это важно, потому что позволит мониторить, кто и когда пытался использовать учетные данные, с какого адреса и зачем. Это сокращает массу работы на выявление уязвимых мест.

Сервер. Он должен быть неприступен.

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

В каждый сервер можно осуществить удаленный доступ, обычно он осуществляется с помощью ssh. Доступ по ssh напрямую связан с пользователем операционной системы или группой. Для каждого пользователя должны иметься пароли или ключи для доступа.

Я заметил, что боты очень хорошо пытаются попасть по логину-паролю на мой сервер. Как я это заметил? Запоминаем!

Необходимо прочитать те логи системы, которые отвечают за вход по ssh (для сервера это сервер sshd):

tail -n 500 /var/log/auth.log | grep 'sshd'

Вот, как выглядит результат с признаками того, что на наш сервер пытались проникнуть:

Логи /var/log/auth.log
Логи /var/log/auth.log

Мы прекрасно по логам можем заметить, что злоумышленники перебирают с разных IP-адресов ssh подключения, используя логины: root, user, debianuser, kuhniitalia, uggi, ubuntu, etc. Также мы видим, что проникнуть у них не получается, для этого стоит придерживаться следующих практик:

1) Придумать очень крипто-стойкий пароль. Основное!

2) Создать отдельного пользователя с нетривиальным username, чтобы избежать того, чтобы боты угадали с логином пользователя.

sudo useradd -m my_hard_username && sudo passwd мойСамыйСложныйПарольОдин1

3) Дать созданному пользователю необходимый sudo

usermod -aG sudo my_hard_username

4) Запрещаем пользователю root логиниться в систему удаленно через ssh. Правим файл /etc/ssh/sshd_config и ставим следующие параметр:

PermitRootLogin no

5) Гораздо эффективнее, когда к серверу невозможно подобрать строковый пароль, а когда у него аутентификация только по private-public key. Это легко реализовать. Сначала пропишем ключи для нашего пользователя my_hard_username:

echo <Мой публичный ключик> >> cd ~/.ssh/authorized_keys

Далее возвращаемся в файл /etc/ssh/sshd_config и запрещаем доступ по паролю и доступ с пустым паролем:

PasswordAuthentication no
PermitEmptyPasswords no

После всех манипуляций с sshd_config перезапускаем сервер удаленного доступа.

sudo systemctl restart ssh.service # Для Ubuntu\Debian
# или
sudo systemctl restart sshd.service # Для RHEL/CentOS

6) Открытые порты. Надо позаботиться о том, чтобы "наружу" из сервера торчало как можно меньше портов, в целом, необходимо сузить порты до самого необходимого, это самое надежное, что можно порекомендовать для счастливой и веселой жизни в безопасности. Для начала посмотрим, какие порты открыты командой:

sudo netstat -tulpn
# или
sudo ss -tulwn | grep LISTEN

Результат будет следующий:

Открытые порты сервера
Открытые порты сервера

Прекрасно видим, какие порты и от какого приложения были открыты на сервере. Можем провести анализ и закрыть ненужные порты, мне в данном примере очень не нужно, чтобы порт 9090 торчал всему Миру на радость наружу, потому что он содержит в себе приложение, которое крутится в docker. А доступ к нему обеспечит мое Nginx приложение и так. Обращаемся к следующим командам для работы с портами:

iptables -A INPUT -p tcp --destination-port 9090 -j DROP

INPUT - входящий порт. tcp - протокол. destination-port - порт, который убираем. DROP - команда о том, что мы закрываем порт. Подробнее о том, как работать с блокировками портов и IP-адресов и прочие сетевые доступы можно тут.

Важно: Если у вас сервер на диструбутиве Debian\Ubuntu, а ковыряться в iptables тяжело, то есть прекрасная альтернатива в виде утилиты UFW (Uncomplicated Firewall), который настраивается за пару команд на нужные порты и адреса.

Важно: Для настоящей безопасности обычно закрывают все порты, а потом открывают нужные. Учитывайте это

Вывод

В данной статье вы увидели способы атак злоумышленников на наше приложение, NGINX, PostgreSQL, ELK, docker и sshd сервера, а я в свое время вам рассказал про эффективную профилактику от НСД, защиту своих драгоценных данных и про инструменты и способы для мониторинга и выявления фактов того, что к нам в гости стучатся злоумышленники. Проблемы и примеры взяты из реальных ситуаций и серверов.

Конечно, защищать сервера и приложения гораздо легче во внутреннем сетьевом контуре, но рано или поздно нам нужен будет выход наружу и мы должны быть к нему готовы. К сожалению, не удалось в этой статье затронуть тему DDoS-атак и других типов уязвимостей и как с ними бороться, но я надеюсь, что это будет материалом для следующих статей.

До новых встреч, друзья! Спасибо за внимание!

Приглашаю всех на чтение других интересных статей в мой telegram-канал

Комментарии (31)


  1. horror_x
    27.01.2022 05:37
    +1

    Прям глаз режет:

    if ($host !~ ^(example.com|www.example.com|docs.example.com)$ ) {
        return 444;
    }
    

    Не лучше ли как-то так?
    server {
        listen 80 default_server;
        listen 443 ssl default_server;
        return 444;
    }
    


    1. RekGRpth
      27.01.2022 06:23
      +4

      тогда уж для 443 лучше так

      server {
          listen 443 default_server ssl;
          listen [::]:443 default_server ssl;
          ssl_certificate /etc/certs/ssl-cert-snakeoil.pem;
          ssl_certificate_key /etc/certs/ssl-cert-snakeoil.key;
          ssl_session_tickets off;
          return 444;
      }


      1. LEVLLN Автор
        27.01.2022 10:16

        Это детали настройки NGINX, у меня на моем сервере так и настроено как указано у вас:

        server {
            listen 443 ssl;
            listen [::]:443 default_server ssl;
        
            ssl_certificate /ssl/nginx.crt;
            ssl_certificate_key /ssl/nginx.key;
            ssl_session_tickets off;
            access_log /var/log/nginx/data-access.log combined;
            return 444;
        
            location / {
               proxy_pass XXXX;
               proxy_set_header X-Real-IP  $remote_addr;
               proxy_set_header X-Forwarded-For $remote_addr;
               proxy_set_header Host $host;
               proxy_set_header X-Forwarded-Proto $scheme;
               proxy_redirect http:// https://;
               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection $connection_upgrade;
               proxy_read_timeout 20d;
               proxy_buffering off;
               }
           }


    1. LEVLLN Автор
      27.01.2022 10:17

      Спасибо большое!


  1. RekGRpth
    27.01.2022 06:26
    +1

    ещё, можно избавиться от процессов docker-proxy, поместив в (или создав) файл /etc/docker/daemon.json

    {
      "userland-proxy": false
    }
    


    1. LEVLLN Автор
      27.01.2022 10:13

      спасибо за замечание!


  1. RekGRpth
    27.01.2022 06:28
    +1

    ну, а чтобы не светить портом 9090 наружу, проще при запуске докер-контейнера вообще не публиковать этот порт, раз всё равно доступ к нему только из контейнера nginx


    1. LEVLLN Автор
      27.01.2022 10:19

      Порты и ситуации с ними указаны в качестве примера. На тот случай "Если вдруг возникла необходимость...и тут учимся работать с iptables"


  1. alexs963
    27.01.2022 07:02

    Не проще запретить все входящие соединения, а потом разрешить только на нужные порты? Не установлен fail2ban.


    1. LEVLLN Автор
      27.01.2022 10:13

      Да, это вообще best-practies. Цель открытых и закрытых портов средствами iptables показан как раз для того, чтобы новички имели представление, как это работает. Соглашусь, что лучше закрыть всё, кроме избранного.


      1. masterbo
        28.01.2022 03:15
        +2

        Ещё лучше сразу внушить новичкам, что все сервисы, не предназначенные для сторонних глаз должны перенастраиваться слушать не 0.0.0.0, а 127.0.0.1 (или любой из 127.0.0.0/8 адресов в случае разделения совпадающих портов). Не выводить наружу внутренние сервисы изначально - это реально best practice.

        Использование же файрвола должно быть уже частью тюнинга - например разрешить извне доступ к порту базы данных только с IP ваших других серверов, предназначенных для репликации БД.


  1. NikaLapka
    27.01.2022 09:09

    Если хочется безопасности и удобства, то первый шаг после покупки VPS это установка ОС с образа загруженного с debian.org, ubuntu.com,...


    1. LEVLLN Автор
      27.01.2022 10:11
      +1

      Токсичный комментарий, не раскрывающий ничего


      1. mxr
        27.01.2022 10:26
        +1

        Наверное, человек выше имеет ввиду что Вы получите чистую систему без доп.сервисов от провайдера (qemu-guest-agent и другие сервисы для управления ВМ). Гарантированно "чистое" ядро.
        Так же, некоторые хостинги добавляют собственные ssh-ключи, даже очень популярные это практиковали(Уловные, лет 7 назад в этом был замечен Firstvds).
        Это все мои предположения, по поводу комментария Выше. Возможно автору комментария есть что добавить.


        1. LEVLLN Автор
          27.01.2022 10:39
          +1

          Да, как раз таки хочется не додумывать за автором комментария, а в чистой дискуссии обсудить выбор диструбутива.

          А по поводу чистого ядра и системы - с Вами согласен. В принципе, ничего нет безопаснее того, что ты контролируешь сам, начиная от ОС, заканчивая железкой. Материал образовательный и для новичков как в плане хостинга серверов, так и в в принципе в карьере IT: подавал примеры на распространенные случаи, частые ошибки.

          Многие поставщики услуг vps\vds и сейчас добавляют ключи, насколько знаю, для поддержки. И много где закрыта возможность через VMware и без этих ключей взять и настроить (на очень бюджетных хостингах и датацентрах)


      1. NikaLapka
        27.01.2022 11:04
        +3

        В руководстве "VPS для чайников" в первой главе сказано, VPS - это в первую очередь компьютер подключенный к сети Интернет, поэтому сперва давайте ограничим доступ к нему из сети Интернет, а затем уже приступим к настройке, первая команда в консоле: # iptables -A INPUT -s <ваш IP> -p tcp -m tcp --dport 22 -j ACCEPT && iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable .

        Но, тут оказывается, что покупая услугу VPS, практически у большинства популярных бюджетных хостинг-провайдеров, выполнив шаг 1(см выше) мы рискуем получить ошибку. Как, почему, откуда? Дело тут в том, что почти все массовые хостинг-провайдеры предоставляют модифицированные версии популярных ОС debian, ubuntu,.. например, там может быть и iptables, iptables-legacy, nftables, nft, ufw, firewalld, и все уже со своими "особенно правильными и удобными" предустановленными цепочками правил. Хорошо это или плохо - это отдельная статья. Но об этом нужно помнить "самым маленьким", потому, что если мы считаем что система уже скомпрометирована, то дальнейшие действия по безопасности бессмысленны.


        1. LEVLLN Автор
          27.01.2022 11:17

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

          Про модифицированные версии согласен, очень много предустановленного ПО и нет возможности во многих бюджетных хостингах просто взять и поставить свой диструбутив - это боль. Изначально хотел писать статью про пользу развертывания со своей машины безопасного сервера, но не у всех есть белый IP-адрес, а ngrok я бы рекомендовал использовать людям на страх и риск :)


          1. mxr
            27.01.2022 11:48

            Белый IP на хосте и не нужен, достаточно доступа в интернет и VPN до сервера с белым IP и масскарадинга. Так же, если есть доп.адрес на vps с белыми ip можно и вовсе "Пробросить".


  1. el777
    27.01.2022 10:02
    +8

    Мой сервис имеет базу данных, до которой тоже дошли злые руки ботов, которые пытаются подобрать пароли. Это видно по следующим логам:

    С ужасом дочитал до конца статьи, а там подозрения подтвердились:

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

    Зачем вы выставили базу данных голой ж открытым портом наружу?

    Когда говорили про фаервол тоже не закрыли ее. Надеяться на pg_hosts не надо - никто не даст гарантий, что там нет бага. Рано или поздно он появится и вашу базу ломанут. Поэтому все внутрение сервисы должны слушать только на внутрненнем интерфейсе - чтобы даже ошибки конфигурации фаервола не открыли доступ. Наружу торчат только sshd и nginx.

    Вы закрываете фаерволом ненужные порты (тот же 9090), а надо делать наоборот - закрыть все по умолчанию и открывать только нужные (22, 80, 443 и ничего больше).

    Если хотите подключаться к базе с локального компьютера - пробрасывайте порт через ssh и работайте с ней.


    1. LEVLLN Автор
      27.01.2022 10:10
      -1

      Пример на скриншоте сделан ради примера. Сервер не реальный, а поднято в виртуальной среде. Как раз-таки для того, чтобы в образовательных целях показать, что есть определенные порты и необходимые нужно закрыть.


      Вы закрываете фаерволом ненужные порты (тот же 9090), а надо делать наоборот - закрыть все по умолчанию и открывать только нужные (22, 80, 443 и ничего больше).

      Вы точно читали текст после скриншота и точно ли понимаете грань между for example и реальными боевыми действиями?


      1. maxzh83
        27.01.2022 12:00
        +2

        Насколько понял, речь про то, что СУБД не должна торчать наружу в принципе. Вся работа с ней осуществляется только через ssh-туннель. И вот этого в статье не хватает как раз.


        1. LEVLLN Автор
          27.01.2022 12:12

          С подобным аргументом не спорю, всё так и надо: закрывать по возможности всё, открывать только для потребителя внешнего нужное. Для примера просто взят один порт для закрытия из множества.

          про ssh-тунель - очень годная мысль в целом


          1. mxr
            27.01.2022 13:07
            +1

            Для примера просто взят один порт для закрытия из множества.

            Обычно, идут от обратного. Т.е закрывают вообще все, и открывают только конкретные порты.


      1. el777
        28.01.2022 22:46
        +1

        Вы точно читали текст после скриншота и точно ли понимаете грань между for example и реальными боевыми действиями?

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

        Понимаете, слово "обычно" подразумевает, что можно и так и эдак. То есть фактически вы пишете: "Важно - можно делать по разному". Тем более нет пояснения почему это важно, в зависимости от чего надо выбирать? То есть на самом деле - это неважно.


        1. LEVLLN Автор
          29.01.2022 00:12

          Хорошее замечание. Учту, пока ещё новичок в написании подобных статей: это вторая моя статья на Хабре. Вы мне очень помогли этим советом. Будем исправляться


  1. uyrij
    27.01.2022 13:35

    В названии статьи стоило бы как-то упомянуть NGINX.


    1. LEVLLN Автор
      27.01.2022 20:45

      Я указал в хабах данную технологию. Так как имеется и Postgres, ELK, Nginx, iptables, ufw в этом обзоре. Подумал, что не вместится весь перечень инструментария)


  1. DenysPetrenko
    27.01.2022 14:48
    -3

    Супер! Добавил себе эту статью еще и на будущее


    1. LEVLLN Автор
      27.01.2022 20:43

      Очень рад, что понравилось!)


  1. AlePil
    28.01.2022 00:07
    +1

    В целом не плохо, но с учётом комментариев выше я бы советовал доработать что бы не было классической статьи "вредных советов". Безопасность сервера не бывает для маленьких и больших и не бывает первой и второй свжести: она или есть или её нет. Как с той осетриной.


    1. LEVLLN Автор
      29.01.2022 00:14

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