Instagram может быть платформой для обмена фотографиями, видео и роликами, но иногда именно текст бросается в глаза. Возможно, кто-то поделился ссылкой в своей подписи или комментарии в Instagram, и вы хотите открыть ее. Но, к сожалению, ссылки, которыми поделились в подписях или комментариях Instagram, не кликабельны.
Итак, какова альтернатива? Если вы не хотите вводить все это самостоятельно, и давайте посмотрим правде в глаза, никто этого не делает, единственный вариант — скопировать текст, чтобы получить эту ссылку. Или, может быть, вы наткнулись на красивую подпись, которую хотите скопировать для своих сообщений. Но проблема в том, что приложение Instagram на наших телефонах тоже не позволяет копировать текст. Итак, каково решение? Как обычно, мы собираемся использовать обходные пути для копирования текста из Instagram на iPhone.
Используйте функцию Live Text на iPhone
Apple представила функцию живого текста в iOS 15. На iPhone XS, XR и более поздних версиях функция живого текста может обнаруживать текст на изображениях на вашем iPhone или в Интернете, чтобы вы могли копировать и делиться или переводить текст на фотографиях. Мы будем использовать эту функцию для копирования текста из Instagram, что сделает все это испытание совершенно безболезненным.
Сначала откройте приложение Instagram и перейдите к сообщению с заголовком/комментарием, который вы хотите скопировать. Затем сделайте скриншот текста. Чтобы сделать снимок экрана, одновременно нажимайте кнопки блокировки и увеличения громкости, пока не увидите миниатюру снимка экрана в левом нижнем углу экрана.
Как только миниатюра исчезнет, снимок экрана появится в приложении «Фотографии».
Перейдите в приложение «Фотографии» и откройте только что сделанный снимок экрана. Затем коснитесь и удерживайте слова, которые хотите скопировать, пока не появятся точки захвата. Переместите точки захвата, чтобы включить весь текст, который вы хотите включить, или нажмите «Выбрать все», чтобы выбрать весь текст на снимке экрана.
Затем нажмите кнопку «Копировать» из плавающих вариантов, чтобы скопировать текст. И вставьте его куда угодно.
Это так просто.
Используйте Instagram в браузерном приложении
К сожалению, функция Live Text доступна не на всех моделях iPhone. Итак, что, если на вашем iPhone нет функции живого текста, но вы все равно хотите скопировать что-то из подписи в Instagram? Есть простой обходной путь, который включает использование Instagram в браузере.
Перейдите к сообщению с текстом в заголовке и коснитесь значка «меню из трех точек».
Затем коснитесь параметра «Ссылка» в меню, чтобы скопировать ссылку.
Скопируйте ссылку в браузере, чтобы открыть пост. Если вы ранее не входили в свою учетную запись в браузере, вам необходимо войти сейчас, чтобы получить доступ к полной подписи.
Вы также можете напрямую перейти на instagram.com и перейти к сообщению вручную.
Затем нажмите и удерживайте текст в подписи, пока не появятся точки захвата. Затем переместите их, чтобы включить полный текст, который вы хотите скопировать, и нажмите кнопку «Копировать».
К сожалению, вы не можете копировать текст в комментариях таким образом, за исключением одного или двух комментариев, которые появляются непосредственно в ленте.
То есть, если вы нажмете кнопку «Просмотреть все комментарии» и попытаетесь скопировать комментарий или даже заголовок с этой страницы, вы не сможете это сделать.
Используйте Google Фото в качестве альтернативы
Если вы отчаянно хотите скопировать текст из комментария к публикации в Instagram, вы можете использовать приложение Google Фото. Вы можете использовать функцию «Google Объектив» в приложении Google Фото, чтобы обнаруживать и копировать текст со снимка экрана, независимо от того, поддерживает ли ваш телефон Live Text или нет.
Если у вас его еще нет, установите приложение «Google Фото» из App Store.
Сделайте скриншот раздела комментариев или подписи из приложения Instagram.
Затем перейдите в приложение Google Фото и откройте снимок экрана. Нажмите кнопку «Google Объектив» на панели инструментов внизу.
Переключитесь на опцию «Текст».
Как только текст будет обнаружен, нажмите и удерживайте слова, пока не появятся точки захвата. Затем переместите точки захвата, чтобы выбрать нужный текст, и коснитесь параметра «Копировать текст» внизу.
В следующий раз, когда вы наткнетесь на подпись, которую хотите скопировать для себя, или на ссылку в комментариях Instagram, у вас есть более простые способы, чем копировать ее вручную туда и обратно.
Многие пользователи сообщают, что установка Windows 10 завершается ошибкой без какого-либо кода ошибки. Код ошибки поможет вам понять, с какой ошибкой сталкивается ваше устройство, чтобы вы могли предпринять соответствующие шаги для ее устранения. Но когда код ошибки отсутствует, вы летите вслепую, и это несколько усложняет устранение неполадок.
Тем не менее, это не невозможно, и мы составили список решений, которые помогут вам быстро решить эту проблему и позволят установить Windows 10 на ваше устройство.
Общие исправления
Прежде чем перейти к перечисленным ниже исправлениям, вот несколько общих простых исправлений, которые вы должны попробовать, чтобы устранить ошибку установки:
Удалите все периферийные устройства: если у вас есть какие-либо ненужные внешние периферийные устройства, такие как наушники, USB-устройства, внешние жесткие диски, принтеры, сканеры и т. д., отключите их. Они могут помешать установке. Если ваш ноутбук подключен к док-станции, также отстыкуйте его.
Обновите драйверы: перед установкой Windows убедитесь, что все важные драйверы обновлены.
Удалите сторонний антивирус: если вы используете стороннее антивирусное программное обеспечение, удалите его и используйте только Microsoft Defender, по крайней мере, пока вы пытаетесь обновить Windows. Стороннее антивирусное программное обеспечение часто может вызывать проблемы с обновлениями Windows. После завершения установки вы можете переустановить программное обеспечение. Но перед удалением убедитесь, что у вас есть необходимая информация для активации, чтобы вы могли повторно активировать ее.
Освободите место на диске: на вашем жестком диске должно быть достаточно места для установки Windows. Если он не получит требуемого места, установка завершится ошибкой. Проверьте место на диске в проводнике (или проводнике Windows в Windows 7) и при необходимости освободите место.
Попробуйте обновить Windows после выполнения этих исправлений. Если вы все еще видите код ошибки, перейдите к дополнительным техническим исправлениям, перечисленным ниже.
Способ 1. Разверните команду DISM и SFC
Сканирование обслуживания образов развертывания и управления ими проверит и восстановит существующие файлы операционной системы, установленные на вашем устройстве, вместе с другими системными файлами.
Перейдите в меню «Пуск» и введите «Командная строка», чтобы найти его. Затем нажмите «Запуск от имени администратора» в правой части меню, чтобы продолжить.
Затем, если вы не вошли в систему с учетной записью администратора, введите учетные данные для нее. В противном случае нажмите кнопку «Да», чтобы продолжить.
Затем введите или скопируйте+вставьте указанную ниже команду и нажмите Enter на клавиатуре. Это восстановит текущий установленный образ ОС на вашем устройстве.
DISM/ Online/Cleanup-Image/RestoreHealth
После завершения введите или скопируйте+вставьте следующую команду и нажмите Enter, чтобы проверить и восстановить системные файлы на вашем ПК.
SFC /scannow
Если после сканирования вы получите сообщение об успешном завершении сканирования, попробуйте обновить Windows еще раз или перейдите к следующему исправлению. Но если при сканировании он обнаружит поврежденные файлы, удалите эти файлы, а затем попробуйте обновить компьютер.
Способ 2: восстановить данные конфигурации загрузки (BCD)
Многие пользователи, обычно отвечающие за правильную загрузку вашего компьютера, сообщают, что восстановление их данных BCD помогло решить проблему с установкой Windows 10.
Чтобы восстановить компьютер, вам потребуется доступ к инструменту Advanced Startup Repair в вашей системе. Для этого включите компьютер и при первых признаках загрузки нажмите и удерживайте кнопку «Питание» в течение 10 секунд, чтобы принудительно выключить компьютер. Вы также можете отключить свой компьютер, если вы используете настольную систему.
Повторите этот процесс три раза, а в четвертый раз дайте компьютеру перезагрузиться как обычно. Advanced Startup Repair запустится автоматически, и вас встретит синий экран. Нажмите на плитку «Устранение неполадок», чтобы продолжить.
После этого нажмите на плитку «Дополнительные параметры», чтобы продолжить.
Затем щелкните плитку «Командная строка».
После этого введите или скопируйте+вставьте приведенные ниже команды по одной за раз и нажимайте Enterпосле ввода каждой из них, чтобы выполнить их.
bootrec /FixMbr
bootrec /RebuildBcd
bootrec /ScanOs
bootrec /FixBoot
Выполнив все команды, снова перезагрузите компьютер и проверьте, сохраняется ли проблема.
Способ 3: удалить конфликтующие языковые пакеты
Многие пользователи подтвердили, что удаление дополнительных языковых пакетов из их системы позволило им решить проблему на своем ПК.
Сначала откройте приложение «Настройки» в меню «Пуск». Либо нажмите клавиши Windows+ Iна клавиатуре, чтобы открыть приложение.
После этого выберите плитку «Время и язык», чтобы продолжить.
Затем нажмите на вкладку «Язык» на левой боковой панели. Затем щелкните языковой пакет, который вы хотите удалить, чтобы развернуть плитку. Затем нажмите кнопку «Удалить» в расширенном представлении, чтобы удалить язык из вашей системы.
Повторите вышеупомянутый процесс, если в вашей системе установлено несколько языков. После этого перезагрузите систему и проверьте, решена ли проблема.
Способ 4: запустить установку в чистой загрузке
Часто сторонние службы или программное обеспечение могут мешать процессу установки Windows. Вы можете устранить эту проблему, запустив установку в чистой загрузке, где работают только основные службы Microsoft.
Сначала нажмите клавиши Windows+ Rна клавиатуре, чтобы открыть утилиту «Выполнить команду». Затем введите msconfig и нажмите Enterна клавиатуре, чтобы продолжить.
После этого щелкните параметр «Выборочный запуск», а затем щелкните, чтобы выбрать параметр «Загрузить системные службы».
Затем перейдите на вкладку «Службы» и установите флажок перед параметром «Скрыть все службы Microsoft». Затем нажмите кнопку «Отключить все», чтобы отключить все службы, кроме служб Microsoft.
Затем нажмите кнопку «Применить», чтобы применить изменения, и нажмите кнопку «ОК», чтобы закрыть окно.
Теперь перезагрузите компьютер из меню «Пуск». ПК запустится в режиме чистой загрузки и снова запустит установку.
Ну вот, ребята. С помощью способов, изложенных в данном руководстве, вы сможете легко и быстро устранить ошибку установки Windows 10 на свой ПК.
Для детей, которые без ума от сладостей, развитие кариеса является распространенным явлением. Для предотвращения патологического процесса, способного испортить улыбку, важно следить за состоянием ротовой полости. Эта задача ложится на плечи родителей, и требует соблюдения определенных мер и рекомендаций.
Почему возникает кариес у детей?
Для того чтобы профилактика кариеса оказалась максимально эффективной, важно установить причину, по которой развивается заболевание. Наиболее частыми являются следующие причины:
Отсутствие должной гигиены полости рта, в результате чего образуется скопление остатков пищи вокруг зубов. Это приводит к размножению вредоносных бактерий.
Обилие сладкой пищи в рационе провоцирует нарушение кислотно-щелочного баланса ротовой полости. В результате возникают условия для жизнедеятельности патогенных микроорганизмов.
Остальные причины преимущественно являются врожденными, и передаются от родителей, либо возникают во время утробного развития. В зависимости от природы развития кариеса, требуются определенные меры профилактики. Установить источник проблемы помогут профессионалы. Ознакомиться с перечнем услуг, оказываемых в стоматологии «Апекс» и записаться на прием можно по ссылке https://apex24.ru/services/.
Эффективные меры профилактики кариеса у детей
Для результативной профилактики следует придерживаться ряда рекомендаций:
Забота о зубах должна иметь регулярный характер. Более того, важно побеспокоиться об этом моменте еще во время беременности. Необходимо уделять должное внимание питанию, что позволит избежать проблем в дальнейшем.
Недопустимо пренебрегать профилактическими и лечебными мерами до смены молочных зубов «постоянным» комплектом. «Временные» зубы не меньше нуждаются в уходе.
Особую роль играет укрепление иммунитета ребенка для увеличения способности сопротивляться воздействию агрессивных факторов. Крепкий организм менее подвержен разрушению зубной эмали, приводящему к проникновению инфекции глубоко в ткани зуба.
Важно правильно подобрать зубную пасту и щетку для ребенка, а также своевременно обновлять средства гигиены.
Привить правильные принципы гигиены поможет специалист. Поскольку не все взрослые умеют корректно чистить зубы, стоит обратиться за консультацией стоматолога.
Комплексный подход позволит избежать развития кариеса у ребенка. Взяв за привычку регулярно посещать кабинет стоматолога, удастся предупредить неприятные последствия заболевания.
Сам Хельм в общих чертах рассмотрели в посте Helm: Kubernetes package manager — обзор, начало работы – теперь надо прикрутить его в Jenkins. И не просто прикрутить его вызов – а создать чарт, потому что сейчас приложение деплоится через “голые” манифест-файлы Kubernetes, в котором sed проставляет теги Докер-образа и значения переменных для загрузки на окружение через kubectl apply -f.
Данный пост очередной НЕ-HowTo, а пример знакомства с Helm: возьмём существующий проект, который уже деплоится в Kubernetes-кластер, обновим его манифесты, что бы использовать их с Helm, продумаем – как именно и куда будем деплоить, и создадим Jenkins-джобу.
По ходу дела будем ближе знакомиться с Helm, и его подводными камнями.
Итак, у нас имеется некое веб-приложение, которое надо деплоить в Kubernetes.
Само приложение разбито на две части – фронтенд на React, хостится и деплоится в AWS S3, и бекенд – NodeJS, работает в Docker-контейнере.
Первый вопрос, который появляется в голове – монорепа, или нет?
Т.е. – где хранить код приложения, где – файлы чартов Helm-а, а где – jenkins-файлы?
Хотелось бы монорепу, и всё держать в одном репозитории, но у нас подобных проектов будет не один, и смысла под каждый писать отдельные дженкис-файлы нет. Тем более, что если (когда!) захочется что-то изменить в одном – то придётся делать это во всех по отдельности.
При этом и их файлы манифестов для Kubernetes будут практически одинаковы – и можно было бы заморочится вообще, и используя возможности шаблонизатора Go – использовать один общий чарт на всех.
Но так как их одинаковость пока под вопросом – запускаемые веб-проекты ещё только разрабатываются, да ещё и отдельными группами девелоперов – то чарты будем делать под каждый проект отдельно.
Значит, у нас будет:
отдельный репозиторий с кодом проекта
там же в отдельной папке храним файлы чартов
отдельный репозиторий с файлами для Jenkins-pipeline
Хочется прикрутить ещё и релизы, да ещё и связать их с Github Releases – но это, может быть, потом. В целом – реализуемо, и даже есть helm/chart-releaser.
Jenkins build steps
Дальше.
Билд Docker-образов – и билд/деплой самих чартов – делать одной джобой – или разными?
Сейчас у нас образы собираются в одной джобе, после чего пушатся в DockerHub, после чего девелопер должен сходить в джобу деплоймента, и при запуске в параметрах указать тег (номер билда) + дополнительные параметры:
Это, конечно, ни разу неудобно, поэтому переделаем.
Опционально – удалять с chart uninstall. Про удаление ресурсов вообще поговорим ниже.
Что ещё?
Namespaces
Ооо – нейспейсы жеж!
Что хочется:
иметь возможность деплоить по одной кнопке в какой-то дефолтный namespace, имя которого зависит от проекта/приложения/чарта
деплоить в кастомный namespace – по имени бранча репозитория, из которого запускался билд
деплоить в вообще кастомный namespace – дать возможность указать его при старте джобы
А как их потом удалять?
Можно добавить вебхук из Гитхаба при delete-операциях, но во-первых часть проектов хостятся в Gitlab – хотя он тоже умеет в вебхуки. Но во-вторых – а все ли девелоперы всех команд будут удалять свои закрытые бранчи?
Т.е. тут проблема как раз из-за разных команд и разных проектов, а решение хочется иметь маскимально универсальное.
А удалять НС-ы надо – иначе будет пачка заброшенных ресурсов – подов, ингресов, волюмов, и т.д.
Что делать?…
Окей. А пусть будет какой-то дефолтный неймспейс. Например, чарт/приложение называются bttrm-apps – значит, для Dev-деплой джобы НС будем создавать bttrm-apps-dev-ns.
В джобе добавить параметр, в нём сделать возможность выбора – использовать этот дефолтный НС, создать/использовать НС по имени бранча, или указать свой.
Можно так в Jenkins?
Не факт – идём глянем.
Choise parameter – тут просто задаётся список предефайненных значений – нельзя будет задать своё имя НС-а:
А Multi string parameter?
Вроде как что-то аналогичное Choise parameter?
Смотрим на него:
Нет, тоже не подходит – оно просто из параметра передаст нам в переменную дженкисфайла значение из нескольких строк, а нам нужна одна string.
Значит – или таки обычный String параметр, или Choise parameter с набором уже заданных значений… Но тогда потеряем возможность создать кастомный НС…
Или… Или… Или… Мысль…
А что на счёт Boolien parameter?
Типа “поменять НС”…
Дефолтное значение “не менять” – и используем предефайненное значение bttrm-apps-dev-1-ns…
А если юзер выбирает менять – то используем имя НС как имя бранча – а имя бранча вытянем из репозитория после чекаута…
Мысль? А может быть!
Хотя снова-таки – лишаемся возможности создать кастомный НС…
А что если просто использовать тот же Choise parameter с набором уже заданных значений, но создать три значения:
use default bm-apps-dev-ns
use github-branch-name
set own name
А потом в коде самого пайплайна проверять выбор, и если выбрано set own name – то просто запросить User input, и пользователь задаст имя неймспейса, который хочет создать.
Тоже не самое кошерное решение – но может сработать. Пока остановимся на нём.
Остаётся открытым вопрос про удаление НС-ов – будем думать потом
Хотя потом может быть больно.
В конце-концов – мы спокойно можем раз в месяц удалять весь Dev-кластер, и провиженить заново – дело 20 минут и одного клика в Jenkins, а для Stage/Prod деплоев будут использоваться только жёстко заданные неймспейсы, потому там такой проблемы не будет (но это не точно).
Окей, make sense.
Что дальше?
Дальше локально сделаем:
создадим чарт для приложения – используем реальное, но отбранчуемся, что бы не мешать девелоперам.
настроим kubectl на новый Dev-кластер
выполним helm install
Потом пойдём делать джобу в дженкисе.
Джоба будет клонировать репозиторий с приложением, и делать helm install в нужный namespace.
А релиз-версии нужны судя по всему только если мы будем заливать чарты в виде архивов в свой Helm-репозиторий – в самом Кубере они никак не применяются…
Значит – пока этот вопрос отложим, потом вернёмся к chart-releaser.
Поехали тестить?
Helm test deploy
kubectl config
У меня есть новый тестовый кластер bttrm-eks-dev-1 – создаём для него конфиг.
aws --profile arseniy eks update-kubeconfig --name bttrm-eks-dev-1 --alias arseniy@bttrm-eks-dev-1
Added new context arseniy@bttrm-eks-dev-1 to /home/setevoy/.kube/config
Создаём тестовый чарт:
cd /tmp/
helm create deployment-testing-chart
Creating deployment-testing-chart
Helm: the server has asked for the client to provide credentials
Пробуем залить в default namespace:
helm install deployment-testing-chart --dry-run deployment-testing-chart/
Error: Kubernetes cluster unreachable: the server has asked for the client to provide credentials
WTF?
Проверяем контекст:
kk config current-context
arseniy@bttrm-eks-dev-1
(kk – алиас для kubectl в ~/.bashrc: alias kk="kubectl")
Всё верно…
А доступ есть?
kk get pod
error: You must be logged in to the server (Unauthorized)
kk config delete-context arseniy@bttrm-eks-dev-1
warning: this removed your active context, use "kubectl config use-context" to select a different one
deleted context arseniy@bttrm-eks-dev-1 from /home/setevoy/.kube/config
helm install deployment-testing-chart deployment-testing-chart/ --namespace deployment-testing-chart-ns
Error: create: failed to create: namespaces "deployment-testing-chart-ns" not found
This is a known limitation of Helm. Helm will not do cross-namespace management, and we do not recommend setting namespace: directly in a template. If you want to install resources in a namespace other than the default namespace, helm install –namespace=foo will install the resources in that namespace. If the namespace does not exist, it will create it.
Эээ? Так мы ж так и делали…
Читаем ниже:
For Helm 3, the namespace creation doesn’t happen during helm install any more, so you’ll have to create that namespace ahead of time as you do today.
For Helm 3, the namespace creation doesn’t happen during helm install any more, so you’ll have to create that namespace ahead of time as you do today.Right now, use kubectl create namespace foo prior to helm install. When Helm 3.2.0 is released, use helm install … –create-namespace.
А у нас какая?
helm version
version.BuildInfo{Version:"v3.2.0", ...
kk get ns
NAME STATUS AGE
bttrm-apps-dev-1-ns Active 28h
bttrm-workouts-dev-1-ns Active 28h
default Active 28h
deployment-testing-chart-ns Active 19s
...
Няшка.
Сервисы:
kk -n deployment-testing-chart-ns get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deployment-testing-chart ClusterIP 172.20.227.114 <none> 80/TCP 2m1s
Окей, вроде работает – можно думать за Helm chart для самого приложения.
Хотя тут можно начать наоборот с Jenkins-джобы и скрипта, и использовать тестовый чарт, а потом создавать чарт реального приложения.
Но давайте сначала всё-таки приведём в рабочий вид приложение.
Helm – создание чарта
Сейчас у нас файлы для Kubernetes лежат в отдельном репозитории devops, а код приложения – в репозитории самого приложения.
Что надо сделать – это создать чарт в репозитории с приложением – в этом репозитории будет и Dockerfile, там же будем хранить Chart.yaml.
Скрипты для Jenkins (jekinsfiles) хранятся в ещё одном отдельном репозитории для общего доступа из различных, но однотипных джоб.
What about RBAC?
Кстати. Задумался я о том, как мы будем деплоить с Jenkins и о правах доступа.
Сам Jenkins использует свою EC2 Instance Profile, которая даёт ему полный доступ к кластерам. Ту же роль использую сейчас я при AssumeRole, которую мы настроили выше в ~/.aws/config.
А что с девелоперами?
У них-то создаются отдельные RoleBinding из определённых неймспейсов, в которые им разрешается доступ, а не глобальный рутовый доступ, как у меня.
Значит – эти RoleBinding надо включить в чарт, и создавать их в тех неймспейсах, которые будут создавать при деплое чарта из Jenkins в – напомню – том числе и кастомные неймспейсы.
Как быть? Делать RBAC сабчартом?
Вопрос… Да и для самого Helm, по-хорошему, надо создавать отдельный Kubernetes ServiceAccount при создании кластера.
Хотя – зачем нам выносить доступы юзеров в отдельный чарт или сабчарт?
Там всего-то создать одну RoleBinding в нужном неймпсейсе. А “глобальная” ClusterRole создаётся при провижене самого кластера из Ansible (потом надо будет переписать на Helm, и все RBAC-ресурсы через него деплоить).
Собственно, как говорилось в начале – все КАПСы вырезаются в Jenkins с помощью sed, и меняются на реальные значения, полученные из параметров джобы, а потом выполняется kubectl apply -f.
spec: replicas: DEPLOY_REPLICAS_NUM вот – тут уже пора в values.yaml идти, добавляем в нём replicaCount: 2 а в деплойменте используем replicas: {{ .Values.replicaCount }}, см. пример ниже
selector: matchLabels: app: bttrm-apps-EKS_ENV меняем на application: {{ .Chart.Name }}
Сначала думал в имя деплоймента включить .Chart.Version или .Chart.AppVersion – но тут у Хельма всё оказалось через… Печаль какую-то, т.к. задать их значения во время helm install нельзя – только во время package, см. https://github.com/helm/helm/issues/3555 (с 2018 обсуждают!).
Ладно – оставим на совести разработчиков – жираф большой, ему виднее. Пока в имени оставлю {{ .Chart.Name }} – по ходу дела посмотрим. Да и не факт, что использовать версии в имени хорошая идея.
Получится строка типа bttrm/bttrm-apps:TAG, а TAG думаю формировать при сборке образа из $BUILD_NUMBER + $GIT_COMMIT, т.е. получим что-то вроде bttrm/bttrm-apps:123.67554433.
Значения для плейсхолдеров типа CLIENT_HOST_VAL в основном будут задаваться из параметров джобы Дженкинса, но добавляем их в values тоже. Где можно – задаём дефолтные значения, где нет – просто “”.
Пока, кстати, вообще все значения можно задать в values – до Jenkins-джобы ещё будем тестить локально.
Кавычки
А что там с кавычками, кстати?
Тоже мрак)
С одной стороны – документация по созданию чарта (тыц>>>) и по переменным (тыц>>>) говорит использовать quote-функцию, которая будет “оборачивать” наши значения в кавычки.
При этом, если посмотреть файлы, сгенерированные при helm create – то там нет ни quote, ни кавычек – в большинстве случаев. Но не везде
YAML’s type coercion rules are sometimes counterintuitive. For example, foo: false is not the same as foo: “false”. Large integers like foo: 12345678 will get converted to scientific notation in some cases.The easiest way to avoid type conversion errors is to be explicit about strings, and implicit about everything else. Or, in short, quote all strings.
Мрак!
Ладно – в values.yaml стринги заключаем в кавычки, целочисленные – без кавычек.
В файле шаблонов… Я не знаю
Использовать quote – тогда само значение в переменных будет с кавычками. Посмотрел, как приложение запущено сейчас – без кавычек:
kk -n bttrm-apps-stage-ns describe pod bttrm-apps-stage-7c5cfd9698-tkmjp | grep CLIENT_HOST
CLIENT_HOST: https://test.example.com
Значит пока без quote, и без явного указания “” в шаблоне вообще.
helm install --debug bttrm-apps-backend-release bttrm-apps-backend
install.go:159: [debug] Original chart version: ""
install.go:176: [debug] CHART PATH: /home/setevoy/Work/landing-backend/k8s/bttrm-apps-backend
client.go:108: [debug] creating 6 resource(s)
Error: Deployment in version "v1" cannot be handled as a Deployment:
v1.Deployment.Spec: v1.DeploymentSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.Containers: []v1.Container: v1.Container.Env: []v1.EnvVar: v1.EnvVar.Value:
ReadString: expects " or n, but found 3, error found in #10 byte of ...|,"value":3001}
Ах ты ж…
Вот честно – я тут очень матерился.
Может я не догоняю чего-то, но ты же мне везде в документации говоришь, что Integer без кавычек кушаешь нормально?
Что ж ты теперь ругаешься на цифры?
Про то, как Go вообще ошибки выводит промолчим – в них часто сложно что-то понять.
Но тут в принципе видно значение, вызвавшее ошибку – 3001:
v1.PodSpec.Containers: []v1.Container: v1.Container.Env: []v1.EnvVar: v1.EnvVar.Value: ReadString: expects ” or n, but found 3, error found in #10 byte of …|,”value”:3001}
Непонятно, конечно, где именно – но так как порты в деплойменте встречаются не так часто – то просто добавляем кавычки для всех, меняем:
При этом в ports: - containerPort: на кавычки он ругается.
А в livenessProbe: port: при --dry-run не ругается. А при install – ругается.
Рукалицо. Ладно.
Деплоим ещё раз:
helm install --debug bttrm-apps-backend-release bttrm-apps-backend/
install.go:159: [debug] Original chart version: ""
install.go:176: [debug] CHART PATH: /home/setevoy/Work/landing-backend/k8s/bttrm-apps-backend
client.go:108: [debug] creating 6 resource(s)
NAME: bttrm-apps-backend-release
LAST DEPLOYED: Sun May 10 14:35:37 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
...
Йай!
Проверяем:
helm ls
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
bttrm-apps-backend-release default 1 2020-05-10 14:35:37.364401788 +0300 EEST deployed bttrm-apps-backend-0.1.0 1.16.0
Ну – бимба!
Оно 100% не работает, но нам важен сам файкт, что оно задеплоилось:
kk get pod
NAME READY STATUS RESTARTS AGE
bttrm-apps-backend-c4d8f8c5d-98vd2 1/1 Running 0 54s
bttrm-apps-backend-c4d8f8c5d-v6slt 1/1 Running 0 54s
...
helm install bttrm-apps-backend-release bttrm-apps-backend/ --namespace bttrm-apps-dev-1-ns --create-namespace
NAME: bttrm-apps-backend-release
LAST DEPLOYED: Sun May 10 14:45:23 2020
NAMESPACE: bttrm-apps-dev-1-ns
STATUS: deployed
REVISION: 1
TEST SUITE: None
Проверяем:
kk -n bttrm-apps-dev-1-ns get po
NAME READY STATUS RESTARTS AGE
bttrm-apps-backend-6c54d5c676-5j6mc 0/1 Pending 0 47s
bttrm-apps-backend-6c54d5c676-vchvh 0/1 Pending 0 47s
Супер, но почему Pending?
Что-то с реквестами, наверно?
Глянем events:
kk -n bttrm-apps-dev-1-ns get event
LAST SEEN TYPE REASON OBJECT MESSAGE
7s Warning FailedScheduling pod/bttrm-apps-backend-6c54d5c676-5j6mc 0/8 nodes are available: 8 Insufficient cpu.
10s Normal NotTriggerScaleUp pod/bttrm-apps-backend-6c54d5c676-5j6mc pod didn't trigger scale-up
(it wouldn't fit if a new node is added): 4 Insufficient cpu
А почему?
В values.yaml500 CPU requests, WorkerNodes у нас на ЕС2 t3.medium – у каждого 2000 CPU юнитов…
Проверим реквесты:
kk -n bttrm-apps-dev-1-ns describe pod bttrm-apps-backend-6c54d5c676-5j6mc
Name: bttrm-apps-backend-6c54d5c676-5j6mc
Namespace: bttrm-apps-dev-1-ns
...
Host Port: 0/TCP
Requests:
cpu: 500
...
helm upgrade bttrm-apps-backend-release bttrm-apps-backend/ --namespace bttrm-apps-dev-1-ns
Release "bttrm-apps-backend-release" has been upgraded. Happy Helming!
NAME: bttrm-apps-backend-release
LAST DEPLOYED: Sun May 10 14:54:57 2020
NAMESPACE: bttrm-apps-dev-1-ns
STATUS: deployed
REVISION: 2
TEST SUITE: None
Евенты:
kk -n bttrm-apps-dev-1-ns get event
LAST SEEN TYPE REASON OBJECT MESSAGE
47s Normal Scheduled pod/bttrm-apps-backend-69d74849df-nvtt2 Successfully assigned bttrm-apps-dev-1-ns/bttrm-apps-backend-69d74849df-nvtt2 to ip-10-3-33-123.us-east-2.compute.internal
15s Warning FailedMount pod/bttrm-apps-backend-69d74849df-nvtt2 MountVolume.SetUp failed for volume "apple-keys" : secret "apple-keys" not found
15s Warning FailedMount pod/bttrm-apps-backend-69d74849df-nvtt2 MountVolume.SetUp failed for volume "apple-certificates" : secret "apple-certificates" not found
47s Normal SuccessfulCreate replicaset/bttrm-apps-backend-69d74849df Created pod: bttrm-apps-backend-69d74849df-nvtt2
...
Ага!
Всё создалось.
Теперь поды не стартуют, потому что не файлов сертификатов для Apple – но это уже детали, сейчас их создадим.
Helm secrets from files
Добавим файлы сертификата – в Jenkins они будут маунтиться из Credentials типа Secret file, тут добавляем в текущий репозиторий:
ll bttrm-apps-be/secrets/
total 12
-rw-r--r-- 1 setevoy setevoy 258 May 10 17:32 AppleAuth.key.p8
-rw-r--r-- 1 setevoy setevoy 3088 May 10 17:27 ApplePay.crt.pem
-rw-r--r-- 1 setevoy setevoy 2006 May 10 17:28 ApplePay.key.pem
Добавляем в ../.gitignore репозитория и в .helmignore чарта:
helm upgrade bttrm-apps-be-release bttrm-apps-be/ --namespace bttrm-apps-dev-1-ns
Release "bttrm-apps-be-release" has been upgraded. Happy Helming!
NAME: bttrm-apps-be-release
LAST DEPLOYED: Sun May 10 17:36:47 2020
NAMESPACE: bttrm-apps-dev-1-ns
STATUS: deployed
REVISION: 4
TEST SUITE: None
Проверяем секреты:
kk -n bttrm-apps-dev-1-ns get secret
NAME TYPE DATA AGE
apple-certificates Opaque 2 37s
apple-key Opaque 1 37s
Но поды серты не увидели, и не запустилиись, так и будут висеть в FailedMount.
Пересоздаём их – вызываем upgrade с --recreate-pods:
helm upgrade bttrm-apps-be-release bttrm-apps-be/ --namespace bttrm-apps-dev-1-ns --recreate-pods
Flag --recreate-pods has been deprecated, functionality will no longer be updated. Consult the documentation for other methods to recreate pods
Release "bttrm-apps-be-release" has been upgraded. Happy Helming!
NAME: bttrm-apps-be-release
LAST DEPLOYED: Sun May 10 17:39:39 2020
NAMESPACE: bttrm-apps-dev-1-ns
STATUS: deployed
REVISION: 5
TEST SUITE: None
Проверяем:
helm -n bttrm-apps-dev-1-ns ls
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
bttrm-apps-be-release bttrm-apps-dev-1-ns 2 2020-05-10 17:44:56.505478002 +0300 EEST deployed bttrm-apps-be-0.1.0 1.16.0
kk -n bttrm-apps-dev-1-ns get pod
NAME READY STATUS RESTARTS AGE
bttrm-apps-be-dp-6f86d5c7d7-k4rjm 1/1 Running 0 2m
bttrm-apps-be-dp-6f86d5c7d7-ztcvp 1/1 Running 0 83s
Тут готово.
.dockerconfigjson
Сейчас в секретах файла bttrm-apps-secrets.yaml значение для .dockerconfigjson задан хардкодом:
неймспейс с именем бранча – APP_NAME + CLUSTER_ENV + GIT_BRANCH_NAME + “NS”, т.е. bttrm-apps-dev-1-WLIOS-5848-Projects-deployments
кастомный неймспейс, задаётся юзером
Есть сомнения по второму пункту – bttrm-apps-dev-1-WLIOS-5848-Projects-deployments – не слишком ли длинно?
Загуглим “kubernetes namespace best practices”, но лучшее, что нашлось – это вот эта запись в блоге, в которой говорится:
An easy to grasp anti-pattern for Kubernetes namespaces is versioning. You should not use Namespaces as a way to disambiguate versions of your Kubernetes resources
Namespace names are DNS1123 Labels: maximum 63 characters … You may want to populate generateName with a prefix, and let kubernetes make a unique suffix.
Хорошо – раз лимит в 63 символа – мы можем в дженкисфайле добавить хендлер, который будет проверять имя неймспейса, переданного из Jenkins-парамтеров, и при необходимости обрезать его.
Весь билд будет выполняться нашим кастомным Docker-образом kubectl-aws, собирается из такого Dockerfile:
FROM bitnami/minideb:stretch
RUN apt update && install_packages ca-certificates wget
RUN install_packages curl python-pip python-setuptools jq git
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
RUN chmod +x ./kubectl
RUN mv ./kubectl /usr/local/bin/kubectl
WORKDIR /tmp
RUN curl --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
RUN mv /tmp/eksctl /usr/local/bin
RUN pip install ansible boto3 awscli
WORKDIR /tmp
RUN curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
RUN /bin/bash get_helm.sh
USER root
Пока все значения тпиа Github URL и имени бранча в скрипте билда хардкодим – потом вынесем в параметры джобы.
Запускаем, проверяем – всё работает.
Пошли дальше.
Docker build
Далее нам надо собрать Docker-образ, и запушить его в репозиторий.
Добавлять ли тег latest? Вопрос.
Наверно нет – билдов может быть много, из разных бранчей – перезаписывать каждый раз latest смысла нет, тем более деплоится в Dev окружение всё будет автоматом при создании пул-реквестов, см. Jenkins: Github Pull-Request Builder плагин.
Значит – делаем только docker build с тегом из переменной $DOCKER_TAG.
Создаём данные доступа для DockerHub:
Добавляем новый стейдж “Docker build”, в нём с помощью Docker-плагина для Jenkins собираем образ, для логина в DockerHub через credentialsId передаём созданные выше данные:
Дальше генерируем пакет. Пока надо только для того, что бы можно было задать release verion и app-version. Позже хочется добавить их пуш куда-то в репозиторий – или Github, или S3-backended.
добавить создание неймспейса по имени бранча и кастомный НС
проверка длины неймспейсов
Но пока, думаю, хватит.
helm upgrade – resource cannot be imported into the current release
P.S. Когда добавлял RBAC-роль – то при апдейте получил ошибку:
helm upgrade --install --namespace bttrm-apps-dev-1-ns --create-namespace --atomic bttrm-apps-backend bttrm-apps-backend-17.tgz
Error: UPGRADE FAILED: rendered manifests contain a resource that already exists. Unable to continue with update:
RoleBinding "rbac-bttrm-web-apps-ro-role-binding" in namespace "bttrm-apps-dev-1-ns" exists and cannot be imported into the current release:
invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by":
must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "bttrm-apps-backend";
annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "bttrm-apps-dev-1-ns"
Собственно, это к тому, что Helm задаёт аннотации и лейблы сам – но есть смысл добавлять их в шаблоны манифестов:
В этой статье мы рассмотрим, как защищать роутер MikroTik от атак и сканеров портов, а также предотвратим попадание нашей сети в бан-листы. Полученный опыт поможет тебе настраивать и другие виды файрволов.
Если у тебя большая сеть с несколькими филиалами и в каждом из них по два роутера для отказоустойчивости, то правила лучше настроить так, чтобы их можно было легко развернуть на любой железке, независимо от количества и именования портов или типа подключения. Для соединения по PPPoE, например, WAN-интерфейсом будет pppoe-out1, а для DHCP — ether1. Если попытаться экспортировать конфиг файрвола с одного роутера на другой, ничего не выйдет, потому что у второго просто нет интерфейса pppoe-out1. Или представь себе, что в одном филиале локальная сеть висит на ether9, а в другом стоит роутер с пятью портами, из-за чего конфигурация девятого порта просто не встанет и вылетит с ошибкой.
Поэтому мы будем настраивать роутер так, чтобы конфиг можно было без проблем перенести на любой другой роутер. Это немного усложнит первоначальную настройку, но сэкономит кучу времени в будущем.
Мы уже рассматривали списки интерфейсов. Это фича для оперирования несколькими интерфейсами как одним. Создадим листы WAN и LAN, а затем добавим туда нужные интерфейсы. Теперь правила файрвола будем привязывать к интерфейс-листам, а не к отдельным интерфейсам. Перед экспортом правил на другой роутер просто создадим на нем нужные листы, и конфиг встанет без ошибок.
Interface List
Обрати внимание, что для использования в файрволе нам нужны L3-интерфейсы, то есть те, на которых есть IP-адреса. Если ты получаешь интернет по PPPoE, то в WAN-лист надо добавить именно его. Если IP локальной сети прописан на бридже или VLAN’е, то и в лист LAN нужно добавить их, а не физические интерфейсы. Если включить в список и логический, и физический интерфейс, ничего страшного произойти не должно, но это нужно будет учитывать в конфигурации.
Но это еще не все. Понятно, что в каждом филиале у нас будет своя подсеть LAN: где-то 192.168.10.0/24, где-то 192.168.11.0/24. Чтобы не путаться с этими значениями и не менять конфиг при переносе с одного роутера на другой, оперировать будем не адресами и подсетями, а списками адресов. На каждом роутере создаем список LAN и дальше работаем только с ним.
В прошлый раз мы создавали адрес-лист MGMT, в котором открывали доступ к управлению роутером только с определенных адресов. А еще раньше рассматривали решение Port Knocking, которое предоставляет доступ к управлению, только если со стороны клиента выполнить секретные манипуляции. Для доступа к роутеру из доверенной сети (LAN) вполне подходит вариант с адрес-листом, а для доступа снаружи — Port Knocking. Было бы хорошо совместить эти варианты в нашей конфигурации. Еще будет удобно разделить цепочку input на две части: input со стороны интернета и input со стороны локалки. Тогда можно применять разные политики фильтрации к разным сегментам сети. В этом нам помогут пользовательские цепочки.
Все, что пришло снаружи, перекидываем в новую цепочку WAN_INPUT. Все, что изнутри, — в LAN_INPUT:
Теперь политики фильтрации будут разными для разного источника трафика. Для внешнего трафика будем использовать цепочку WAN_INPUT и более жесткие ограничения, для внутреннего — LAN_INPUT и правила попроще. Цепочка input нам больше не нужна, теперь мы все будем делать в новых цепочках. Причем указывать интерфейсы или списки интерфейсов в правилах больше не понадобится. Однако этот подход может использоваться в сложных решениях, например когда у тебя два провайдера с разными политиками фильтрации или локалка поделена на разные VLAN. Но об этом позже.
В статье о безопасной настройке роутера мы настраивали Port Knocking для доступа к управлению роутером. Ограничивать таким образом доступ изнутри локальной сети — излишество. Поэтому поменяем в правилах цепочку с input на WAN_INPUT. Изнутри сети разрешим доступ к WinBox только с нужных адресов: мы уже делали это в статье про основы файрвола. Оставим в правиле только порт WinBox — TCP 8291. А для SSH разрешим подключения из всей нашей сети, но предотвратим возможность брутфорса (да, изнутри сети тоже может произойти брутфорс SSH, потому что отсутствие троянов в ней не гарантировано).
Тут применяется механизм динамических адрес-листов с тайм-аутами. Мы рассматривали их в статье «Защищаем MikroTik. Хитрости безопасной настройки роутера». При первой попытке подключения пакет обработается правилом 5, и адрес хакера попадет в адрес-лист ssh_stage1. Вторая попытка подключения обработается правилом 4 и добавит брутфорсера в лист ssh_stage2. И так далее вплоть до листа ssh_blacklist, где адрес будет храниться десять дней, а весь трафик, идущий с адресов из этого списка, будет дропаться.
В прошлой статье мы создавали правила, разрешающие коннекты established, related и запрещающие invalid. Давай продублируем эти правила и перенесем их в новые цепочки, а из input удалим. В результате мы получим четыре правила вместо двух. На прохождение трафика это не повлияет, зато позволит видеть статистику по трафику с разных сторон. В правиле с established, related поставь галочку untracked. Чуть позже объясню, зачем она. Думаю, адаптировать остальные правила под новую логику не составит труда. В конце каждой цепочки не забудь указать правило дропа.
Должно получиться примерно так
Две цепочки позволят нам уменьшить количество переходов трафика по правилам, а значит, и немного снизить нагрузку на CPU. Счетчики в разных цепочках дадут возможность увидеть чуть более детальную статистику трафика. Хоть правил и стало больше, но они не применяются ко всему объему трафика: при первом джампе весь трафик будет обрабатываться уже новой цепочкой и в другую никогда не попадет. Подобный подход также упрощает поддержку за счет того, что по названию цепочки сразу видно, что это за трафик и откуда он идет. Можно для разных типов трафика создавать свои цепочки, например отдельную цепочку для management-трафика. За возврат трафика в родительскую цепочку отвечает action return.
Защищаемся от атак
До сих пор мы рассматривали правила файрвола, позволяющие обрабатывать трафик по простым признакам: интерфейсу, адресу, порту. Но файрвол гораздо более гибкий инструмент, с его помощью можно строить сложную логику для противодействия разным типам атак.
Есть зарезервированные адреса, которые не используются в интернете. Они называются «богон-адресами». Отсечем пакеты с таких адресов:
Мы ожидаем пакеты только с юникаст-адресов, поэтому запретим все, кроме них.
Drop non unicast
Port Scan Detect — функция, позволяющая обнаружить сканер портов. Как она работает? Портам задается некий условный вес — Weight. Причем для системных портов (до 1024-го) весовой коэффициент низкий (Low ports), а для остальных — высокий (High ports). Если в течение времени Delay Threshold от одного хоста на роутер прилетят пакеты на порты, сумма весов которых окажется больше, чем Weight Threshold, то адрес отправителя будет добавлен в блек-лист. В нашем примере, если с одного хоста за три секунды поступят десять пакетов на порты до 1024-го (общий вес 10 * 2 = 20) и двадцать пакетов на порты выше 1024-го (20 * 1 = 20), общий их вес составит 40. Обрати внимание, что Port Scan Detect работает только для TCP- или UDP-трафика.
Защищаемся от сканеров
Один из самых распространенных видов атак — это атака на отказ в обслуживании, или DDoS. Защититься от нее своими силами практически нереально. Но с помощью простого правила можно отсечь самые простые попытки атаки. Находим хост, который насоздавал к нам больше 100 сессий, и добавляем его в блек-лист. В этом правиле обязательно нужно использовать параметр connection-state=new. Но мы ведь уже разрешили все established, related и untracked, а invalid дропнули, поэтому сюда дойдут только пакеты new. Оставлять или нет этот флажок в правиле — твое дело. Отмечу, что с помощью этой же фичи можно выявлять в своей сети торрентокачальщиков.
Защищаемся от DDoS
ICMP — один из важных протоколов в любой сети. Многие админы любят блокировать его, но это очень плохой подход. Именно ICMP позволяет работать трассировке, указывать на недоступность UDP-портов, отправлять разные служебные сообщения. И если запретить его полностью, можно наловить кучу багов. У каждого сообщения ICMP свое предназначение, и уже по этому параметру нетрудно понять, имеет ли смысл разрешить какие-то типы ICMP изнутри сети или снаружи. Например:
ICMP Echo Request — наш любимый пинг, имеет тип 8, код 0;
ICMP Echo Reply — ответ на пинг, тип 0, код 0;
Destination Unreachable — узел недоступен, тип 3 и коды 0–15 в зависимости от причины недоступности:0 — сеть недоступна;
1 — хост недоступен;
2 — протокол недоступен;
3 — порт недоступен;
4 — необходима фрагментация пакета, но она запрещена (стоит флаг DF — Don’t Fragment).
Остальное легко найти в интернете, а лучше почитать RFC 792.
Создадим цепочку ICMP и отправим в нее весь ICMP-трафик (можно создать две цепочки: для LAN и WAN — и настроить разные политики). Разрешаем только нужные типы сообщений и ограничиваем обработку пятью пакетами в секунду:
TCP тоже поддерживает кучу флагов, часть которых не может содержаться в одном пакете. Комбинации этих флагов часто используются сканерами портов, чтобы пробить плохо настроенную защиту. Сделаем отдельную цепочку для TCP и дропнем подобные «подозрительные» пакеты:
До сих пор мы в основном смотрели на трафик, прилетевший в input-цепочку, а дальше по каким-то признакам направляли его в разные цепочки. Но весь этот трафик предназначался самому роутеру. Цепочку output используют редко, но ты можешь отфильтровать в ней, например, ICMP-ответы от роутера или IPsec-трафик. Понятно, что большая часть трафика будет попадать в forward — ведь на то он и роутер, чтобы перенаправлять пакеты из одной сети (локалка) в другую (интернет или второй VLAN локалки). И в этой цепочке мы будем управлять трафиком пользователей.
Я не стану детально рассказывать о том, что надо разрешить или запретить, — об основных приемах настройки и так уже написано несколько статей и есть куча примеров в интернете. Рассмотрим более интересный кейс: репутацию сети.
В интернете есть сервисы, содержащие списки спамеров, ддосеров, распространителей нелегального контента. Если на машины в твоей сети попал троян-спамер, то ты тоже окажешься в этих списках. Через какое-то время письма от любого клиента изнутри сети начнут попадать в спам у всех получателей, потом ты будешь добавлен в публичные блек-листы и у пользователей исчезнет доступ ко многим ресурсам. В том числе к сетям партнеров, админы которых пользуются такими списками, чтобы запретить доступ потенциальным вредителям. Представь, что произойдет с твоей премией, когда письмо с многомиллионным контрактом от твоего шефа упадет у контрагента в папку «Спам».
Попробуем защитить свою премию. Для этого нужно понять, по какому поводу нас могут внести в списки. Причин этому несколько:
мы часть DoS- или иного ботнета;
мы рассылаем спам;
с наших адресов брутфорсят чужие сервисы;
мы нарушаем авторские права (раздаем торренты).
Некоторые читатели этой статьи вполне могли участвовать в DDoS-ботнете, сами того не осознавая. Атаки UDP Amplification основаны на некорректных настройках сервисов, когда можно обратиться к ним с просьбой узнать что-то у другого сервера. Например, к нам может прилететь DNS-запрос с просьбой отрезолвить адрес жертвы. И таких, как мы, миллионы. Когда к жертве поступит миллион пакетов в секунду, она не обрадуется, а мы увидим загрузку CPU под 100%, жуткие тормоза и однажды окажемся в блек-листе. Такая же схема работает и с другими UDP-сервисами, например NTP. Вывод простой: блокируй трафик к этим сервисам снаружи. Но это все еще про INPUT.
Не только роутер может быть частью такого ботнета, но и машины внутри сети. Для детекта таких хостов воспользуемся уже известной фичей connection limit.
По порту назначения можно определить, к какому сервису обращаются хосты изнутри нашей сети. И если это общеизвестный порт, например СУБД, а все наши базы расположены внутри периметра, логично предположить, что сотни пакетов в секунду к этому порту в интернете с компьютера бухгалтера — не простая ошибка и не личный интерес самого бухгалтера. Дропаем подозрительные пакеты и возвращаемся в родительскую цепочку (последнее правило):
Мы рассмотрели более продвинутые методы настройки файрвола. Эту статью не нужно воспринимать как инструкцию по настройке: у каждой сети свои особенности и сервисы. Роутеры у всех тоже разные — у кого-то он спокойно обработает тысячи неоптимизированных правил файрвола, для других сотня правил будет обрабатываться с трудом. Поэтому подходи к настройке файрвола с умом.
В две статьи всё не вместишь, и мы не затронули еще несколько больших тем: таблицы NAT, RAW, IPv6 Firewall, Bridge Firewall, фильтрацию по контенту, определение типа трафика по его содержимому (когда мы меняем порт у HTTP, а файрвол все равно понимает, что внутри HTTP), проксирование трафика.
Все эти темы рассматриваются в официальном обучающем курсе MikroTik — MikroTik Certified Traffic Control Engineer. Но чтобы на него попасть, нужно пройти курс MikroTik Certified Network Associate, где изучаются общие принципы настройки роутера и работа TCP/IP.