Страницы

Поиск по вопросам

воскресенье, 9 февраля 2020 г.

Нужен ли nginx для node.js сервера?

#nodejs #nginx


Нужно ли ставить nginx перед нодой?

У нас в компании занимаются поиском Т-функции у новичков, и поэтому на новый проект
я назначен главным backdoor разработчиком.

До этого ребята у нас ставили nginx перед нодой
и имели, с моей точки зрения кучу, проблем и неявных состояний.
Например между nginx и нодой рвется ws соединения, но nginxs об этом никому ничего
не говорит.
А между клиентом и nginx соединение в порядке, но данные почему-то не приходят.
Пришлось городить свой пинг-понг.  

На мой вопрос, а зачем вам вообще nginx, мне ответили что:
1) ничто так быстро не отдает статику как nginx;
2) в конце концов все всегда так делают.  

Ну статику мы отдаем клиенту 1 раз и ее не так уж много.
А вот json'ы потом гоняем туда-сюда сутками, сгусями и с прочими птицами.
А по поводу того, что nginx отдает статику так быстро потому, что он ее никак не
обрабатывает,
а видит из запроса что это "просто" статика и "просто" отдает ее (так мне объяснили) -
разве написав

арр.use(express.static( path.join(__dirname, '/static') ))


я не "просто" отдаю статику, никак ее не обрабатывая?

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

Буду благодарен услышать Ваши комментарии.
    


Ответы

Ответ 1



Да, nginx добавляет сложности, требуя настроить себя, но по-моему это с лихвой компенсируется получаемыми плюшками. Масштабируемость Работать с одной-единственной нодой получится только до тех пор, пока на сервере находится один-единственный сайт. Однако в моей практике такого не было почти никогда: я как минимум ставлю ещё Munin для наблюдения за состоянием сервера. Придётся или вешать сайт на отдельный порт/айпишник (неудобно), или дописывать в ноде код для проксирования запросов на другой сайт (замусоривание кода всякими сложностями). В то время как в nginx новый сайт легко подключить парой строчек в конфиге. Ещё один пример — A/B тестирование: запускаем две разные версии сайта, половину пользователей направляем на одну версию сайта, половину на другую, сравниваем их поведение и решаем, какая версия сайта лучше. Если изменения значительные, то скорее всего придётся запустить две ноды, и опять же нужно каким-то чудом решать, какой пользователь на какую ноду будет отправлен. Опять же в nginx это делается парой строчек (split_clients). Когда сайт станет большой и популярный, нода может перестать помещаться в одном процессе или одном сервере, и придётся запускать несколько экземпляров ноды или даже докупать новые серверы. nginx позволит равномерно распределить нагрузку между процессами/серверами, принимая все запросы на себя и пересылая его на один из случайно выбранных процессов/серверов (или не случайно — смотря как настроить). Безопасность Использовать стандартные порты 80/443 может только root. А когда код сайта запускается от рута, это ОЧЕНЬ плохо: малейшая RCE-уязвимость — и злоумышленник без проблем получает полный доступ к серверу. Если нода будет работать от рута, то малейшая уязвимость в коде сайта может позволить с лёгкостью получить контроль над сервером целиком (как с помощью RCE, так и с помощью чтения какого-нибудь ../../../../../../etc/shadow и последующего подбора пароля от рута в оффлайне, например). В идеале код должен быть максимально изолирован от всего (вплоть до помещения в изолированный Docker-контейнер (ходят слухи, что докер ещё и для разработки и развёртывания очень удобен, но я не верю)). Если нода будет изолирована от всех, то максимум, что получит злоумышленник — контроль над нодой. Ну и доступ к базе данных, если она используется. Это плохо, но не совсем плохо, потому что взломанную ноду можно просто выключить до исправления уязвимости. А вот выпнуть злоумышленника, получившего root, будет уже гораздо тяжелее (вплоть до необходимости отключения сервера от интернета и полной переустановки системы). Но, допустим, вы перекостыляли с роутингом или форками или пропатчили ядро или ещё что-то и в итоге каким-то чудом умудрились поднять ноду на порту 80/443 без root. Тогда пришло время вспомнить про HTTPS и сертификаты для него. Для работы SSL/TLS ноде нужен будет доступ к приватному ключу, и опять же, если злоумышленник откопает RCE-уязвимость, то он сможет прочитать приватный ключ и начать организовывать MitM-атаки. Если же HTTPS будет настроен на nginx и доступ к приватному ключу будет только у nginx, то злоумышленник обломается. (Хотя, конечно, налажать могут всегда и везде, даже у nginx+openssl однажды утекали приватные ключи... поэтому переходим на libressl) Кроме того, есть ряд менее серьёзных атак, которые всё же могут подпортить нервы. Например, манипуляции с медленными HTTP-запросами. В nodejs была уязвимость CVE-2013-4450, позволяющая завалить её HTTP pipelining запросами и тем самым скушать ресурсы сервера. Теоретически подобное, конечно, может найтись и в nginx, но всё же сама его архитектура неплохо спасает от подобных пакостей. При наличии nginx на ноду уже будут приходить белые и пушистые HTTP-запросы, доставляющие минимум проблем, в то время как всякий мусор будет отфильтрован или забуферизован самим nginx'ом. (Хотя от терабитных DDoS-атак ничего не спасёт, но не будем о грустном) Прочие плюшки Обязательно будут моменты, когда нода не будет работать (например, она может быть просто выключена на техработы). Без nginx пользователи получат просто какую-то невнятную ошибку браузера, уведомляющую о невозможности подключения. С nginx можно отдать статическую страницу с более понятным описанием ошибки и предложением сообщить о проблеме администраторам сайта, или же повесить плашку техработ и предложение подписаться на твиттер. Про вебсокеты Непонятно, что у вас за проблемы были — без подрбоностей понять, кто виноват и что делать, трудно; у меня всё проксируется через nginx вполне стабильно. А пинги должны быть в любом случае, потому что отвалиться по таймауту может что угодно где угодно даже не на вашем сервере (например, мобильный оператор Теле2 обрубает TCP-соединения после пяти минут бездействия). «Городить свой пинг-понг» не нужно, потому что эта фича встроена в протокол — не знаю, как именно вы реализуете вебсокеты в ноде, но пинги где-то там наверняка уже должны быть.

Ответ 2



Например между nginx и нодой рвется ws соединения, но nginxs об этом никому ничего не говорит. А между клиентом и nginx соединение в порядке, но данные почему-то не приходят. Видимо, криво настроили. 1) ничто так быстро не отдает статику как nginx; Правда. я не "просто" отдаю статику, никак ее не обрабатывая? Вы считываете файл средствами node.js и отдаёте в стрим. nginx, который на такие вещи заточен, явно будет быстрее. На своем проекте я пока стучусь непосредственно на ноду. Прав ли я? Возможно пока правы. Рационально ли это? Если сервис только для себя, то возможно. Или меня в будущем ждут непредвиденные трудности? При росте нагрузок как будете масштабировать? Если бы вы использовали nginx, то могли бы поднять несколько node.js сервисов на разных портах, а балансили бы их с помощью nginx. Если ваш сервис упадёт, что будете делать? Если понадобится SSL соединение, что будете делать? К тому же, если понадобится для статики в будущем CDN, то они очень хорошо умеют работать с nginx.

Комментариев нет:

Отправить комментарий