Здравствуйте, меня зовут Александр Зеленин, и я веб-разработчик сисадмин.
К сожалению, вся информация о полноценной развётки приложения на MeteorJS довольно разрозненна, и приходится в ручную решать миллион задач. В этой статье я хочу разобрать самую базовую (но уже достаточную для безопасной работы в продакшене) настройку сервера и последующий процесс ручного деплоя.
Разворачивать будем на Ubuntu 16, но, в целом, схема на 99% совпадает и для Debian 8.
На самом деле я близко не сисадмин, так что буду очень рад предложенным правкам, но в целом схема достаточно рабочая.
В качестве файловой системы при установке выбираем XFS — монга с ней хорошо дружит.
Если доступ у нас рутовый, то первое что надо сделать — создать пользователя.
adduser zav # Используйте свой %username% вместо zav apt-get install sudo usermod -aG sudo zav # Добавляем нашего пользователя в группу sudo, # что бы иметь возможность далее всё делать из-под него vi /etc/ssh/sshd_config # Если вы совсем не можете в vi — используйте тут nano вместо vi. # Если он не установлен — apt-get install nano
Нам надо изменить порт на случайный, по вашему выбору — это сразу защитит от части атак на ssh сервера.
Port 355 # Обычно изначально стоит Port 22 PermitRootLogin no # Запрещаем вход под рутом
Перезагружаем SSH
/etc/init.d/ssh restart
Теперь переподключаемся по SSH на новый порт (355) на нового, свежесозданного пользователя.
Я использую 2 раздельных физических диска что бы минимизировать шанс отказа.
Вы можете размещать всё на 1 на свой страх и риск, схема от этого не изменится.
В этом случае можете точно так же использовать папку /secondary, но не монтировать в неё диск.
sudo cfdisk /dev/sdb # имя второго диска (sdb) может отличаться. # Выбираем создать новый, 100% места, запись sudo mkfs.xfs /dev/sdb1 # создаем ФС на втором диске sudo mkdir /secondary sudo vi /etc/fstab # делаем авто-монтирование при запуске системы
Добавляем в конец (если второго диска нет — первую строку опускаем)
tmpfs — файловая система будет расположена в оперативной памяти. Т.е. запись в раздел /data/inmemory будет делать запись в оперативную память, а не на диск. Надо понимать что при перезагрузке оно очищается. size задает размер данной области. Ваша задача что бы её хватило на размещение монги со всеми индексами. В моём случае оперативной памяти 128Gb, соответственно под tmpfs выделено 32 гигабайта.
/dev/sdb1 /secondary xfs defaults 0 2 tmpfs /data/inmemory tmpfs size=25% 0 0
Актуальный способ установки можно посмотреть на официальном сайте.
В данном примере идёт установка версии 3.4 на Ubuntu 16.
Устанавливаем:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list sudo apt-get update sudo apt-get install mongodb-org
Создаем папки, конфиги и ставим права:
sudo mkdir /data sudo mkdir /data/db sudo mkdir /data/inmemory sudo mkdir /secondary/data sudo mkdir /secondary/data/db sudo vi /data/mongod-memory.conf
Подход, в котором primary в памяти может быть опасен, т.к. в случае внезапного выключения питания данные, которые не успели перейти в реплики — теряются. В моём случае потеря 1-2 секунд не страшна, т.к. всё приложение пишется с учетом возможности восстановления из любой позиции. Финансовые данные пишутся с параметром, подтверждающим что данные уже есть на реплике (т.е. на диске).
Если ваше приложение к такому не готово — вы можете отказаться от memory раздела и делать всё классически. В целом для этого достаточно будет убрать монтирование tmpfs и немного изменить конфиг, сделав его схожим с mongod-sec-d1.conf
processManagement: fork: true pidFilePath: "/data/inmemory/mongod.pid" storage: dbPath: "/data/inmemory" journal: enabled: false # Отключаем журналирование # т.к. в памяти в случае падения оно нас всё равно не спасёт indexBuildRetry: true wiredTiger: engineConfig: cacheSizeGB: 8 # Ограничиваем размер кеша. # Я, честно говоря, не уверен, но его можно убрать полностью, # т.к. это то, что монга для оптимизации поместить # в оперативную память, а данный инстанс уже весь в ней systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" # Для всех экземпляров указываем один инстанс. # Теоретически тут можно получить просадку, # если монга в памяти начнёт писать # на диск, но при нормальном функционировании # эти события редки (ошибки, медленный запросы) logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 127.0.0.1 # Делаем монгу доступной только для локального интерфейса # в случае если настраиваем реалтайм бекап добавляем внешний интерфейс port: 27000 # указываем на каких портах будем размещать, # они должны быть разные для разных инстансов в пределах сервера http: enabled: false # отключаем доступ по http и прочим интерфейсам JSONPEnabled: false RESTInterfaceEnabled: false ssl: # ssl нам тоже не нужен в данном случае mode: disabled security: # Мы будем настраивать корректный доступ по правам, #что бы клиенты видели только то, что им надо authorization: "enabled" keyFile: "/data/mongod-keyfile" # Это ключ для общения реплик между собой javascriptEnabled: false # Запрещаем исполнение JS в БД. replication: oplogSizeMB: 4096 # Указываем максимальный размер oplog'а. # случае падения реплик их восстановление будет быстрым # только если они отстали не более чем на размер oplog'a. # Корректный размер можно определить # в зависимости от приложения — как часто идёт изменение БД? replSetName: "consulwar" enableMajorityReadConcern: false # указываем что мы НЕ дожидаемся подтверждение # от реплики на запись для возврата значений поиска. operationProfiling: slowOpThresholdMs: 30 # указываем сколько максимум может выполнятся запрос, # после чего будет считаться медленным # и записан в лог, для последующей ручной обработки mode: "slowOp"
sudo vi /data/mongod-sec-d1.conf
По большей части конфиг повторяется, разница всего в паре мест.
Но оставляю для удобства
processManagement: fork: true pidFilePath: "/data/db/mongod.pid" storage: dbPath: "/data/db" journal: enabled: true # Обращаем внимание что тут журнал уже включен, # диск у нас считается надёным источником indexBuildRetry: true wiredTiger: engineConfig: cacheSizeGB: 8 # Фактически, даже если по какой-то причине Primary упадёт, # secondary будет использовать память но только для чтения systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 127.0.0.1 port: 27001 http: enabled: false JSONPEnabled: false RESTInterfaceEnabled: false ssl: mode: disabled security: authorization: "enabled" keyFile: "/data/mongod-keyfile" javascriptEnabled: false replication: oplogSizeMB: 4096 replSetName: "consulwar" enableMajorityReadConcern: false operationProfiling: slowOpThresholdMs: 30 mode: "slowOp"
sudo vi /data/mongod-sec-d2.conf
Разница, по сути, только в пути до БД и в зависимости от используемого порта.
processManagement: fork: true pidFilePath: "/secondary/data/db/mongod.pid" storage: dbPath: "/secondary/data/db" journal: enabled: true indexBuildRetry: true wiredTiger: engineConfig: cacheSizeGB: 8 systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 127.0.0.1 port: 27002 http: enabled: false JSONPEnabled: false RESTInterfaceEnabled: false ssl: mode: disabled security: authorization: "enabled" keyFile: "/data/mongod-keyfile" javascriptEnabled: false replication: oplogSizeMB: 4096 replSetName: "consulwar" enableMajorityReadConcern: false operationProfiling: slowOpThresholdMs: 30 mode: "slowOp"
Добавляем ключ для корректной работы реплики, устанавливаем права на папки
sudo openssl rand -base64 741 > ~/mongod-keyfile sudo mv mongod-keyfile /data/mongod-keyfile sudo chmod 600 /data/mongod-keyfile sudo chown mongodb:mongodb -R /data sudo chown mongodb:mongodb -R /secondary/data
Создаем скрипты автозапуска
sudo apt-get install numactl sudo mv /lib/systemd/system/mongod.service /lib/systemd/system/mongod@.service sudo vi /lib/systemd/system/mongod@.service
@ в названии сервиса означает что мы можем запускать его с параметрами.
Данный скрипт устанавливает все необходимые параметры ОС для работы с монгой — удобно.
[Unit] Description= Mongo Database on %i After=network.target [Service] Type=forking ExecStartPre=/bin/sh -c '/bin/echo never > /sys/kernel/mm/transparent_hugepage/enabled' ExecStartPre=/bin/sh -c '/bin/echo never > /sys/kernel/mm/transparent_hugepage/defrag' User=mongodb Group=mongodb PermissionsStartOnly=true ExecStart=/usr/bin/numactl --interleave=all /usr/bin/mongod --config /data/mongod-%i.conf LimitFSIZE=infinity LimitCPU=infinity LimitAS=infinity LimitNOFILE=64000 LimitNPROC=64000 TasksMax=infinity TasksAccounting=false [Install] WantedBy=multi-user.target
Говорим БД запускаться при старте системы и так же запускаем экземпляры прямо сейчас.
Наш параметр устанавливается после @, например, memory укажет использовать при запуске /data/mongod-memory.conf
sudo systemctl enable mongod@memory sudo systemctl enable mongod@sec-d1 sudo systemctl enable mongod@sec-d2 sudo service start mongod@memory sudo service start mongod@sec-d1 sudo service start mongod@sec-d2
Подключаемся к монге, инициализируем реплику, устанавливаем пользователей
mongo localhost:27000/admin
Выполняем в консоли монги
rs.initiate({ _id: "consulwar", // название реплики version: 1, protocolVersion: 1, writeConcernMajorityJournalDefault: false, // Говорим что бы реплика не дожидалась // подтверждения о записи от других configsvr: false, // Указываем, что это не конфигурационный сервер для кластера // (кластер — тема отдельной статьи) members: [ { _id: 0, // id начинаем от нуля и далее инкрементим host: 'localhost:27000', // по какому адресу доступна данная монга arbiterOnly: false, // может ли отдавать и хранить данные buildIndexes: true, // указываем что строить индексы надо hidden: false, // не скрытая, т.е. приложение к ней может подключиться priority: 100, // приоритет при выборе Primary — чем больше, тем приоритетнее slaveDelay: 0, // задержка репликации. Нам задержка не нужна. votes: 1 // может ли голосовать при выборе Primary }, { _id: 1, host: 'localhost:27001', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 99, // Приоритет ниже slaveDelay: 0, votes: 1 }, { _id: 2, host: 'localhost:27002', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 98, slaveDelay: 0, votes: 1 } ], settings: { chainingAllowed : true, // Разрешаем репликам читать друг с друга, а не только с мастера electionTimeoutMillis : 5000, // Указываем время на переголосование, // в случае падения одной из БД. ~7 секунд. // Если все экземпляры у нас на 1 машине // можем уменьшить до 500мс, скажем catchUpTimeoutMillis : 2000 } }); // Создаем первого пользователя, он должен иметь права root'а db.createUser({user: 'zav', pwd: '7Am9859dcb82jJh', roles: ['root']}); // Выходим - ctrl+c, ctrl+c
Подключаемся под нашим пользователем
mongo localhost:27000/admin -u zav -p '7Am9859dcb82jJh' --authenticationDatabase admin
Добавляем пользователя для работы с приложением
use consulwar // вместо consulwar название основной БД вашего приложения db.createUser({ user: 'consulwar', pwd: '37q4Re7m432dtDq', roles: [{ // Права на чтение и запись в нашу БД. // Включает ещё ряд прав, типа создание индексов и т.п. role: "readWrite", db: "consulwar" }, { // Права на чтение oplog'а, для быстрой работы приложения метеора role: 'read', db: 'local' }] });
Теперь довольно важный и сложный вопрос — реалтайм репликация для бекапа. Целиком он рассмотрен не будет, ввиду необходимости настройки ещё ряда оборудования, чего я бы хотел избежать в данной статье.
Реплицировать мы будем на внешний сервер (иначе в чём смысл бекпап? :-)).
На внешнем сервере должна быть установлена монга схожим образом.
Примерный конфиг:
processManagement: fork: true pidFilePath: "/data/db/mongod.pid" storage: dbPath: "/data/db" journal: enabled: true indexBuildRetry: false # Отключаем построение индексов wiredTiger: engineConfig: cacheSizeGB: 0 # Отключаем кеш systemLog: destination: "file" path: "/var/log/mongodb/mongodb.log" logAppend: true quiet: false verbosity: 0 logRotate: "reopen" timeStampFormat: "iso8601-local" net: bindIp: 222.222.222.222 # Данный экземпляр должен быть доступен из-вне port: 27000 http: enabled: false # но не по http, само собой JSONPEnabled: false RESTInterfaceEnabled: false ssl: mode: disabled security: authorization: "enabled" keyFile: "/data/mongod-keyfile" # mongod-keyfile берем с основного сервера javascriptEnabled: false replication: oplogSizeMB: 0 replSetName: "consulwar" enableMajorityReadConcern: false operationProfiling: mode: "off" # нам не нужно профилирование на бекапе
В фаерволе сервера-бекапа разрешаем коннект на 27000 порт ТОЛЬКО с IP сервера-приложения/бд.
Тоже самое, на сервере приложения/БД в bindIp указываем смотреть ещё и во внешний интерфейс (ip внешний сервера), и в iptables разрешаем доступ на 27000-27002 порты ТОЛЬКО с ip севера-бекапа.
При инициализации/реинициализации реплики добавляем
{ _id: 4, host: '222.222.222.222:27000', // собственно интерейс, на который смотрит бекап arbiterOnly: false, buildIndexes: false, // не строим индексы вообще на бекапе hidden: true, // скрытый! Используется ТОЛЬКО для хранения информации priority: 0, // Не участвует в выборах slaveDelay: 0, // Задержка бекапа нам не нужна, // но может использоваться если нужно пару бекапов в реалтайме "час назад" votes: 0 // Не участвует в голосовании }
Готово! Теперь данные будут литься в реалтайме ещё и во внешний бекап, что очень круто.
В случае полного краха приложения мы можем инициализировать реплику точно так же, и она восстановится из бекапа.
Поверьте, это намного быстрее чем mongodump/mongorestore (по личным прикидкам в 25-100 раз).
Устанавливаем ноду, ставим модуль n, ставим им версию ноды 4.8.1 (последняя, официально поддерживаемая метеором версия).
Устанавливаем pm2, т.к. именно им будем запускать процессы.
sudo apt-get install nodejs sudo apt-get install npm sudo npm install -g n sudo n 4.8.1 sudo npm install pm2@latest -g
Добавляем пользователя, из-под которого будет всё запускаться и который будет отвечать за деплой
sudo adduser consulwar
Заходим за данного пользователя
su consulwar mkdir app mkdir app/current
На локальной машине заходим в директорию с нашим meteor проектом.
Создаем папку для билдов, собираем проект в эту папку.
mkdir ../build meteor build ../build/ --architecture os.linux.x86_64
Полученный архив загружаем на наш сервер, например, по sftp. Заходим под нашим пользователем для приложения.
Загружаем в папку ~/app.
Заходим по ssh за нашего пользователя (consulwar у меня).
cd app mkdir 20170429 # создаем папку по сегодняшней дате tar -xvzf consulwar-master.tar.gz -C 20170429 ln -s 20170429/bundle ~/app/current # Создаем симлинк, что бы быстро переключаться (cd current/programs/server && npm install) vi pm2.config.js # создаем конфиг для нашего pm2
var settings = { ... }; // Объект заменяем объектом из settings.json вашего приложения var instances = 10; // Сколько экземпляров запускаем? Советую не более N-1 // Где N — количество ядер var apps = []; for (var i = 0; i < instances; i++) { apps.push({ "script": "/home/consulwar/app/current/bundle/main.js", // укажите корректный путь "exec_mode": "fork", // т.к. рулить будем через Nginx, создаем форками "name": "consulwar", // имя приложения в списке процессов "env": { "ROOT_URL": "http://consulwar.ru/", // Адрес приложения "HTTP_FORWARDED_COUNT": 1, // Указываем количество прокси перед приложением // Что бы корректно разрулить IP пользователя в приложении "PORT": 3000 + i, // Порты начинают с 3000 (3000, 3001, 3002...) "MONGO_URL": "mongodb://consulwar:37q4Re7m432dtDq@localhost:27000,localhost:27001,localhost:27002/consulwar?replicaSet=consulwar&readPreference=primary&authSource=consulwar", "MONGO_OPLOG_URL": "mongodb://consulwar:37q4Re7m432dtDq@localhost:27000,clocalhost:27001,localhost:27002/local?replicaSet=consulwar&authSource=consulwar", "METEOR_SETTINGS": settings } }); } module.exports = { apps : apps }
И запускаем
pm2 startup pm2.js # Выведет команду, которую надо выполнить для автозапуска после перезагрузки ... # Выполняем команду pm2 start pm2.js pm2 status # Валидируем, что всё запустилось. В случае ошибок можем посмотреть pm2 logs
Готово, приложение развернуто и уже должно быть доступно по ip сервера/адресу с указанием порта, например http://consulwar.ru:3000
sudo apt-get install software-properties-common sudo add-apt-repository ppa:nginx/stable sudo apt-get install nginx sudo vi /etc/nginx/nginx.conf
user www-data; # из-под кого запускаем nginx worker_processes 6; # Указываем количество воркеров worker_rlimit_nofile 65535; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 4000; # Кол-во подключений на воркера # В нашем случае мы можем обработать 6 * 4000 = 24 000 запросов # в момент времени } http { map $http_upgrade $connection_upgrade { # Для корретной установки сокет-подключения default upgrade; '' close; } include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; server_tokens off; sendfile on; # Для отправки статики tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; gzip on; # Включаем gzip gzip_comp_level 6; gzip_vary on; gzip_proxied any; gzip_buffers 16 8k; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; gzip_static on; # Разрешаем отдачу файлов с .gz на конце. Например, main.js.gz будет отдаваться при запросе main.js gzip_http_version 1.1; gzip_disable "MSIE [1-6]\.(?!.*SV1)" proxy_connect_timeout 60; proxy_read_timeout 620; proxy_send_timeout 320; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; upstream backends { #ip_hash; # указываем если нам надо что бы пользователь всегда подключался к одному и тому же экземпляру приложения least_conn; # Я выбрал что бы подключение отдавалось наименее нагруженному процессу # Прописываем каждый из интерфейсов # Я запускал их 10, значит тут 10 записей server 127.0.0.1:3000 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3001 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3002 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3003 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3004 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3005 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3006 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3007 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3008 weight=5 max_fails=3 fail_timeout=60; server 127.0.0.1:3009 weight=5 max_fails=3 fail_timeout=60; # Интерфейс, который будет отрабатывать в случае недоступности приложения server 127.0.0.1:3100 backup; } # Указываем пути до ssl сертификатов. Мы их создадим чуть позже ssl_certificate /etc/letsencrypt/live/consulwar.ru/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/consulwar.ru/privkey.pem; ssl_dhparam /etc/ssl/certs/dhparam.pem; ssl_stapling on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!EXP:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; server { server_name consulwar.ru; # указываем слушать 80 и 443 порты listen 80; listen 443 ssl http2; # любой запрос переадресовываем на одно из наших приложений location / { proxy_pass http://backends; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header X-Forwarded-For $remote_addr; } # Статику раздаем с помошью nginx location ~* \.(jpg|jpeg|gif|ico|png)$ { root /home/consulwar/app/current/programs/web.browser/app; } # Основной css и js файл лежит отдельно, добавляем правило дополнительное location ~* "^/[a-z0-9]{40}\.(css|js)$" { root /home/consulwar/app/current/programs/web.browser; } location ~ "^/packages" { root /home/consulwar/app/current/programs/web.browser; } # В случае если у вас никаких систем мониторинга не стоит, # можно убрать следующую конструкцию. location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all; } # Для получения SSL сертификата location ~ "^/.well-known" { root /home/consulwar/app/current/programs/web.browser/app/.well-known; } } include /etc/nginx/conf.d/*.conf; client_max_body_size 128m; }
Перезапускаем nginx
sudo service nginx restart
Получаем SSL от Let’s Enctypt.
Само собой, домен уже должен быть привязан к этому IP адресу.
sudo apt-get install letsencrypt sudo letsencrypt certonly -a webroot --webroot-path=/home/consulwar/app/current/programs/web.browser/app -d consulwar.ru sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 # Генерируем дополнительный сертификат безопасности
Вжух! SSL Работает
sudo vi /etc/network/if-up.d/00-iptables
#!/bin/sh iptables-restore < /etc/firewall.conf ip6tables-restore < /etc/firewall6.conf
sudo chmod +x /etc/network/if-up.d/00-iptables apt-get install xtables-addons-dkms sudo vi /etc/firewall.conf
*filter :INPUT ACCEPT [193038:64086301] :FORWARD DROP [0:0] :OUTPUT ACCEPT [194475:60580083] -A INPUT -i lo -j ACCEPT # Разрешаем локальное общение -A INPUT -m state --state RELATED,ESTABLISHED -p all -j ACCEPT # Разрешаем существующие подключения # Разрешаем SSH -A INPUT -m state --state NEW -p tcp -m multiport --dport 355 -j ACCEPT # Доступ к Nginx -A INPUT -m state --state NEW -p tcp -m multiport --dport 80,443 -j ACCEPT # Ловушка для кривых подключений, будет тратить ресурсы атакующего, а не сервера -A INPUT -p tcp -m tcp -j TARPIT # Дропаем всю фигню -A INPUT -p udp -j DROP COMMIT
sudo vi /etc/firewall6.conf # оставляем пустым или заполняем что вам надо sudo iptables-restore < /etc/firewall.conf
itables настроены, и лишние порты закрыты.
DONE!
Если понравится подход/формат — выложу настройку почтовой системы, мониторинга инфраструктуры, CI через Bamboo и ещё ряд используемых у нас вещей.
Вполне вероятно что что-то я упустил (но в целом прямо вот так должно работать) — спрашивайте, дополню.
Надеюсь, у кого-то это теперь займет меньше времени, чем у меня 🙂
PS: У нас открыта вакансия front-end разработчика.
ссылка на оригинал статьи https://habrahabr.ru/post/327624/
Добавить комментарий