<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>Логово (а)социальной твари</title>
	<atom:link href="https://nixman.info/?feed=rss2" rel="self" type="application/rss+xml"/>
	<link>https://nixman.info/</link>
	<description>Конспекты вечного студента</description>
	<lastBuildDate>Sun, 30 Jan 2022 22:47:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Закупки как сервис</title>
		<link>https://nixman.info/?p=5867</link>
					<comments>https://nixman.info/?p=5867#respond</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Sun, 30 Jan 2022 22:47:37 +0000</pubDate>
				<category><![CDATA[FinOPS]]></category>
		<category><![CDATA[finops]]></category>
		<category><![CDATA[supplier relations]]></category>
		<guid isPermaLink="false">https://nixman.info/?p=5867</guid>

					<description><![CDATA[<p>Всем привет! Меня зовут Алексей, и я работаю  в компании ecommpay IT. Мы пишем и эксплуатируем ПО для эквайринга и процессинга карточных платежей. Если совсем по-простому &#8211; мы делаем так, чтобы оплачивать товары в Интернете было удобно, быстро и безопасно. Я было хотел написать, что в компании я решаю проблемы, как Мистер Вульф из известного&#8230;</p>
<p>The post <a href="https://nixman.info/?p=5867">Закупки как сервис</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Всем привет!</p>
<p>Меня зовут Алексей, и я работаю  в компании ecommpay IT. Мы пишем и эксплуатируем ПО для эквайринга и процессинга карточных платежей. Если совсем по-простому &#8211; мы делаем так, чтобы оплачивать товары в Интернете было удобно, быстро и безопасно.</p>
<p>Я было хотел написать, что в компании я решаю проблемы, как Мистер Вульф из известного фильма, но вовремя вспомнил недавнюю статью и подкаст Василия Пантюхина, и решил, что надо быть скромнее.</p>
<p>Пусть это будет <del datetime="2022-01-30T22:23:57+00:00">Максми Поташёв</del> Александр Друзь.<br />
<img decoding="async" src="https://habrastorage.org/getpro/habr/upload_files/db0/977/c86/db0977c8610d949cc9de2a39249c320a.png" alt="" /></p>
<p>Почему? потому что чаще всего я по работе отвечаю на три простых вопроса:</p>
<p><strong>Что</strong> из оборудования или софта было заказано в текущему/прошлом месяце/квартале? Что ещё можно/нужно заказать в этом квартале, чтобы уложиться в бюджет?<br />
<strong>Где</strong> деньги сейчас находится заказанное оборудование? А что есть на складе?<br />
<strong>Когда</strong> приедет/будет оплачено то, что заказали?</p>
<p>Кому-то может показаться, что это абсолютно скучная бумажная работа, и инженерам тут делать нечего, но это будет только долей правды <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<blockquote><p>disclaimer: &#8220;В нашей жизни не всё, всегда и везде, а кое-что, иногда и местами&#8221; (с) Максим Дорофеев.<br />
Всё ниженаписанное можно и нужно считать личным мнением автора, не претендующим на истину в последней инстанции, и даже на полноценное исследование. Все персонажи вымышленны, все совпадения случайны.</p></blockquote>
<h1>Кто обычно занимается закупками техники и софта, и какие с этим есть проблемы</h1>
<p>В не-ИТ компаниях обычно это офисный сисадмин (ну или начальник ИТ-отдела, если таковой вообще есть).</p>
<p>С ИТ-компаниями всё сложнее. Я видел как варианты &#8220;офисного сисадмина на максималках&#8221;, когда человек покупал в т.ч. и железо для ДЦ, и софт, и ноутбуки для сотрудников. Если компания большая, то в ней может быть целый отдел, который занимается закупками (причём всего &#8211; от скрепок до СХД). В маленьких компаниях со множеством команд &#8220;живущих по эджайлу&#8221;, вообще у каждой может быть свой бюджет и своя карта для оплаты (и хорошо, если это карта корпоративная, а не личная).</p>
<p>Ну и разумеется, не последнюю роль в закупках играет ИТ-директор, который отвечает за немаленький, обычно, бюджет, а значит, должен следить за наиболее важными/крупными затратами лично.</p>
<blockquote><p>Я встречал ситуацию, когда каждый сисадмин в компании мог практически без апрува заказывать серверы для своей команды через письмо в sales-отдел хостинга. Помимо кучи железа, которое не пойми для чего было заказано, и как использовалось, довольно часто возникала ситуация, когда сервер выдали, а кто, когда и зачем его заказал &#8211; непонятно. Или сервер выдали &#8211; и его тут же по ошибке или намеренно &#8220;подрезали&#8221; более расторопные коллеги. Отдельно стоит отметить чатик в скайпе на 20+ человек, в котором сидели представители хостинга и все сисадмины, и где одним из самых частых вопросов было &#8220;а кто заказывал сервер по тикету xxxxx?&#8221;</p></blockquote>
<p>Но кто бы это ни был, частенько бывает так, что управление расходами на ИТ-инфраструктуру превращается в кошмар:</p>
<ul>
<li>у офисного сисадмина часто не хватает квалификации и времени (потому что обычных офисных задач с него никто не снимал);</li>
<li>у директора ИТ (CIO/CTO/CITO, подставить нужное) и так дел невпроворот, в итоге задачи либо &#8220;падают на пол&#8221;, либо рандомно скидываются кому-то из его подчинённых, (обычно, когда все сроки уже прошли), либо просто сжирают и без того конечное рабочее время и силы;</li>
<li>у отдела закупок своё (отличное от ИТ) начальство, свои KPI и свой взгляд на то, как должен быть организован процесс. В идеальном мире сотрудники этого отдела имеют некоторое представление о том, что они покупают, и плотно общаются с командами-заказчиками, но так происходит не всегда. Да и выделенный отдел &#8211; это, банально, дорого;</li>
<li>если оплатой занимаются тимлиды команд или отдельные инициативные сотрудники, то отслеживание этого &#8211; мрак, ужас, и много-много новопассита для бухгалтерии. <del datetime="2022-01-30T22:23:57+00:00">Левые</del> личные карты, учётки на личные почты на гмыле, потеря информации при увольнениях/переходах и т.д. и т.п. Поиск концов каждый раз превращается в увлекательный квест.</li>
</ul>
<p>Почему так происходит? Айтишники не очень хотят возиться с бумажками, счетами и отчётностью, да и вообще не очень любят общаться с менеджерами. У них (как правило) есть резон побыстрее включить нужный сервис, протестировать, и, если всё ок &#8211; запустить в продакшен. Меньше всего им хочется отвечать на письма и звонки от продаванов и обсуждать детали договора с бухгалтерией и юристами.</p>
<p>Процесс управления работой с поставщиками называется на Западе Supplier relationships management, а если по-модному &#8211; FinOPS. Когда я только начинал этим заниматься года три с половиной назад, ни про каких FinOPS я не знал, поэтому для названия команды выбрал именно Supplier relations. В англоязычных статьях упирают на то, что FinOPS оптимизируют только облачные расходы (читай: умеют пользоваться Cost calculator), но для простоты здесь я буду считать, что это одно и то же.</p>
<h1>Кто такие FinOPS</h1>
<p>Supplier relations managers, (или FinOPS) &#8211; это люди, которые не только занимаются закупками IT-сервисов, лицензий и оборудования, но и налаживают связь между заказчиком (т.е. компанией, где они работают) и внешними поставщиками. Чтобы не было, как на известной картинке:<br />
<img decoding="async" src="https://habrastorage.org/getpro/habr/upload_files/7aa/892/a6a/7aa892a6ab5c3df95bf8e2d6993524b9.png" alt="" /></p>
<p>Собственно, сам процесс закупки &#8211; это только один из этапов довольно длинной цепочки.</p>
<p>Ещё раньше, даже до поиска подходящего поставщика, нужно заняться переводом хотелок заказчика (бизнеса или команды) в нечто измеримое: ядра, гигабайты, стойки, киловатты и т.д. И хорошо если заказчиком является свой родной ИТ-отдел, (хотя и тут бывает не всё радужно).</p>
<blockquote><p>Например, задача найти &#8220;хостинг в Бразилии&#8221; может на самом деле означать как то, что нужно проработать вариант организации полноценного PoP с размещением оборудования и подключением провайдеров, так и то, что для тестовых целей нужно поднять пару виртуалок в AWS в соответствующем регионе. Причём, реальные требования могут меняться в процессе жизни всего проекта в обе стороны.</p></blockquote>
<p>Следующим шагом является поиск подходящего поставщика (в гугле на рынке или через знакомых). При этом у каждого из них свои условия оплаты и гарантии (часто с привлечением партнёров), свои нюансы вроде SLA со звёздочкой и примечанием мелким шрифтом на пятьдесят последней странице договора, и ещё десяток различных мелочей, часть из которых проходит по разряду &#8220;так исторически сложилось&#8221; и ни в каких документах не отражается. И чем понятнее (на языке поставщика!) будет сформулирован запрос, тем меньше отличий будет между ожиданием и реальностью. (и это происходит, в хорошем сценарии, ещё до подписания договора, на этапе предварительного знакомства). Ну и опять же, в каждом крупном заказе есть множество различных нюансов: например, одни провайдеры делают резервирование VPN-каналов по-умолчанию, другие хотят за это дополнительных денег. Одни готовы подписаться на SLA по latency, другие нет. Какой-нибудь Trusted Platform Module или дополнительная сетевая карта, как опция при заказе сервера, не стоят, практически, ничего, но если покупать их у того же поставщика отдельно, то влетят в копеечку &#8211; и таких нюансов просто море.</p>
<p><img decoding="async" src="https://habrastorage.org/getpro/habr/upload_files/e8c/9c1/9da/e8c9c19da83cba5a8636e86697360391.png" alt="" /></p>
<p>Далее следует самый скучный этап: подписание договора, заказ, оплата и прочая бумажная волокита. Дело, вроде бы, простое, однако же иногда приходится побегать, то согласовывая правки в договоре, то объясняя, что и зачем мы всё-таки хотим купить (ниже я расскажу, какие нюансы встречаются при оформлении).</p>
<p>Ну и наконец после получения железки или лицензии есть &#8220;послепродажное обслуживание&#8221;, с которым тоже далеко не всегда всё бывает гладко, и приходится помогать коллегам решать различные вопросы, в т.ч. и самому общаться с техподдержкой (и её начальством), координировать возвраты по RMA и т.д.</p>
<blockquote><p>Одна компания пользовалась весьма крупным публичным облаком для тестовых сред. Облако достаточно дешёвое, но его стабильность даже для этих целей оставляла желать, к тому же саппорт отвечал не то, чтобы быстро, а уж про решение проблем я вообще молчу. На звонке с аккаунт-менеджером тот заверил, что это неприемлемо, и он примет все меры… После чего исчез. Натурально, перестал отвечать на письма, а его личного номера у нас не было. Как вы думаете, что сделали FinOPS в этой ситуации?</p></blockquote>
<p>С одной стороны, это куча бумажек, писем, звонков и новых знакомств практически ежедневно. Ты общаешься с партнёрами, юристами, бухглатерией и &#8220;внутренними заказчиками&#8221; по совершенно разным вопросам, начиная от причины появления НДС/VAT в очередном инвойсе и заканчивая порядком расположения плат расширения в сервере в зависимости от выбранной в конфигураторе опции razer extender. Нужно следить за рынком, новыми версиями железа и софта, новостями, которые могут повлиять на стратегию закупок (например, недавние остановки фабрик в Техасе могут привести к дефициту и увеличению сроков отгрузки, так что лучше какие-то позиции купить заранее). Не менее важно давать поставщикам обратную связь &#8211; не только по нынешним/прошедшим заказам, но и делиться планами на квартал/год.</p>
<blockquote><p>Как-то мы ждали оборудование от одного очень важного партнёра для размещения в нашей стойке. Партнёр &#8211; очень крупная международная компания, поэтому для доставки нанял специального подрядчика, который уже общался с логистами и нами, как получателями груза. Примерно за день до предполагаемой даты доставки мне звонит представитель подрядчика и просит не принимать груз, потому что это оборудование отправили к нам по ошибке, а &#8220;правильное&#8221; отправят в другой день. Этот же партнёр отличился, заказав в датацентре кроссировку в нашу стойку без LoA (letter of authorization), т.е. без разрешения с нашей стороны. А т.к. кроссировку прокладывал ещё один подрядчик, то о том, что к нам собираются завести кабель, я узнал только от нашего аккаунт-менеджера, который запросил разрешение на доступ в нашу стойку инженеров ДЦ.</p></blockquote>
<p>В подавляющем большинстве случаев, задачей любого поставщика (не важно, продукта или сервиса) является доставка пользователю счастья. В случае b2b счастье (оно же value) обычно выражается в удовлетворении некой потребности (как бы банально это ни звучало). Но проблема заключается в том, что далеко не всегда заказчик может сформулировать, а что же он, собственно, хочет. И тут FinOPS выступает в роли &#8220;переводчика&#8221;, причём в обе стороны. С одной стороны, он объясняет поставщикам в технических терминах (и со специфическими для поставщика деталями), что же именно хочет получить бизнес. Да, в идеальном мире это делает &#8220;админ или тимлид из ИТ отдела&#8221;, но… см выше про интровертную сущность инженеров и недостаток времени у руководителей.</p>
<p>С другой стороны, нужно перевести бравурные презентации пресейлов на технический язык, продраться сквозь бумажки (а вы знали, что английский канцелярит ничуть не лучше русского?), добавить известными &#8220;мелочами&#8221;, которые не пишутся в оферте, и внятно объяснить своим, что же именно нам хотят продать, но уже на понятном внутри языке.</p>
<p>С облаками всё ещё печальнее &#8211; счета и ценообразование, порой, настолько непонятные, что приходится пользоваться сторонними ресурсами для расшифровки месячных счетов, или привлекать специально обученных людей, которые помогают максимально эффективно и предсказуемо использовать ресурсы. Вот тут и могут пригодиться &#8220;свои&#8221; FinOPS-инженеры, которые разбираются не только в ценообразовании того или иного провайдера, но и, благодаря технической экспертизе и знанием внутренней кухни, могут сами оценить адекватность использования тех или иных сервисов.</p>
<p>Другой неочевидный момент &#8211; это экономия времени. Если у FinOPS есть крепкий технический бэкграунд, то многие вещи он может разруливать сам, не отвлекая коллег или руководителей. Составление оптимальных спек (учитывая особенности вендора или партнёра), общение с пресейлами и саппортом &#8211; зачастую, всё это гораздо удобнее решать именно им, т.к. именно у FinOPS есть под рукой и контекст задачи, и нужные контакты, и возможность ускорить решение вопроса за счёт личных знакомств.</p>
<blockquote><p>Полезно периодически тестировать разных поставщиков одного и того же железа. В сравнении узнаёшь, кто как работает с налогами и логистикой, у кого какие скидки у вендора и т.д. Из курьёзных случаев &#8211; как-то один наш давний партнёр предложил нам партию серверов по выгодной цене, хотя раньше именно это оборудование мы у него не покупали. Серверы оказались &#8220;почти такие же&#8221;, но в несколько штук не доставили сетевые и диски, плюс немного напортачили с гарантией.</p>
<p>Ещё был совершенно классический случай, когда две услуги от разных провайдеров &#8220;мамойклянус, независимые!&#8221; оказались в одном кабеле. Было неприятно.</p></blockquote>
<h1>С кем взаимодействуют FinOPS по работе</h1>
<p>В больших (и очень больших) компаниях отдел закупок может быть централизованным. Но это немного не наш сценарий. Впрочем даже в этом случае FinOPS найдёт своё место либо в рамках этого отдела, либо…</p>
<p>Разумно выделять SR team (или FinOPS team) в рамках ИТ-отдела. Почему? потому что часто это основная точка расходов компании. Закупка железа, лицензий, сервисов &#8211; очень быстро расходы на ИТ становятся заметными (и очень заметными) для собственников, и ИТ-директору нужно очень хорошо и чётко не только объяснять, сколько и куда уже потратили, но и делать прогнозы (или составлять бюджет и его исполнять) на квартал, а то и год вперёд. Сюда же относятся управление лицензиями и общение с сервис-провайдерами &#8211; всё это забота ИТ, и FinOPS, как его части.</p>
<blockquote><p>Одна из обычных историй &#8211; в пять часов вечера пятницы к тебе приходит представитель поставщика, и говорит, что хорошо бы оплатить вот этот инвойс до конца дня, а то резерв превратится в тыкву, и отгрузка пройдёт неизвестно когда. Далее начинается квест &#8220;подтверди закупку, найди бухгалтера и дождись платёжки&#8221; длиною в час. Платёжка была отправлена в 17:58, заказ был спасён.</p></blockquote>
<p>Команда SR (FinOPS) может успешно работать (и работает) в связке с Ops и инфраструктурными командами (которые непосредственно занимаются эксплуатацией датацентров, сетевого и серверного железа), привлекая их экспертизу и помогая общаться с вендорским саппортом, начиная от помощи с эскалациями (когда проблема не решается в разумные сроки, и нужен живительный пендель; и заканчивая полным ведением тикета (как правило, общение с саппортом крупного вендора вялотекущее, но контекст всё равно нужно держать в голове. Плюс в случае RMA помогать с доставкой или организацией визита сервис-инженера).</p>
<p>Я встречал мнение, что быть технарём FinOPS не обязательно, ему главное бумажки вовремя перекладывать, эскалации писать и за оплатами следить. Но на своём опыте могу сказать. что именно FinOPS в таком случае не получится, а будет очередной &#8220;отдел закупок&#8221;, слабо понимающий, что за услуги он закупает.</p>
<blockquote><p>Ещё одна типичная история &#8211; это постоянный анализ &#8220;выгодных предложений&#8221; от партнёров. Предложения бывают выгодные или не очень, своевременные и не совсем. Их первичным анализом занимается именно FinOPS, как &#8220;первая линия обороны&#8221;. Если же он просто будет бегать туда-сюда с вопросами, то какой в нём смысл?</p></blockquote>
<h1>Неочевидные нюансы работы и требования к FinOPS</h1>
<p>Как я уже говорил выше, при оформлении сделки (подписании договора и/или выставлении инвойса) возникают различные неожиданные моменты, даже если мы говорим о 100% белых компаниях.</p>
<p>Сюда относится:</p>
<ul>
<li>юрисдикция сделки (по законодательству какой страны заключается соглашение);</li>
<li>резидентами каких стран являются стороны сделки;</li>
<li>по какому адресу необходимо отгрузить товар или предоставить услугу;</li>
<li>валюта (RUR/USD/EUR &#8211; порой одна из сторон, например, не принимает платежи в USD, или наоборот, не может платить в USD без большого геморроя, предпочитая евро, сюда же платежи из России в пользу иностранных юр. лиц);</li>
<li>налоги (в каждой стране свои приколы);</li>
<li>сроки поставки и её стоимость;</li>
<li>трансграничная торговля, санкции и ограничения регуляторов (и связанные с этим ограничения на поддержку, увеличение сроков поставки и т.д.);</li>
<li>срок договора (расторгнуть его досрочно может быть очень дорого), SLA сервиса, и т.д. и т.п.</li>
</ul>
<p>На каждый из этих пунктов есть свои спецы, но, как правило, основная часть вопросов закрывается одним человеком с опытом, потому что они довольно типовые в рамках одной компании и плюс-минус стабильного пула поставщиков.</p>
<blockquote><p>Например, некоторое время назад покупать софт в РФ было выгоднее, чем в Европе, потому что на него не начислялся НДС. С января, к сожалению, халява закончилась, и по этому поводу в конце 2020 года было достаточно жарко, т.к. нужно было успеть заказать/подписать/оплатить самые важные и дорогие позиции.</p></blockquote>
<h1>Что требуется от Supplier relations manager/FinOPS</h1>
<ul>
<li>Разговорный английский. Это прямо must have и не обсуждается, если только ваша компания не общается сугубо с российскими поставщиками</li>
<li>Разумная степень занудства.</li>
<li>Не бояться разбираться с бумажками, огромным количеством почты и кучей разных сейлзов, часть из которых разговаривает по-английски хуже, чем вы (хотя по опыту, общаться с британцами и ирландцами тоже нелегко).</li>
<li>Умение ориентироваться в 100500 различных сервисах, в части из них разбираться очень хорошо.</li>
<li>Умение и желание находить нужных людей и добиваться от них того, что тебе нужно.</li>
<li>Умение найти нужный сервис по очень примерному ТЗ, а заодно набросать MVP или задать правильные вопросы пресейлу (например, при выборе датацентра).</li>
<li>Совершенно обязателен технический кругозор (а также желание его постоянно расширять), чтобы разговаривать на одном языке и со своими командами, и с вендорами/партнёрами.</li>
<li>Умение держать в голове кучу вещей одновременно и помнить сроки, суммы и проценты (это бывает важно). Можно, конечно, обойтись каким-то аналогом CRM, но помнить всё равно нужно много (как минимум &#8211; как и где быстро найти нужную информацию).</li>
</ul>
<h1>Инструменты FinOPS</h1>
<p>Начать можно с почты (это вообще основной инструмент); шаренной папки (хоть на гуглодиске) для сканов документов, вики (для ведения реестра поставщиков) и гуглотаблицы с раскладом по оплатам.</p>
<p>Уже после, когда поймёте, что вам нужно, можно будет поискать (или написать самим) соответствующие инструменты а-ля &#8220;CRM наоборот&#8221;.</p>
<blockquote><p>Не надо недооценивать силу эксель-таблиц и усложнять что-то раньше времени.</p></blockquote>
<p>Ну и конечно, мессенджеры становятся вашими лучшими друзьями. Причём почти все, включая довольно экзотические &#8211; потому что у всех партнёров разные предпочтения и корпоративные правила. В 2021 говорить про использование мессенджеров это, наверное, из разряда &#8220;советы Капитана Очевидность&#8221;, но нужно понимать, что у FinOPS это не опция, а суровая необходимость и бОльшая часть работы.</p>
<h1>Заключение</h1>
<p><del datetime="2022-01-30T22:23:57+00:00">Закупки в IT &#8211; это просто, как кататься на горящем велосипеде.</del> Управление закупками в IT &#8211; это не только своевременная оплата счетов и бюджетирование. Это ещё и общение с партнёрами, коллегами и &#8220;просто так&#8221;, потому что никогда не знаешь, какая информация и какие знакомства тебе пригодятся завтра. Сегодня ты слушаешь байки об особенностях работы в арабских странах и думаешь &#8220;как хорошо, что мы там не работаем!&#8221;, а завтра ищешь партнёра для размещения там нового PoP. Это ещё и глубокое понимание особенностей собственной инфраструктуры, чтобы коллеги из эксплуатации получили нужное качество сервиса без звёздочек и сносок мелким шрифтом. Это, наконец, понимание юридических и финансовых &#8220;правил игры&#8221;, потому что вовремя подмеченная неточность в договоре или бланке заказа может сэкономить неделю-другую времени на согласованиях.</p>
<p>В общем, это весело!</p>
<p>The post <a href="https://nixman.info/?p=5867">Закупки как сервис</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=5867</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Juniper SRX и Cisco ASA: серия очередная</title>
		<link>https://nixman.info/?p=2882</link>
					<comments>https://nixman.info/?p=2882#respond</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Tue, 24 Dec 2019 09:24:58 +0000</pubDate>
				<category><![CDATA[Hard]]></category>
		<category><![CDATA[asa]]></category>
		<category><![CDATA[cisco]]></category>
		<category><![CDATA[ipsec]]></category>
		<category><![CDATA[juniper]]></category>
		<category><![CDATA[srx]]></category>
		<category><![CDATA[vpn]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2882</guid>

					<description><![CDATA[<p>Первый раз строить IPSec между Juniper SRX и Cisco ASA мне довелось ещё в далёком 2014 году. Уже тогда это было весьма болезненно, потому что проблем было много (обычно &#8211; разваливающийся при регенерации туннель), диагностировать было сложно (ASA стояла у нашего заказчика, поэтому возможности для дебага были ограничены), но как-то это работало. С той поры&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2882">Juniper SRX и Cisco ASA: серия очередная</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Первый раз строить IPSec между Juniper SRX и Cisco ASA мне довелось ещё в далёком 2014 году. Уже тогда это было весьма болезненно, потому что проблем было много (обычно &#8211; разваливающийся при регенерации туннель), диагностировать было сложно (ASA стояла у нашего заказчика, поэтому возможности для дебага были ограничены), но как-то это работало.</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.meme-arsenal.com/memes/27b272109ebdf8879f03323f366bb6ab.jpg" alt=""/></figure>



<p class="wp-block-paragraph">С той поры и рекомендованный JunOS для SRX обновился на 15.1 (для линейки SRX300, по крайней мере), и ASA научилась в route based IPSec (c версии софта 9.8), что несколько упрощает настройку. И вот на текущей работе не так давно представился шанс снова собрать такую схему. И снова неудачно &#8211; при регенерации туннель благополучно падал (и не всегда поднимался без ручного рестарта). И снова в логах тишина и непонятки, а т.к. ASA находилась у нашего партнёра, то и дебажить, соответственно, не было никакой возможности.И вот теперь представился случай собрать схему, при которой обе стороны (и SRX, и ASA) находятся под нашим управлением, соответственно, поиграться можно на славу.</p>



<span id="more-2882"></span>



<h2 class="wp-block-heading">Диспозиция</h2>



<p class="wp-block-paragraph">Итак, что у нас имеется:</p>



<ul class="wp-block-list"><li>Juniper SRX340, JunOS 15.1X49D150.2</li><li>Cisco ASA 5506 asa 9.8.4</li><li>route based IPSec между ними (роутинг будет обеспечиваться BGP, о нём тоже скажу пару слов)<br></li></ul>



<h2 class="wp-block-heading">Схема</h2>



<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://www.evernote.com/shard/s261/res/c967fc6e-55b8-48b6-a1f0-e54b20a4f208" alt=""/></figure></div>



<h2 class="wp-block-heading">Конфигурация</h2>



<h3 class="wp-block-heading">Juniper</h3>



<p class="wp-block-paragraph">Начнём с конфигурации SRX. У меня довольно много различных туннелей строится на SRX, в итоге я пришёл примерно к такой схеме:</p>



<pre class="wp-block-code"><code>set security ike policy IKE-ASA mode main
set security ike policy IKE-ASA proposals SHA256-AES128-5-86400
set security ike policy IKE-ASA pre-shared-key ascii-text ...

set security ike gateway GW-ASA ike-policy IKE-ASA
set security ike gateway GW-ASA address 192.0.2.2 
set security ike gateway GW-ASA dead-peer-detection interval 10
set security ike gateway GW-ASA dead-peer-detection threshold 3
set security ike gateway GW-ASA local-identity inet 198.51.100.2
set security ike gateway GW-ASA external-interface ae0.4
set security ike gateway GW-ASA version v2-only

set security ipsec vpn VPN-ASA bind-interface st0.7
set security ipsec vpn VPN-ASA df-bit clear
set security ipsec vpn VPN-ASA vpn-monitor source-interface st0.7
set security ipsec vpn VPN-ASA vpn-monitor destination-ip 169.254.100.2
set security ipsec vpn VPN-ASA ike gateway GW-ASA
set security ipsec vpn VPN-ASA ike ipsec-policy SHA256-AES128-3600-14-policy
set security ipsec vpn VPN-ASA establish-tunnels immediately

set interfaces st0 unit 7 description "ASA AnyConnect router"
set interfaces st0 unit 7 family inet mtu 1436
set interfaces st0 unit 7 family inet address 169.254.100.1/30

set routing-options static route 192.0.2.2/32 next-hop 198.51.100.1

set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic system-services ping
set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic system-services ike
set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic system-services traceroute
set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic protocols bgp</code></pre>



<p class="wp-block-paragraph">Видно, что используется IKEv2, без traffic-selectors (у нас в арсенале и без того достаточно средств, чтобы ограничить хождение трафика &#8211; от префикс-листов BGP до security policies). До кучи используется DPD (dead peer detection) и vpn-monitor (у них немного разный тип проверок, для надёжности я использую оба).</p>



<h3 class="wp-block-heading">Cisco</h3>



<p class="wp-block-paragraph">Конфигурация ASA:</p>



<pre class="wp-block-code"><code>crypto ipsec ikev2 ipsec-proposal SHA256-AES128
 protocol esp encryption aes-256 aes-192 aes
 protocol esp integrity sha-256

crypto ipsec profile IPSEC-PROFILE-AMS1-VPN2
 set ikev2 ipsec-proposal SHA256-AES128
 set pfs group14
 set security-association lifetime kilobytes unlimited
 set security-association lifetime seconds 3600

crypto ikev2 policy 1
 encryption aes-256 aes-192 aes
 integrity sha256
 group 5
 prf sha256
 lifetime seconds 86400
  
tunnel-group 198.51.100.2 type ipsec-l2l
tunnel-group 198.51.100.2 ipsec-attributes
 isakmp keepalive threshold 30 retry 10
 ikev2 remote-authentication pre-shared-key ...
 ikev2 local-authentication pre-shared-key ...

crypto ikev2 enable outside

interface Tunnel7
 nameif l2l-ams1-vpn2
 ip address 169.254.100.2 255.255.255.252 
 tunnel source interface outside
 tunnel destination 198.51.100.2
 tunnel mode ipsec ipv4
 tunnel protection ipsec profile IPSEC-PROFILE-AMS1-VPN2</code></pre>



<p class="wp-block-paragraph">Структура конфигов примерно одинаковая на обоих роутерах, но, как обычно, название секций не совпадают совершенно.<br>Давайте пробежимся, что чему соответствует.</p>



<h3 class="wp-block-heading">Сравнение конфигов</h3>



<h4 class="wp-block-heading">IKE policy / proposal</h4>



<pre class="wp-block-code"><code>crypto ikev2 policy 1
 encryption aes-256 aes-192 aes
 integrity sha256
 group 5
 prf sha256
 lifetime seconds 86400</code></pre>



<pre class="wp-block-code"><code>set security ike proposal SHA256-AES128-5-86400 description ike-phase1-proposal1
set security ike proposal SHA256-AES128-5-86400 authentication-method pre-shared-keys
set security ike proposal SHA256-AES128-5-86400 dh-group group5
set security ike proposal SHA256-AES128-5-86400 authentication-algorithm sha-256
set security ike proposal SHA256-AES128-5-86400 encryption-algorithm aes-128-cbc
set security ike proposal SHA256-AES128-5-86400 lifetime-seconds 86400

set security ike policy IKE-ASA mode main
set security ike policy IKE-ASA proposals SHA256-AES128-5-86400
set security ike policy IKE-ASA pre-shared-key ascii-text ...</code></pre>



<p class="wp-block-paragraph">Здесь начинается некоторая путаница в терминологии. То, что у Cisco называется IKE policy, у Juniper &#8211; IKE Proposal. А IKE policy у Juniper похоже на tunnel group у ASA&#8230; Лично мне больше нравится подход Juniper, но тут, безусловно, дело привычки. Надо сказать, настройка IKEv2 (тем более route based) на ASA выглядит всё же куда логичнее, чем crypto maps и прочее безобразие, которое было раньше. </p>



<h4 class="wp-block-heading">IPSec policy/proposal</h4>



<pre class="wp-block-code"><code>crypto ipsec ikev2 ipsec-proposal SHA256-AES128
 protocol esp encryption aes-256 aes-192 aes
 protocol esp integrity sha-256

crypto ipsec profile IPSEC-PROFILE-SHA256-AES128-3600-14
 set ikev2 ipsec-proposal SHA256-AES128
 set pfs group14
 set security-association lifetime kilobytes unlimited
 set security-association lifetime seconds 3600</code></pre>



<pre class="wp-block-code"><code>set security ipsec proposal SHA256-AES128-3600 description ipsec-phase2-proposal
set security ipsec proposal SHA256-AES128-3600 protocol esp
set security ipsec proposal SHA256-AES128-3600 authentication-algorithm hmac-sha-256-128
set security ipsec proposal SHA256-AES128-3600 encryption-algorithm aes-128-cbc
set security ipsec proposal SHA256-AES128-3600 lifetime-seconds 3600

set security ipsec policy SHA256-AES128-3600-14-policy description SHA256-AES128-3600-14-policy
set security ipsec policy SHA256-AES128-3600-14-policy perfect-forward-secrecy keys group14
set security ipsec policy SHA256-AES128-3600-14-policy proposals SHA256-AES128-3600</code></pre>



<p class="wp-block-paragraph">Здесь оба вендора делают плюс-минус одинаково &#8211; сначала создаём proposal с параметрами шифрования/аутентификации, а потом навешиваем на него lifetime и pfs.</p>



<h4 class="wp-block-heading">Gateway</h4>



<pre class="wp-block-code"><code>tunnel-group 176.56.179.13 type ipsec-l2l
tunnel-group 176.56.179.13 ipsec-attributes
 isakmp keepalive threshold 30 retry 10
 ikev2 remote-authentication pre-shared-key ...
 ikev2 local-authentication pre-shared-key ...</code></pre>



<pre class="wp-block-code"><code>set security ike gateway GW-ASA ike-policy IKE-ASA-LEGAL
set security ike gateway GW-ASA address 192.0.2.2
set security ike gateway GW-ASA dead-peer-detection interval 10
set security ike gateway GW-ASA dead-peer-detection threshold 3
set security ike gateway GW-ASA local-identity inet 198.51.100.2
set security ike gateway GW-ASA external-interface ae0.4
set security ike gateway GW-ASA version v2-only</code></pre>



<p class="wp-block-paragraph">А здесь отличия уже более явные. На ASA PSK указывается непосредственно в настройках пира. Juniper же позволяет здесь задать и исходящий интерфейс и дополнительные опции типа local-identity, плюс ссылается на ike policy (где мы указывали PSK). Кстати, если вы захотите переделать на ASA IKEv2 в IKEv1 (и наоборот), то у Cisco надо будет пересоздавать всю tunnel-group. А на SRX всего лишь сменить одну строчку. <em>(Правда, далее при commit могут вылезти несовместимые опции, но это уже детали)</em></p>



<h4 class="wp-block-heading">VPN / VTI</h4>



<pre class="wp-block-code"><code>interface Tunnel7
 nameif l2l-ams1-vpn2
 ip address 169.254.100.2 255.255.255.252 
 tunnel source interface outside
 tunnel destination 198.51.100.2
 tunnel mode ipsec ipv4
 tunnel protection ipsec profile IPSEC-PROFILE-SHA256-AES128-3600-14</code></pre>



<pre class="wp-block-code"><code>set security ipsec vpn VPN-ASA bind-interface st0.7
set security ipsec vpn VPN-ASA df-bit clear
set security ipsec vpn VPN-ASA vpn-monitor source-interface st0.7
set security ipsec vpn VPN-ASA vpn-monitor destination-ip 169.254.100.2
set security ipsec vpn VPN-ASA ike gateway GW-ASA
set security ipsec vpn VPN-ASA ike ipsec-policy SHA256-AES128-3600-14-policy
set security ipsec vpn VPN-ASA establish-tunnels immediately

set interfaces st0 unit 7 description "AnyConnect router"
set interfaces st0 unit 7 family inet mtu 1436
set interfaces st0 unit 7 family inet address 169.254.100.1/30</code></pre>



<p class="wp-block-paragraph">И снова конфиг Juniper мне кажется более логичным. VPN настраивается отдельно (он может быть и policy-based), сам security tunnel &#8211; отдельно. Отдельное спасибо за &#8220;establish-tunnels immediately&#8221;. Очень полезная опция <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (цисководы поймут, о чём я). Ещё один &#8220;бонус&#8221; SRX &#8211; можно строить многоточечные IPSec, как с автообнаружением пиров (работает, к сожалению, только между SRX), так с ручным роутингом. Это, конечно, не полноценный DMVPN, но жизнь в сетапах типа &#8220;один центр &#8211; много филиалов&#8221; значительно облегчает.</p>



<h4 class="wp-block-heading">Interfaces</h4>



<p class="wp-block-paragraph">Отдельно остановлюсь на настройке интерфейсов, на которых строится IPSec. У Juniper это, соответственно, <strong>ae0.4</strong>, у ASA &#8211; <strong>outside</strong></p>



<pre class="wp-block-code"><code>crypto ikev2 enable outside</code></pre>



<pre class="wp-block-code"><code>set security zones security-zone ZONE-INTERNET interfaces ae0.4 host-inbound-traffic system-services ike
set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic system-services ping
set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic system-services traceroute
set security zones security-zone ZONE-VPN interfaces st0.7 host-inbound-traffic protocols bgp</code></pre>



<p class="wp-block-paragraph">На интерфейсах нужно разрешить ike, иначе работать ничего не будет <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Дополнительно, у SRX нужно для туннельного интерфейса разрешить bgp/ipsec/whatever для входящих подключений на st0.x интерфейсе</p>



<h2 class="wp-block-heading">Настройка BGP</h2>



<p class="wp-block-paragraph">Тут всё довольно банально (с одной стороны)</p>



<pre class="wp-block-code"><code>set protocols bgp group ASA type external
set protocols bgp group ASA description "AnyConnect router"
set protocols bgp group ASA hold-time 30
set protocols bgp group ASA import IMPORT-EBGP-ASA
set protocols bgp group ASA export EXPORT-EBGP-ASA
set protocols bgp group ASA local-as 64666
set protocols bgp group ASA neighbor 169.254.100.2 peer-as 65001

set policy-options policy-statement EXPORT-EBGP-ASA term 0 from route-filter 10.0.0.0/8 exact
set policy-options policy-statement EXPORT-EBGP-ASA term 0 then accept
set policy-options policy-statement EXPORT-EBGP-ASA term 1 then reject

set policy-options policy-statement IMPORT-EBGP-ASA term 1 then reject</code></pre>



<p class="wp-block-paragraph">На ASA отдаём агрегированный префикс нашей локалки &#8211; у меня это будет 10/8. От ASA ничего не принимаем, потому что с версии софта 9.8.4 всё равно нельзя анонсировать по BGP адреса management-интерфейсов (что объяснимо) и BVI (что жутко неудобно). Но если у вас за ASA есть ещё какие-то сети, их нужно будет добавить в policy, конечно.</p>



<pre class="wp-block-code"><code>asa(config-router-af)# network 10.255.32.252 mask 255.255.255.254
ERROR: BGP configuration not supported on management-only/BVI interface</code></pre>



<p class="wp-block-paragraph">Чтобы &#8220;увидеть&#8221; inside интерфейс, нужно будет на SRX прописать static route в сторону ipsec:</p>



<pre class="wp-block-code"><code>set routing-options static route 10.255.32.252/31 next-hop 169.254.100.2</code></pre>



<p class="wp-block-paragraph">Вдобавок, ASA до сих пор не умеет в loopback интерфейсы, поэтому все логи/netflow и прочая мы будем отправлять с inside.В ASA5506 есть встроенный свич, поэтому можно использовать виртуальный BVI-интерфейс (особенно полезно, когда у вас схема &#8220;роутер-на-палочке&#8221;, и используется всего лишь один физический порт.</p>



<pre class="wp-block-code"><code>interface BVI1
 nameif inside
 security-level 100
 ip address 10.255.32.253 255.255.255.254
management-access inside</code></pre>



<p class="wp-block-paragraph">После этого в нужных местах (logging, snmp, flow) в качестве интерфейса-источника нужно будет указать `inside`.</p>



<h2 class="wp-block-heading">Если что-то пошло не так a.k.a. troubleshooting</h2>



<h3 class="wp-block-heading">IKE/IPSec</h3>



<p class="wp-block-paragraph">Первое &#8211; у вас должны установиться обе фазы IPSec (у Juniper это, собственно, IKE/IPSec). Смотрим:</p>



<pre class="wp-block-code"><code>admin@srx> show security ike security-associations 
Index   State  Initiator cookie  Responder cookie  Mode           Remote Address   
2128190 UP     ae7d7d447326218a  2be3b3004ae0e36a  IKEv2          192.0.2.2    

admin@srx> show security ipsec security-associations  
  Total active tunnels: 6
  ID    Algorithm       SPI      Life:sec/kb  Mon lsys Port  Gateway   
  &lt;131077 ESP:aes-cbc-128/sha256 fec3c7d1 2867/ unlim U root 500 192.0.2.2    
  >131077 ESP:aes-cbc-128/sha256 74d792ca 2867/ unlim U root 500 192.0.2.2    </code></pre>



<p class="wp-block-paragraph">На ASA:</p>



<pre class="wp-block-code"><code>asa# sho crypto ikev2 sa 

IKEv2 SAs:

Session-id:5, Status:UP-ACTIVE, IKE count:1, CHILD count:1

Tunnel-id Local                                               Remote                                                  Status         Role
585564345 192.0.2.2/500                                  198.51.100.2/500                                        READY    RESPONDER
      Encr: AES-CBC, keysize: 128, Hash: SHA256, DH Grp:5, Auth sign: PSK, Auth verify: PSK
      Life/Active Time: 86400/47018 sec
Child sa: local selector  0.0.0.0/0 - 255.255.255.255/65535
          remote selector 0.0.0.0/0 - 255.255.255.255/65535
          ESP spi in/out: 0xc989d9ea/0xcca8b6d5</code></pre>



<p class="wp-block-paragraph">У Juniper ещё можно посмотреть статистику по ipsec-туннелю, включая причины падения:</p>



<pre class="wp-block-code"><code>admin@srx> show security ipsec security-associations index 131078 detail 

ID: 131078 Virtual-system: root, VPN Name: VPN-ASA-LEGAL-PL
  Local Gateway: 198.51.100.2, Remote Gateway: 192.0.2.2
  Local Identity: ipv4_subnet(any:0,[0..7]=0.0.0.0/0)
  Remote Identity: ipv4_subnet(any:0,[0..7]=0.0.0.0/0)
  Version: IKEv2
  DF-bit: clear, Copy-Outer-DSCP Disabled, Bind-interface: st0.7
  Port: 500, Nego#: 734, Fail#: 0, Def-Del#: 0 Flag: 0x600a29 
  Tunnel events: 
    Mon Dec 09 2019 13:40:35: IPSec SA rekey successfully completed (48 times)
    Mon Dec 09 2019 00:30:47: IKE SA rekey successfully completed (10 times)
    Fri Nov 29 2019 02:13:55: IPSec SA negotiation successfully completed (1 times)
    Fri Nov 29 2019 02:13:55: IKE SA negotiation successfully completed (1 times)
    Fri Nov 29 2019 02:13:55: No response from peer. Negotiation failed (7 times)
    Fri Nov 29 2019 02:10:14: DPD detected peer as down. Existing IKE/IPSec SAs cleared (1 times)
    Fri Nov 29 2019 01:39:15: IPSec SA rekey successfully completed (1 times)
    Fri Nov 29 2019 00:49:50: IPSec SA negotiation successfully completed (1 times)
    Fri Nov 29 2019 00:49:50: IKE SA negotiation successfully completed (1 times)
    Fri Nov 29 2019 00:49:30: No response from peer. Negotiation failed (23 times)
    Fri Nov 29 2019 00:37:24: DPD detected peer as down. Existing IKE/IPSec SAs cleared (1 times)
    Fri Nov 29 2019 00:30:00: IPSec SA rekey successfully completed (77 times)
    Thu Nov 28 2019 20:11:31: IKE SA rekey successfully completed (7 times)
    Tue Nov 26 2019 08:51:44: IPSec SA negotiation successfully completed (1 times)
    Thu Nov 21 2019 21:24:32: IKE SA negotiation successfully completed (1 times)
    Thu Nov 21 2019 01:06:27: IKE SA rekey successfully completed (6 times)
  Direction: inbound, SPI: 4bd2e2bd, AUX-SPI: 0
                              , VPN Monitoring: UP
    Hard lifetime: Expires in 3132 seconds
    Lifesize Remaining:  Unlimited
    Soft lifetime: Expires in 2495 seconds
    Mode: Tunnel(10 10), Type: dynamic, State: installed
    Protocol: ESP, Authentication: hmac-sha256-128, Encryption: aes-cbc (128 bits)
    Anti-replay service: counter-based enabled, Replay window size: 64
  Direction: outbound, SPI: 504f306e, AUX-SPI: 0
                              , VPN Monitoring: UP
    Hard lifetime: Expires in 3132 seconds
    Lifesize Remaining:  Unlimited
    Soft lifetime: Expires in 2495 seconds
    Mode: Tunnel(10 10), Type: dynamic, State: installed
    Protocol: ESP, Authentication: hmac-sha256-128, Encryption: aes-cbc (128 bits)
    Anti-replay service: counter-based enabled, Replay window size: 64</code></pre>



<p class="wp-block-paragraph">Если с IPSec всё в порядке, то нужно смотреть на ACL (security policies, host-inbound правила и т.д.). На крайней случай, можно попробовать перезагрузить коробку (ASA) &#8211; мне, бывало, помогает.</p>



<h3 class="wp-block-heading">BGP</h3>



<p class="wp-block-paragraph">Здесь всё довольно стандартно &#8211; если сессия не устанавливается, можно посмотреть через <code>capture</code> , летят ли BGP-hello в обе стороны.</p>



<p class="wp-block-paragraph">На этом всё. Не знаю, виной ли тому новый софт, или звёзды так сошлись &#8211; но туннель ASA&lt;&gt;SRX держится стабильно и не падает раз в сутки, как было раньше.Надеюсь, у вас тоже всё получится!</p>
<p>The post <a href="https://nixman.info/?p=2882">Juniper SRX и Cisco ASA: серия очередная</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2882</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Настройка Postfix через Yandex relay</title>
		<link>https://nixman.info/?p=2868</link>
					<comments>https://nixman.info/?p=2868#respond</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Mon, 13 May 2019 07:09:20 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mail]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[relay]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[tls]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2868</guid>

					<description><![CDATA[<p>Сейчас, во времена новомодных devops-инструментов, отправки сообщений в Slack или Telegram одной строчкой в скрипте и так далее, электронная почта кажется ненужным атавизмом. И всё-таки возникают случаи, когда с linux-машины нужно отправить сообщение. И, желательно, через какой-нибудь доверенный relay типа Google или Yandex. Почему? Потому что иначе отправленное вами письмо или попадёт в спам, или&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2868">Настройка Postfix через Yandex relay</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Сейчас, во времена новомодных devops-инструментов, отправки сообщений в Slack или Telegram одной строчкой в скрипте и так далее, электронная почта кажется ненужным атавизмом.<br />
И всё-таки возникают случаи, когда с linux-машины нужно отправить сообщение. И, желательно, через какой-нибудь доверенный relay типа Google или Yandex.<br />
Почему? Потому что иначе отправленное вами письмо или попадёт в спам, или вовсе не дойдёт до адресата.<br />
Не буду останавливаться на настройке DKIM/SPF &#8211; тут всё, во-первых, будет зависеть от того, используете ли вы ПДД (почта для домена), а во-вторых, если вы знаете, что это такое и зачем нужно, то разберётесь и без меня (ну или погуглите ;))</p>
<p>Итак, рассмотрим простую ситуацию. У нас есть аккаунт в Yandex (у меня это Yandex.PDD). Мы хотим отправлять почту с linux-машины (ubuntu 18.04) через SMTP Relay с авторизацией.<br />
Делать мы это будем при помощи postfix.<br />
<span id="more-2868"></span></p>
<h2>1. Ставим нужное</h2>
<p>Поехали:<br />
[cc lang=&#8221;bash&#8221;]apt install postfix mailutils libsasl2-2 sasl2-bin libsasl2-modules[/cc]</p>
<h2>2. Правим конфиги</h2>
<p><em>cat /etc/mailname</em><br />
[cc]server.example.com[/cc]<br />
<em>cat /etc/hostname</em><br />
[cc]server.example.com[/cc]</p>
<p><em>cat /etc/postfix/main.cf</em><br />
[cc lang=&#8221;bash&#8221;]<br />
myorigin = /etc/mailname<br />
ЕСЛИ почтовый домен совпадает с hostname сервера, меняем параметр mydestination<br />
mydestination = localhost.$mydomain, localhost<br />
Если этого не сделать, сервер не сможет слать письма в свой домен, т.к. будет искать адресатов в таблице локальных пользователей — разумеется безуспешно.<br />
[/cc]<br />
Часть настроек я опустил, оставил только то, что изменится по сравнению с дефолтной конфигурацией.</p>
<p>В этом файлике мы будем настраивать маппинг внутренних адресов<br />
Подробное описание <a href="http://www.postfix.org/generic.5.html" rel="noopener" target="_blank">тут</a>:<br />
<em>cat /etc/postfix/generic</em><br />
[cc]<br />
root robot@example.com<br />
mailer-daemon robot@example.com<br />
@localhost robot@example.com<br />
@localhost robot@example.com<br />
@example.com robot@example.com<br />
@localhost.localdomain robot@example.com<br />
[/cc]</p>
<p>Настраиваем rewrite адресов отправителей.<br />
Вместо домена можно указать конкретный адрес<br />
Подробное описание <a href="http://www.postfix.org/canonical.5.html" rel="noopener" target="_blank">тут</a>:<br />
<em>cat /etc/postfix/sender_canonical_maps</em><br />
[cc]@example.com robot@example.com[/cc]</p>
<p>Тут мы говорим, для каких доменов (или адресантов) мы будем использовать релей<br />
<em>cat /etc/postfix/sender_relay</em><br />
[cc]@example.com [smtp.yandex.ru][/cc]</p>
<p>А в этом файле, указываем, собственно, smtp-сервер и параметры аутентификации.<br />
<em>cat /etc/postfix/sasl_passwd</em><br />
[cc][smtp.yandex.ru]:587    robot@example.com:password[/cc]</p>
<p>Т.к. взаимодействие с сервером идёт по TLS, не помешает скачать сертификат SMTP-сервера.<br />
Добыть сертификат можно вот так:<br />
[cc lang=&#8221;bash&#8221;]openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25[/cc]</p>
<p>Из вывода нам нужно что-то вроде такого:<br />
[cc]&#8212;&#8211;BEGIN CERTIFICATE&#8212;&#8211;<br />
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf<br />
MQswCQYDVQQGEwJSVTETMBEGA1UEChMKWWFuZGV4IExMQzEnMCUGA1UECxMeWWFu<br />
ZGV4IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRIwEAYDVQQDEwlZYW5kZXggQ0Ew<br />
HhcNMTcxMDExMTMyNzI2WhcNMTkxMDExMTMyNzI2WjB3MQswCQYDVQQGEwJSVTET<br />
MBEGA1UECgwKWWFuZGV4IExMQzEMMAoGA1UECwwDSVRPMQ8wDQYDVQQHDAZNb3Nj<br />
b3cxGzAZBgNVBAgMElJ1c3NpYW4gRmVkZXJhdGlvbjEXMBUGA1UEAwwOc210cC55<br />
YW5kZXgucnUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTI5WsplxQ<br />
g7gZDCEmnbxHI0a0/cXtx0+Zwz7Y9TSFy0NI/SzYC+bgukWvsnvuIheM3yKpJ+cU<br />
Ss2G+K3nKOYDNJUezzziirhu3UVC/tZLD39orKKGAa6qmx5Dv2Z7/ynkOfKZjmXB<br />
t9HemoCItyM62YTD8AQQmkMCB4Kue+j2wm8fHxPtgIYuQzEtD9xCU9vANj6imgaM<br />
IlrM0cegknd6sWBDR074pDsBEUjg2GsNSqAo2nD0tvOGCFZ2qkIMLIjZgsCmtain<br />
nM7Xt+THw8ApMu9BVsgTyXMTfVC0CzfB1HbId1UzqIbILprB3iLrxCHn3K1F68ok<br />
WfBXBDY4gphTAgMBAAGjggMJMIIDBTAMBgNVHRMBAf8EAjAAMGkGA1UdHwRiMGAw<br />
L6AtoCuGKWh0dHA6Ly9jcmxzLnlhbmRleC5uZXQvY2VydHVtL3ljYXNoYTIuY3Js<br />
MC2gK6AphidodHRwOi8veWFuZGV4LmNybC5jZXJ0dW0ucGwveWNhc2hhMi5jcmww<br />
cQYIKwYBBQUHAQEEZTBjMCwGCCsGAQUFBzABhiBodHRwOi8veWFuZGV4Lm9jc3At<br />
cmVzcG9uZGVyLmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL3JlcG9zaXRvcnkuY2Vy<br />
dHVtLnBsL3ljYXNoYTIuY2VyMB8GA1UdIwQYMBaAFDdc4xngso6hqE7Sz6vQ3OML<br />
XDVNMB0GA1UdDgQWBBTC1Kbatmr8y04cui/VCaPVq1mgKzAOBgNVHQ8BAf8EBAMC<br />
BaAwggEXBgNVHSAEggEOMIIBCjCCAQYGDCqEaAGG9ncCBQEKAjCB9TCB8gYIKwYB<br />
BQUHAgIwgeUwIBYZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjADAgECGoHAVXNh<br />
Z2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdHJpY3RseSBzdWJqZWN0ZWQgdG8g<br />
dGhlIENFUlRVTSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudCAoQ1BT<br />
KSBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlIGhlcmVpbiBhbmQgaW4gdGhlIHJl<br />
cG9zaXRvcnkgYXQgaHR0cHM6Ly93d3cuY2VydHVtLnBsL3JlcG9zaXRvcnkuMB0G<br />
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjARBglghkgBhvhCAQEEBAMCBsAw<br />
egYDVR0RBHMwcYIOc210cC55YW5kZXgucnWCDnNtdHAueWFuZGV4LmJ5gg5zbXRw<br />
LnlhbmRleC5reoIPc210cC55YW5kZXguY29tgg5zbXRwLnlhbmRleC51YYISc210<br />
cC55YW5kZXguY29tLnRyggpzbXRwLnlhLnJ1MA0GCSqGSIb3DQEBCwUAA4IBAQA1<br />
GjyKSYMgaRVLGd4EWtB3oTkybDu5QrUXt/eoZiquzUqZwk7x9FRsEEirawKsrSS6<br />
FXcliRD7xcXneROVDZK1a4ur6974vn742B/lOx9T/7+6a8XQo4jz191zZWS3J47G<br />
dSvkMZPSdsZPxn7cDbAymFP4yw3b/aJJBFarpYTUixvRXZardO93VAFx157pCt/8<br />
3dN7jLWyYVWBvZh93JioukAu9uDt7Nzuq9XhTBLUzLnFFi4vXVsssKk7h3X2sMNU<br />
kZ3EPMAOSsvl9XY5RHZJs7BZubvGgnDxxGFfziP1XnTbL4MRCAXbdhwx3nmnQ3yZ<br />
nRG0DfdqYIuPGApFORYe<br />
&#8212;&#8211;END CERTIFICATE&#8212;&#8211;[/cc]</p>
<p>..и сохранить в файл (в моём случае /etc/postfix/yandex.crt).</p>
<h2>3. Проверяем</h2>
<p>Комилируем конфигурацию для postfix:<br />
[cc]<br />
postmap /etc/postfix/canonical<br />
postmap /etc/postfix/generic<br />
postmap /etc/postfix/sasl_passwd<br />
postmap /etc/postfix/sender_relay<br />
[/cc]</p>
<p>И рестартуем сервис<br />
[cc]service postfix restart[/cc]</p>
<p>Отправку почты проверяем так (возможно, потребуется поставить mailx):<br />
[cc]echo &#8216;Hello, world!&#8217; | mail -s &#8216;Test of Yandex relay&#8217; root@example.com[/cc]</p>
<p>Если всё ок, то будет так (смотреть можно так: `sudo tail -F /var/log/mail.log`):<br />
[cc]<br />
May  5 01:10:38 server postfix/qmgr[18264]: 6F57B7D92E: from=<robot@example.com>, size=365, nrcpt=1 (queue active)<br />
May  5 01:10:39 server postfix/smtp[18274]: 6F57B7D92E: to=<root@example.com>, relay=smtp.yandex.ru[213.180.204.38]:25, delay=1.3, delays=0.01/0/0.49/0.8, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued on smtp4j.mail.yandex.net as 1557007839-eNWMy4YFLq-AcPCKVEh)<br />
[/cc]</p>
<p>А если не ок, то вот так:<br />
[cc]<br />
May  5 01:05:36 vpn01 postfix/qmgr[18014]: 6B2567D92E: from=<robot@example.com>, size=386, nrcpt=1 (queue active)<br />
May  5 01:05:36 vpn01 postfix/smtp[18024]: 6B2567D92E: to=<root@example.com>, relay=smtp.yandex.ru[213.180.204.38]:25, delay=0.49, delays=0.01/0/0.42/0.05, dsn=5.5.4, status=bounced (host smtp.yandex.ru[213.180.204.38] said: 503 5.5.4 Error: send AUTH command first. (in reply to MAIL FROM command))<br />
[/cc]<br />
<em>Я, в своё время, долго бился с этой ошибкой (потому что часть почты таки ходила нормально, а часть отбрасывалась сервером), даже переписывался с поддержкой Яндекса на этот счёт. Ничего вразумительного мне, конечно же, не ответили. Помогла тотальная ревизия конфигурации. Так что проверьте внимательно &#8211; возможно, что-то где-то вы написали не так, как надо</em></p>
<p>Или вот так:<br />
[cc]May  5 00:33:43 vpn01 postfix/qmgr[14714]: 2B1877D92F: from=<>, size=2359, nrcpt=1 (queue active)<br />
May  5 00:33:43 vpn01 postfix/smtp[14724]: 2B1877D92F: to=<robot@example.com>, relay=smtp.yandex.ru[93.158.134.38]:587, delay=0.55, delays=0.01/0/0.49/0.05, dsn=5.7.1, status=bounced (host smtp.yandex.ru[93.158.134.38] said: 553 5.7.1 Sender address rejected: not owned by auth user. (in reply to MAIL FROM command))<br />
[/cc]<br />
<em>Такая ошибка возникает, если в поле from указан не тот адрес, с которым вы логинитесь в почту.<br />
Возможны и другие ошибки, но при корректной конфигурации мне они не попадались.</em></p>
<p>P.S. Я советую использовать ansible для раскатывания ПО на ваши машины, и хранить YAML-описание ваших хостов в Git. Такой подход не только экономит время при раскатывании новой машины (или переустановке старой), но и позволяет хранить всю конфигурацию ваших хостов в одном месте &#8211; наглядно и просто.</p>
<p>The post <a href="https://nixman.info/?p=2868">Настройка Postfix через Yandex relay</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2868</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Репликация PostgreSQL</title>
		<link>https://nixman.info/?p=2828</link>
					<comments>https://nixman.info/?p=2828#comments</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Mon, 05 Feb 2018 07:00:40 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[barman]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[sql]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2828</guid>

					<description><![CDATA[<p>Как-то одна из моих знакомых админов спрашивала за репликацию PostgreSQL 9.4. Вопрос, в общем-то, несложный, но существующие howto и официальные мануалы показались мне не до конца понятными и прозрачными, и я решил написать свой, по-настоящему универсальный стандарт выложить в блог материал из нашей внутренней вики, благо PostgreSQL у нас используется давно и успешно. За предоставленный&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2828">Репликация PostgreSQL</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Как-то одна из моих знакомых админов спрашивала за репликацию PostgreSQL 9.4. Вопрос, в общем-то, несложный, но существующие howto и официальные мануалы показались мне не до конца понятными и прозрачными, и я решил <s>написать свой, по-настоящему универсальный стандарт</s> выложить в блог материал из нашей внутренней вики, благо PostgreSQL у нас используется давно и успешно.<br />
За предоставленный материал спасибо Андрею =)</p>
<p>Что мы рассмотрим?</p>
<ul>
<li>настройка доступов</li>
<li>репликация</li>
<li>резервные копии и восстановление</li>
</ul>
<p>А теперь обо всём этом подробнее под катом<br />
<span id="more-2828"></span></p>
<h2>Настройка доступов</h2>
<p>В нашей схеме работы используется связка PgBouncer + PostgreSQL 9.x.<br />
PgBouncer &#8211; это мультиплексор соединений к БД, его использование обусловлено тем, что приложения могут плодить сотни коннектов к базе &#8211; а в postgresql схема работы такова, что &#8220;один коннект == один процесс&#8221;: соответственно, кол-во одновременно работающих коннектов(процессов) не сможет превышать кол-во ядер процессора.</p>
<p>PgBouncer позволяет группировать подключения к бд по связке &#8220;username/database&#8221;, и использовать тем самым одно подключение к БД для разных коннектов приложений. В некоторых случаех это позволяет неплохо сэкономить ресурсы и не дёргать базу лишний раз.</p>
<p>Для контроля доступа/подключения используется так называемый &#8220;hba&#8221; файл (сокр. от &#8220;host-based authentication&#8221;).<br />
Почитать подробнее про него и его формат можно в <a href="https://postgrespro.ru/docs/postgrespro/9.6/auth-pg-hba-conf" rel="noopener" target="_blank">официальной документации</a>, здесь же стоит отметить лишь то, что у нас здесь их используется два: один &#8211; для PgBouncer&#8217;a, второй &#8211; для самого сервера PostgreSQL.</p>
<p>В файле для pgbouncer&#8217;a прописаны доступы для хостов приложений, в файле сервера &#8211; доступы для самого pgbouncer, ldap-пользователей и настройки, необходимые для работы репликации.<br />
Так же, возможен дополнительный уровень проверки с использованием <a href="https://postgrespro.ru/docs/postgrespro/9.6/auth-username-maps" rel="noopener" target="_blank">pg_ident.conf</a>.</p>
<p>В общих чертах, это всё. В конце будет приведен наглядный пример настроек.</p>
<h2>Репликация</h2>
<p>Прежде, чем я опишу механизм настройки репликации для postgresql, следует сделать небольшую вводную.</p>
<p>PostgreSQL предоставляет такой механизм, как &#8220;потоковая репликация&#8221; (streaming replication): это механизм работы, основанный на постоянном копировании WAL-логов с master-сервера и применении их на слейве.<br />
Чтобы это работало, нам необходим сервер, на котором установлена та же версия postgresql, что и на мастере (а в идеале &#8211; и такое же железо, чтобы, в случае становления слейва &#8211; мастером, он смог &#8220;потянуть&#8221; рабочую нагрузку), и идентичные настройки в конфигах и hba (кроме listen_addresses, понятное дело).</p>
<p>WAL (сокр. от &#8220;write-ahead log&#8221;) &#8211; это бинарный лог, в который postgres пишет диффы и правила, как их применять: это НЕ лог транзакций, в котором описаны SQL-команды для выполнения, и НЕ классический бинарный лог, в котором светятся только сырые данные &#8211; его внутреннее содержание отличается (хотя ближе ко второму варианту). Но основная особенность этого лога в том, что он <em>пишется прежде, чем действия реально применяются в базе</em> (отсюда и его название).<br />
Имея сохраненную копию папки с данными postgresq и WAL-логи с того момента, как была сделана копия данных, можно осуществить восстановление PITR (сокр. от &#8220;point-in-time-recovery&#8221;) &#8211; восстановление на любой, заданный момент времени от создания бэкапа до последней метки времени в WAL-логе (об этом позже).</p>
<p>PostgreSQL позволяет себя настроить таким образом, чтобы стягивать WAL-логи в real-time режиме (за это отвечает специальный демон), причем это будет практически &#8220;бесплатно&#8221;. Делать это можно как с мастера, так и с других реплик (т.н. &#8220;каскадная репликация&#8221;), в нашем случае мы можем позволить себе делать это напрямую с мастера (в случае с резервным копированием, это разумно &#8211; чтобы не было ошибок, связанных с несовпадающими id транзакций на мастере и слейвах).</p>
<p>Для начала, нам необходимо проверить, что в конфиге postgresql.conf имеются следующие настройки:</p>
<p><em><a href="https://postgrespro.ru/docs/postgrespro/9.5/runtime-config-wal.html#GUC-WAL-LEVEL" rel="noopener" target="_blank">wal_level</a> = archive</em> (или выше); необходимо для того, чтобы WAL-логи содержали информацию, необходимую для работы streaming replication<br />
<em><a href="https://postgrespro.ru/docs/postgrespro/9.5/runtime-config-replication.html#GUC-HOT-STANDBY" rel="noopener" target="_blank">hot_standby</a> = on;</em> позволяет обрабатывать запросы на чтение в процессе восстановления<br />
<em><a href="https://postgrespro.ru/docs/postgrespro/9.6/runtime-config-replication" rel="noopener" target="_blank">max_wal_senders</a> = &#8220;number_of_replicas + 1&#8221;;</em> учитываются в общем кол-ве соединений к серверу max_connections; так же, можно задать max_replication_slots<br />
<em>wal_keep_segments = 1000;</em> количество файлов WAL в директории pg_xlog/, которое будет храниться в папке с данными (по умолчанию, 16mb/файл);<br />
оно должно быть достаточным для того, чтобы обеспечить реплике успевание их стягивать при потоковой репликации;<br />
в противном случае, вы рискуете получить ситуацию, когда мастер удалит файлы журналов, которые ещё не были скопированы на реплику, и репликация сломается;<br />
если у вас активная запись в БД, и за время &#8220;лага репликации&#8221; вы успеваете выбрать это количество &#8211; вам стоит его увеличить.</p>
<p>Если вы хотите дополнительно копировать WAL-логи в другое хранилище &#8211; вам понадобятся:</p>
<p><em><a href="https://postgrespro.ru/docs/postgrespro/9.5/runtime-config-wal.html#GUC-ARCHIVE-MODE" rel="noopener" target="_blank">archive_mode</a> = on;</em><br />
<em><a href="https://postgrespro.ru/docs/postgrespro/9.5/runtime-config-wal.html#GUC-ARCHIVE-COMMAND" rel="noopener" target="_blank">archive_command</a> = &#8216;test ! -f /mnt/server/archivedir/%f &#038;&#038; cp %p /mnt/server/archivedir/%f&#8217; ;</em> # здесь может быть любая ваша команда или даже скрипт, который обеспечит копирование файлов, например rsync</p>
<p>Далее, создаём в базе пользователя с определенной ролью REPLICATION, и прописываем в hba-файле сервера для него доступ.<br />
Все действия производятся на pgsql-master.server из-под пользователя &#8220;postgres&#8221;:</p>
<p>[cc lang=&#8221;bash&#8221;]# md5 пароля формируется следующим образом: &#8220;md5&#8221; + $( echo -n &#8220;<UserPassword><UserName>&#8221; | md5sum &#8211; )<br />
# в psql выполняем:<br />
postgres=$ CREATE ROLE repusr;<br />
postgres=$ ALTER ROLE repusr WITH NOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB LOGIN REPLICATION NOBYPASSRLS PASSWORD &#8216;md540e8137e4ef276ecbcbe3f1b2eb5c343&#8217;;</p>
<p># добавляем в /etc/postgresql/9.6/main/pg_hba.conf следующую строчку (в данном случае, 192.168.0.11/32 &#8211; адрес pgsql-slave.server):<br />
# помните: если в вашем hba-файле имеются запретительные правила, то порядок следования строк приобретает значение &#8211; анализ идёт сверху вниз, и если вы попадёте под запретительное правило &#8211; до вашего разрешения вы уже не доберетесь<br />
host replication repusr 192.168.0.11/32 md5 # pgsql-slave.server</p>
<p># чтобы применились новые правила из pg_hba.conf, выполним команду (нужны sudo-привилегии):<br />
root@pgsql-master ~$: sudo systemctl reload postgresql<br />
[/cc]</p>
<p>После этого необходимо сходить на pgsql-slave.server, и сделать т.н. &#8220;<a href="https://postgrespro.ru/docs/postgrespro/9.6/app-pgbasebackup.html" rel="noopener" target="_blank">pg_basebackup</a>&#8221; &#8211; команду, которая автоматизирует за нас следующие действия:</p>
<ul>
<li>создание checkpoint&#8217;a (когда сервер флашит все изменения на диск и создает контрольную точку);</li>
<li>выполнение &#8220;pg_start_backup()&#8221; (в этот момент серверу сообщается о начале резервного копирования; создается checkpoint, метки начала, а все изменения в базе на это время будут писаться в WAL);</li>
<li>запуск копирования основной директории с данными на резервный сервер с помощью rsync/cp или любыми другими способами;</li>
<li>создание файла восстановления <a href="https://postgrespro.ru/docs/postgrespro/9.6/recovery-config.html" rel="noopener" target="_blank">recovery.conf</a> ;</li>
<li>выполнение &#8220;pg_stop_backup()&#8221; (сообщает серверу о том, что резервное копирование завершено, и можно продолжить работу в штатном режиме);</li>
</ul>
<p>Функционал &#8220;pg_basebackup&#8221; стал доступен начиная с версии 9.2, до этих пор процедура бэкапов и настройки репликации происходили по описанной выше схеме (подробнее <a href="https://postgrespro.ru/docs/postgrespro/9.6/continuous-archiving" rel="noopener" target="_blank">здесь</a>).<br />
Итак. На сервере pgsql-slave.server выполняем (подразумевается, что основная директория с данными располагается в /db/9.6/main ):</p>
<p>[cc lang=&#8221;bash&#8221;]<br />
root@pgsql-slave ~$: sudo systemctl stop postgresql<br />
root@pgsql-slave ~$: sudo rm -rf /db/9.6/main/*<br />
root@pgsql-slave ~$: su &#8211; postgres<br />
postgres@pgsql-slave ~$: pg_basebackup -P -R -X stream -c fast -h pgsql-master.server -U repusr -D /db/9.6/main<br />
postgres@pgsql-slave ~$: echo -e &#8220;recovery_target_timeline = &#8216;latest&#8217;\n# recovery_min_apply_delay = 10min \ntrigger_file = &#8216;/tmp/psql.trigger'&#8221; >> /db/9.6/main/recovery.conf<br />
root@pgsql-slave ~$: systemctl start postgresql<br />
[/cc]</p>
<p>Параметр &#8220;recovery_min_apply_delay = XX&#8221; позволяет настроить применение изменений из WAL-логов с задержкой на XX минут (часов, дней). Это быавет полезно, если вы любите дропать у себя таблички =)<br />
Параметр &#8220;trigger_file&#8221; позволит нашей реплике быстро стать мастером в случае необходимости: для этого надо всего лишь создать этот файл &#8211; и postgresql перестанет стримить WAL-логи с мастера, сам станет мастером и откроется на запись.</p>
<p>Проверить, что наша репликация работает, можно следующим образом:</p>
<p>[cc lang=&#8221;bash&#8221;]<br />
&#8212; (on slave &#8211; &#8220;t&#8221;, on master &#8211; &#8220;f&#8221;) SELECT pg_is_in_recovery();<br />
postgres=$ SELECT pg_is_in_recovery();<br />
# pg_is_in_recovery<br />
# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
# t<br />
# (1 row)</p>
<p>&#8212; (on slave, т.н. &#8220;лаг репликации&#8221;) SELECT now()-pg_last_xact_replay_timestamp();<br />
&#8212; если вы выставляли параметр &#8220;recovery_min_apply_delay&#8221;, то оно будет ~равно этому значению<br />
postgres=$ SELECT now()-pg_last_xact_replay_timestamp();<br />
# ?column?<br />
# &#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
# 00:00:00.021257<br />
# (1 row)</p>
<p>&#8212; (on master) SELECT * FROM pg_stat_replication;<br />
postgres=$ \x<br />
# Expanded display is on.<br />
postgres=$ SELECT * FROM pg_stat_replication;<br />
# -[ RECORD 1 ]&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
# pid | 507<br />
# usesysid | 27581<br />
# usename | repusr<br />
# application_name | walreceiver<br />
# client_addr | 192.168.0.11<br />
# client_hostname |<br />
# client_port | 54340<br />
# backend_start | 2017-06-16 20:34:43.342+03<br />
# backend_xmin |<br />
# state | streaming<br />
# sent_location | 3/9FABB8E0<br />
# write_location | 3/9FABB8E0<br />
# flush_location | 3/9FABB8E0<br />
# replay_location | 3/9FABB8A8<br />
# sync_priority | 0<br />
# sync_state | async[/cc]</p>
<p>Итог: у нас есть рабочая реплика. Таким способом можно цеплять любое (разумное) количество реплик к мастеру, не трогая при этом сам мастер &#8211; надо лишь следить, чтобы мы не выходили за рамки max_wal_senders.</p>
<p>Если понадобится из неё сделать мастера &#8211; достаточно создать trigger_file: в этот момент slave станет new_master&#8217;ом и позволит влить в себя пачку данных.<br />
При этом, файл recovery.conf переименуется в recovery.done, а trigger_file будет удален автоматически, как только слейв почувствует себя мастером.</p>
<p><strong>ВАЖНО:</strong> стоит следить &#8211; чтобы не был запущен прежний &#8220;old_master&#8221;, в противном случае вы рискуете получить жёсткий рассинхрон.<br />
Процедура возврата old_master -> master будет состоять из шагов:</p>
<ul>
<li>удалить папку с данными на old_master;</li>
<li>сделать old_master репликой к new_master (создать пользователя, выполнить pg_basebackup);</li>
<li>остановить new_master (бывший слейв), и переименовать обратно recovery.done > recovery.conf;</li>
<li>запустить postgresql на old_master;</li>
</ul>
<p>Если всё прошло без ошибок &#8211; таким образом мы получим картину, которая была до создания trigger_file; &#8220;удобно&#8221;, конечно &#8211; но что поделать <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h2>Резервное копирование и восстановление</h2>
<p>Существует 3 основных способа, как можно делать резервные копии:</p>
<ul>
<li>использовать классические SQL-дампы нужных таблиц или баз данных;</li>
<li>использовать периодическое резервное копирование средствами pg_dump/pg_dumpall;</li>
<li>использовать резервное копирование на основе базовых копий и архивов WAL.</li>
</ul>
<p>Первый вариант полезен для проверки консистентности данных (дамп не сделается, если нарушена связность в бд), но нам не подходит.<br />
Второй вариант также не подходит: выполнение pg_dump не блокирует мастера, но создает довольно высокую нагрузку на дисковую подсистему и, главное, не позволяет выполнить Point-In-Time Recovery (PITR).<br />
Поэтому мы будем использовать третий подход.</p>
<p>По своей сущности, он ничем не отличается от процедуры настройки реплики, описанной выше: бэкап с возможностью восстановления на момент во времени == pg_basebackup + пачка WAL-логов, начиная с момента создания бэкапа.<br />
Это можно делать с использованием самописных скриптов, или с использованием утилиты barman (http://www.pgbarman.org/).<br />
Barman &#8211; это всего лишь python-обвязка над всеми теми же действиями и функциями postgresql, но оформленными в довольно удобный инструмент.</p>
<p>Итак. Для приготовления нам понадобятся:</p>
<ul>
<li>сервер с достаточным количеством диска, на котором будет работать barman, 1шт;</li>
<li>сервер для проверки наших резервных копий, 1шт;</li>
<li>новые пользователи в базе с нужными привилегиями, 2шт;</li>
<li>новые записи в pg_hba.conf для этих пользователей, по вкусу.</li>
</ul>
<p>На сервер с barman&#8217;ом устанавливаем:</p>
<ul>
<li>postgresql-client</li>
<li>postgresql-client-common</li>
<li>postgresql-client-9.6 (версия должна совпадать с той, что стоит на нашем сервере БД)</li>
<li>barman (версия 2+)</li>
</ul>
<p>На сервер для проверок резервных копий устанавливаем:</p>
<ul>
<li>postgresql-9.6</li>
<li>postgresql-common</li>
<li>postgresql-client-common</li>
<li>postgresql-client-9.6 (версия должна совпадать с той, что стоит на нашем сервере БД)</li>
<li>barman (версия 2+)</li>
<li>postgresql-contrib-9.6</li>
<li>python-psycopg2</li>
</ul>
<p>Далее.<br />
На master-базе (которую мы хотим бэкапить) создадим новых пользователей, и добавим их в pg_hba.conf.<br />
Для корректной работы barman нам понадобятся 2 пользователя: &#8220;barman&#8221; (должен быть суперюзером) и &#8220;streaming_barman&#8221; (пользователь для стриминга WAL-логов, достаточно привилегий REPLICATION):</p>
<p>[cc lang=&#8221;bash&#8221;]<br />
# добавим новых пользоавтелей в pg_hba.conf на сервере:<br />
host postgres barman 192.168.0.12/32 md5 # pgsql-barman.server<br />
host replication streaming_barman 192.168.0.12/32 md5 # pgsql-barman.server</p>
<p># из-под пользователя &#8220;postgres&#8221;, в psql-консоли:<br />
# как сделать правильный MD5-hash написано выше<br />
postgres=$ BEGIN;<br />
postgres=$ CREATE ROLE barman;<br />
postgres=$ CREATE ROLE streaming_barman;<br />
postgres=$ ALTER ROLE barman WITH SUPERUSER NOCREATEDB NOCREATEROLE LOGIN PASSWORD &#8216;md567e47ea958fcd33af11cb8fb8d3ecad1&#8217;;<br />
postgres=$ ALTER ROLE streaming_barman WITH LOGIN REPLICATION PASSWORD &#8216;md5ce13788c9e6d33c997a5723aecb742a6&#8217;;<br />
postgres=$ COMMIT;<br />
postgres=$<br />
postgres=$ SELECT pg_reload_conf();<br />
[/cc]</p>
<p>Если мы всё сделали правильно, то теперь barman должен уметь ходить в нашу БД. Самое время настроить его для создания бэкапов.<br />
Идём на сервер pgsql-barman.server и настраиваем конфигурационную секцию для нашего сервера. Напомню, что мы хотим схему &#8220;pg_basebackup + streaming WAL&#8221;.<br />
[cc lang=&#8221;bash&#8221;]<br />
#<br />
# создаём файл следующего содержания в /etc/barman.d/pgsql-master.conf из-под пользоавтеля &#8220;root&#8221; (в этой директории уже есть подходящие шаблоны конфигов, в т.ч. для streaming replication)<br />
# обратите внимание: название секции в конфигурационном файле и название самого файла совпадают &#8211; это идентификатор, по которому barman будет работать с вашим сервером.<br />
#<br />
#192.168.0.10 &#8211; это адрес нашего сервера с PostgreSQL<br />
root@pgsql-barman ~$: cat /etc/barman.d/pgsql-master.conf<br />
; Barman, Backup and Recovery Manager for PostgreSQL<br />
; http://www.pgbarman.org/ &#8211; http://www.2ndQuadrant.com/<br />
;<br />
; Template configuration file for a server using<br />
; only streaming replication protocol<br />
;</p>
<p>[pgsql-master]<br />
description = &#8220;pgsql-master.server&#8221;<br />
conninfo = host=192.168.0.10 user=barman dbname=postgres<br />
streaming_conninfo = host=192.168.0.10 user=streaming_barman<br />
backup_method = postgres<br />
streaming_archiver = on<br />
slot_name = barman<br />
retention_policy = RECOVERY WINDOW OF 7 DAYS<br />
minimum_redundancy = 5<br />
[/cc]</p>
<p>[cc lang=&#8221;bash&#8221;]<br />
#<br />
# создаем в домашней директории пользователя &#8220;barman&#8221; файлик .pgpass, кот. будет содержать информацию по подключениям к нашим серверам<br />
# BE AWARE: лучше всего, чтобы этот файл должен быть с правами &#8220;только на чтение&#8221;, а сам сервер pgsql-barman.server должен быть надёжно защищен<br />
# т.к. в этом файле пароли хранятся в открытом виде, а созданный нами в базе пользователь &#8220;barman&#8221; имееть привилегии SUPERUSER<br />
# формат этого файла следующий: сервер:порт:база_данных:имя_пользователя:пароль<br />
# допускается использование шаблона &#8216;*&#8217;<br />
#<br />
barman@pgsql-barman ~$: cat .pgpass<br />
192.168.0.10:5432:postgres:barman:PASSWORDbarman<br />
192.168.0.10:5432:*:streaming_barman:PASSWORDstreaming_barman</p>
<p>barman@pgsql-barman ~$: ls -la ~/.pgpass<br />
-r&#8212;&#8212;&#8211; 1 barman barman 329 Jun 14 10:27 /var/lib/barman/.pgpass<br />
[/cc]<br />
[cc lang=&#8221;bash&#8221;]<br />
#<br />
# проверяем, что созданные нами пользователи имеют все необходимые привилегии и доступы (выполняем команды из-под пользователя &#8220;barman&#8221;):<br />
#<br />
barman@pgsql-barman ~$: psql -c &#8216;SELECT version()&#8217; -U barman -h 192.168.0.10 postgres<br />
# version<br />
# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
# PostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609, 64-bit<br />
# (1 row)</p>
<p>barman@pgsql-barman ~$: psql -U streaming_barman -h 192.168.0.10 -c &#8220;IDENTIFY_SYSTEM&#8221; replication=1<br />
# systemid | timeline | xlogpos | dbname<br />
# &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;<br />
# 6429565456649844276 | 1 | 8/C9E37B8 |<br />
# (1 row)<br />
[/cc]<br />
[cc lang=&#8221;bash&#8221;]<br />
#<br />
# создадим слот для репликации, и запустим стриминг WAL-логов<br />
#<br />
barman@pgsql-barman ~$: barman receive-wal &#8211;create-slot pgsql-master<br />
barman@pgsql-barman ~$: barman receive-wal pgsql-master<br />
[/cc]<br />
[cc lang=&#8221;bash&#8221;]<br />
#<br />
# теперь нам осталось проверить статус сервера, и мы сможем запустить бэкап<br />
#<br />
barman@pgsql-barman ~$: barman check pgsql-master<br />
# Server pgsql-master:<br />
# PostgreSQL: OK<br />
# superuser: OK<br />
# PostgreSQL streaming: OK<br />
# wal_level: OK<br />
# replication slot: OK<br />
# directories: OK<br />
# retention policy settings: OK<br />
# backup maximum age: OK (no last_backup_maximum_age provided)<br />
# compression settings: OK<br />
# failed backups: OK (there are 0 failed backups)<br />
# minimum redundancy requirements: FAILED (have 1 backups, expected at least 5)<br />
# pg_basebackup: OK<br />
# pg_basebackup compatible: OK<br />
# pg_basebackup supports tablespaces mapping: OK<br />
# pg_receivexlog: OK<br />
# pg_receivexlog compatible: OK<br />
# receive-wal running: OK<br />
# archiver errors: OK</p>
<p>barman@pgsql-barman ~$: barman backup pgsql-master<br />
# Starting backup using postgres method for server pgsql-master in /var/lib/barman/pgsql-master/base/20170620T153138<br />
# Backup start at xlog location: 3/B3D45640 (0000000100000003000000B3, 00D45640)<br />
# Copying files.<br />
# Copy done.<br />
# Finalising the backup.<br />
# WARNING: pg_basebackup does not copy the PostgreSQL configuration files that reside outside PGDATA. Please manually backup the following files:<br />
# /etc/postgresql/9.6/main/postgresql.conf<br />
# /etc/postgresql/9.6/main/pg_hba.conf<br />
# /etc/postgresql/9.6/main/pg_ident.conf<br />
# Backup size: 187.7 MiB<br />
# Backup end at xlog location: 3/B5000000 (0000000100000003000000B4, 00000000)<br />
# Backup completed</p>
<p>barman@pgsql-barman ~$: barman list-backup pgsql-master<br />
# pgsql-master 20170620T153138 &#8211; Tue Jun 20 15:31:38 2017 &#8211; Size: 203.7 MiB &#8211; WAL Size: 0 B</p>
<p>barman@pgsql-barman ~$: barman show-backup pgsql-master 20170620T153138<br />
# Backup 20170620T153138:<br />
# Server Name : pgsql-master<br />
# Status : DONE<br />
# PostgreSQL Version : 90603<br />
# PGDATA directory : /db/9.6/main<br />
# Base backup information:<br />
# Disk usage : 187.7 MiB (203.7 MiB with WALs)<br />
# Incremental size : 187.7 MiB (-0.00%)<br />
# Timeline : 1<br />
# Begin WAL : 0000000100000003000000B4<br />
# End WAL : 0000000100000003000000B4<br />
# WAL number : 1<br />
# Begin time : 2017-06-20 12:35:02+00:00<br />
# End time : 2017-06-20 15:31:38.593898+03:00<br />
# Begin Offset : 11299552<br />
# End Offset : 0<br />
# Begin XLOG : 3/B4AC6AE0<br />
# End XLOG : 3/B5000000<br />
# WAL information:<br />
# No of files : 0<br />
# Disk usage : 0 B<br />
# Last available : 0000000100000003000000B4<br />
# Catalog information:<br />
# Retention Policy : VALID<br />
# Previous Backup : 20170619T172911<br />
# Next Backup : &#8211; (this is the latest base backup)<br />
[/cc]</p>
<p>Вот мы и сделали бэкап, cool. Можем поставить эту команду в crontab, и делать бэкапы по расписанию. Вот толку от них будет немного, если мы не сможем из них восстановиться.</p>
<p>Чтобы этого избежать, мы будем регулярно восстанавливаться из нашего бэкапа на отдельном сервере. Делать это можно тоже по крону.<br />
Только предварительно надо выполнить следующие действия:</p>
<ul>
<li>создать ssh-ключ пользвателю &#8220;barman&#8221;, чтобы он мог ходить на сервер для восстановления без пароля;</li>
<li>добавить публичную часть ключа в .ssh/authorized_keys пользователю &#8220;postgres&#8221; на сервере для восстановления;</li>
<li>добавить пользователю &#8220;postgres&#8221; привилегии для старта/стопа/проверки статуса postgresql.</li>
</ul>
<p>[cc lang=&#8221;bash&#8221;]<br />
#<br />
# на сервере pgsql-barman.server, из-под пользователя &#8220;barman&#8221;<br />
#<br />
barman@pgsql-barman ~$: ssh-keygen -t rsa<br />
Generating public/private rsa key pair.<br />
Enter file in which to save the key (/home/barman/.ssh/id_rsa):<br />
Created directory &#8216;/home/barman/.ssh&#8217;.<br />
Enter passphrase (empty for no passphrase):<br />
Enter same passphrase again:<br />
Your identification has been saved in /home/barman/.ssh/id_rsa.<br />
Your public key has been saved in /home/barman/.ssh/id_rsa.pub.<br />
The key fingerprint is:<br />
SHA256:npqoTQYiASIKYeL1EZeDkBIQy0MG/lTXg3ngsSliAgE barman@pgsql-barman<br />
The key&#8217;s randomart image is:<br />
+&#8212;[RSA 2048]&#8212;-+<br />
|EO.oo+o=* |<br />
|/o..o.==++ |<br />
|+*.+ o +o . |<br />
| .* . . |<br />
|o .. S |<br />
|.. . . . |<br />
| o o |<br />
| + . o |<br />
| ..o o |<br />
+&#8212;-[SHA256]&#8212;&#8211;+</p>
<p>barman@pgsql-barman ~$: cat .ssh/id_rsa.pub<br />
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEXvb9WLCIS9Lkxb9MENOXl1Uvv+nqpIkvdx38zp7/h68maLCqDFXMfXciR8j1pS7xbtOgvjzxfAxZ4MAiqRfDq/PNwjiI3Bi+ZDrwRkUeQ4GBuwl99uVTnaa6qkTBZa4BKMZNnYhuAB8ZhhJ/r7TqwN+duch7cxt1Vc9O2zwJJE85doS3DZAO+cjoXuONgDLuF9p4w1A4NIhG9KxAgkLCwvjrvowhTB6zv8PJk7UKEUtgVSdpRDmS5g9OhSyzXZ7nrfHM96qheJgB0jSGOTMVo3UTpZ7orqEqR40QcHiMsiTEocRhzEiphPh82/3leOBtMhhvoJ3gT3j+XEalOOz9 barman@pgsql-barman<br />
[/cc]<br />
[cc lang=&#8221;bash&#8221;]<br />
#<br />
# на сервере pgsql-verify.server, из-под пользователя &#8220;postgres&#8221;<br />
# так же, сразу добавим необходимые sudo-привилегии этому пользователю в sudoers (из-под пользователя &#8220;root&#8221;)<br />
#<br />
postgres@pgsql-verify ~$: install -m 700 -d ~/.ssh &#038;&#038; echo -n &#8216;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEXvb9WLCIS9Lkxb9MENOXl1Uvv+nqpIkvdx38zp7/h68maLCqDFXMfXciR8j1pS7xbtOgvjzxfAxZ4MAiqRfDq/PNwjiI3Bi+ZDrwRkUeQ4GBuwl99uVTnaa6qkTBZa4BKMZNnYhuAB8ZhhJ/r7TqwN+duch7cxt1Vc9O2zwJJE85doS3DZAO+cjoXuONgDLuF9p4w1A4NIhG9KxAgkLCwvjrvowhTB6zv8PJk7UKEUtgVSdpRDmS5g9OhSyzXZ7nrfHM96qheJgB0jSGOTMVo3UTpZ7orqEqR40QcHiMsiTEocRhzEiphPh82/3leOBtMhhvoJ3gT3j+XEalOOz9 barman@pgsql-barman&#8217; > .ssh/authorized_keys &#038;&#038; chmod 600 ~/.ssh/authorized_keys<br />
#<br />
root@pgsql-verify ~$: echo &#8216;%postgres ALL=(ALL) NOPASSWD: /usr/sbin/service postgresql stop ,/usr/sbin/service postgresql start&#8217; > /etc/sudoers.d/barman<br />
[/cc]<br />
[cc lang=&#8221;bash&#8221;]<br />
#<br />
# проверяем. пробуем зайти по ssh: barman@pgsql-barman.server -> postgres@pgsql-verify.server (должно пускать без проблем)<br />
#<br />
barman@pgsql-barman ~$: ssh postgres@pgsql-verify.server<br />
[/cc]<br />
<strong>ВАЖНО:</strong> на вашем сервере для проверок <strong><em>уже должны быть конфигурационные файлы</em></strong>, поскольку barman не копирует их при создании резервной копии базы &#8211; он об этом явно пишет в своём выводе:<br />
[cc]<br />
WARNING: pg_basebackup does not copy the PostgreSQL configuration files that reside outside PGDATA. Please manually backup the following files:<br />
/etc/postgresql/9.6/main/postgresql.conf<br />
/etc/postgresql/9.6/main/pg_hba.conf<br />
/etc/postgresql/9.6/main/pg_ident.conf<br />
[/cc]<br />
Лучше всего скопировать их с вашего pgsql-master.server (только не забудьте подправить параметр &#8216;listen_addresses&#8217; и вписать в него адрес сервера pgsql-verify.server)</p>
<p>Теперь у нас есть всё, что необходимо для восстановления бэкапа на сервере для проверок.<br />
Само восстановление представляет из себя следующую последовательность действий:</p>
<ul>
<li>остановить postgresql на сервере;</li>
<li>удалить все данные из PGDATA;</li>
<li>запустить barman recover;</li>
<li>запустить postgresql на сервере;</li>
<li>проверить, что сервер поднялся и готов обрабатывать запросы.</li>
</ul>
<p>Команда восстановления на заданный Point-In-Time выглядит так:</p>
<p>[cc lang=&#8221;bash&#8221;]barman recover &#8211;target-time &#8220;2017-06-19 16:08:00&#8221; &#8211;remote-ssh-command &#8220;ssh postgres@pgsql-verify.server&#8221; pgsql-master latest /db/9.6/main[/cc]</p>
<p>параметры означают следующее:<br />
[cc]<br />
&#8211;target-time            |  желаемый Point-In-Time, формат:   date +&#8217;%Y-%m-%d %H:%M:%S&#8217;<br />
&#8211;remote-ssh-comand      |  команда для доступа на сервер, в нашем примере: &#8220;ssh postgres@pgsql-verify.server&#8221;<br />
<server-id> <backup-id>  |  получается из вывода `barman list-backup`, в нашем примере: pgsql-master latest<br />
<targed-path>            |  путь к директории, в которую следует восстанавливать бэкап, в нашем примере: /db/9.6/<br />
[/cc]</p>
<p>Поскольку мы настроили доступ по ssh для пользователя barman, мы можем всё это сделать удаленно. Выглядит это примерно так:</p>
<p>[cc lang=&#8221;bash&#8221;]<br />
/usr/bin/ssh -o ConnectTimeout=4 -o PubkeyAuthentication=yes -o PasswordAuthentication=no postgres@pgsql-verify.server &#8216;/usr/bin/sudo /usr/sbin/service postgresql stop&#8217;<br />
/usr/bin/ssh -o ConnectTimeout=4 -o PubkeyAuthentication=yes -o PasswordAuthentication=no postgres@pgsql-verify.server &#8216;/usr/sbin/service postgresql status&#8217;<br />
/usr/bin/ssh -o ConnectTimeout=4 -o PubkeyAuthentication=yes -o PasswordAuthentication=no postgres@pgsql-verify.server &#8216;/bin/rm -rf /db/9.6/main/*&#8217;<br />
/usr/bin/barman recover &#8211;target-time &#8220;2017-06-19 16:08:00&#8221; &#8211;remote-ssh-command &#8220;ssh postgres@pgsql-verify.server&#8221; pgsql-master latest /db/9.6/main<br />
/usr/bin/ssh -o ConnectTimeout=4 -o PubkeyAuthentication=yes -o PasswordAuthentication=no postgres@pgsql-verify.server &#8216;/usr/bin/sudo /usr/sbin/service postgresql start&#8217;<br />
/usr/bin/ssh -o ConnectTimeout=4 -o PubkeyAuthentication=yes -o PasswordAuthentication=no postgres@pgsql-verify.server &#8216;/usr/sbin/service postgresql status'[/cc]</p>
<p>NB: в случае, когда вы восстанавливаете бэкап с timestamp&#8217;ом, сильно отличным от текущего &#8211; может потребоваться после завершения восстановления выполнить на сервере в psql из-под пользователя &#8220;postgres&#8221; команду<br />
[cc lang=&#8221;bash&#8221;]SELECT pg_xlog_replay_resume();[/cc]</p>
<p>Это всё.<br />
Можно это дело обернуть в скрипт и так же запускать по крону, после того как бэкап снимается.</p>
<p>The post <a href="https://nixman.info/?p=2828">Репликация PostgreSQL</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2828</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Мониторинг с помощью RPM probe в Juniper</title>
		<link>https://nixman.info/?p=2826</link>
					<comments>https://nixman.info/?p=2826#comments</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Wed, 17 Jan 2018 07:33:23 +0000</pubDate>
				<category><![CDATA[Hard]]></category>
		<category><![CDATA[ipsla]]></category>
		<category><![CDATA[juniper]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[rpm]]></category>
		<category><![CDATA[sla]]></category>
		<category><![CDATA[test]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2826</guid>

					<description><![CDATA[<p>Многие знают, что в Cisco есть такая удобная штука, как IP SLA. Она позволяет прямо с устройства запускать различные тесты (icmp, tcp, udp), и на основании их совершать какие-то действия &#8211; например, переключать роуты. Как использовать IP SLA для переключения каналов на роутере, можно почитать на замечательном сайте LinkMeUp (кстати, рекомендую весь цикл &#8220;Сети для&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2826">Мониторинг с помощью RPM probe в Juniper</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Многие знают, что в Cisco есть такая удобная штука, как IP SLA. Она позволяет прямо с устройства запускать различные тесты (icmp, tcp, udp), и на основании их совершать какие-то действия &#8211; например, переключать роуты.<br />
Как использовать IP SLA для переключения каналов на роутере, можно почитать на замечательном сайте <a href="http://linkmeup.ru/blog/65.html" target="_blank" rel="noopener noreferrer">LinkMeUp</a> (кстати, рекомендую весь цикл &#8220;Сети для самых маленьких&#8221;, узнаете много нового).</p>
<p>Ну а мы будем настраивать аналог IP SLA в Juniper, и называется он RPM (Realtime Perfomance Monitoring)</p>
<p><span id="more-2826"></span></p>
<h2>1. Что есть что</h2>
<p>У нас есть пробы и тесты.<br />
Проба &#8211; это, собственно, метрика, которую мы будем снимать. ICMP, UDP и т.д. Проба посылается на удалённый хост и отправляет ответ. Разумеется, если мы проверяем не просто ICMP, а udp/tcp-порт, то на удалённом хосте должен быть настроен респондер &#8211; причём вовсе не обязательно это должен быть такой же Juniper, может быть и обычный веб-сервер, если мы проверяем http url.</p>
<p>Поддерживаемые типы проб:</p>
<ul>
<li>HTTP GET request at a target URL</li>
<li>HTTP GET request for metadata at a target URL</li>
<li>ICMP echo request to a target address (the default)</li>
<li>ICMP timestamp request to a target address</li>
<li>UDP ping packets to a target device</li>
<li>UDP timestamp requests to a target address</li>
<li>TCP ping packets to a target device</li>
</ul>
<p>Тест &#8211; это проба, запущенная в нужном количестве с нужным интервалом и параметрами (типа source port или next-hop). По каждому тесту можно посмотреть результат и статистику.</p>
<h2>Давайте уже что-нибудь запустим</h2>
<p>Настройка RPM довольно простая. Например, вот так выглядит простой icmp-тест<br />
[cc]<br />
set services rpm probe BRANCH test ICMP-PROBE probe-type icmp-ping<br />
set services rpm probe BRANCH test ICMP-PROBE target address 172.27.1.17<br />
set services rpm probe BRANCH test ICMP-PROBE probe-count 5<br />
set services rpm probe BRANCH test ICMP-PROBE probe-interval 5<br />
set services rpm probe BRANCH test ICMP-PROBE test-interval 5<br />
set services rpm probe BRANCH test ICMP-PROBE thresholds successive-loss 5<br />
set services rpm probe BRANCH test ICMP-PROBE destination-interface st0.4<br />
[/cc]</p>
<p>&#8220;Как же так?&#8221; &#8211; спросите вы. Ведь мы только что договорились, что проба &#8211; это часть теста, а тут получается наоборот. Я не знаю, чем руководствовались разработчики JunOS, но в данном случае после probe идёт имя PROBE_OWNER &#8211; т.е. например роутер в филиале, к которому запускаются несколько тестов, или клиент, которого мы хотим мониторить. Немного путано, но так вот есть.</p>
<p>Параметры теста можно посмотреть в документации (там почти два десятка параметров). Также в этой же ветке (services rpm) можно настроить ответную часть пробы.</p>
<h2>Что в результате?</h2>
<p>Смотреть статистику по пробам можно вот так (можно все тесты указанного OWNER, можно только выбранного теста):<br />
[cc]<br />
root@srx340-01> show services rpm probe-results owner BRANCH<br />
    Owner: BRANCH, Test: ICMP-PROBE<br />
    Target address: 172.27.1.17, Probe type: icmp-ping<br />
    Destination interface name: st0.4<br />
    Test size: 5 probes<br />
    Probe results:<br />
      Response received, Thu Jan 11 08:38:38 2018, No hardware timestamps<br />
      Rtt: 12362 usec, Round trip jitter: -1450 usec, Round trip interarrival jitter: 1797 usec<br />
    Results over current test:<br />
      Probes sent: 5, Probes received: 5, Loss percentage: 0.000000<br />
      Measurement: Round trip time<br />
        Samples: 5, Minimum: 12362 usec, Maximum: 13886 usec, Average: 12975 usec, Peak to peak: 1524 usec, Stddev: 714 usec, Sum: 64876 usec<br />
      Measurement: Positive round trip jitter<br />
        Samples: 2, Minimum: 1426 usec, Maximum: 1456 usec, Average: 1441 usec, Peak to peak: 30 usec, Stddev: 15 usec, Sum: 2882 usec<br />
      Measurement: Negative round trip jitter<br />
        Samples: 3, Minimum: 436 usec, Maximum: 1500 usec, Average: 1129 usec, Peak to peak: 1064 usec, Stddev: 490 usec, Sum: 3386 usec<br />
    Results over last test:<br />
      Probes sent: 5, Probes received: 5, Loss percentage: 0.000000<br />
      Test completed on Thu Jan 11 08:38:38 2018<br />
      Measurement: Round trip time<br />
        Samples: 5, Minimum: 12362 usec, Maximum: 13886 usec, Average: 12975 usec, Peak to peak: 1524 usec, Stddev: 714 usec, Sum: 64876 usec<br />
      Measurement: Positive round trip jitter<br />
        Samples: 2, Minimum: 1426 usec, Maximum: 1456 usec, Average: 1441 usec, Peak to peak: 30 usec, Stddev: 15 usec, Sum: 2882 usec<br />
      Measurement: Negative round trip jitter<br />
        Samples: 3, Minimum: 436 usec, Maximum: 1500 usec, Average: 1129 usec, Peak to peak: 1064 usec, Stddev: 490 usec, Sum: 3386 usec<br />
    Results over all tests:<br />
      Probes sent: 981160, Probes received: 980587, Loss percentage: 0.058400<br />
      Measurement: Round trip time<br />
        Samples: 980587, Minimum: 9317 usec, Maximum: 994921 usec, Average: 14290 usec, Peak to peak: 985604 usec, Stddev: 10607 usec, Sum: 14012472325 usec<br />
      Measurement: Positive round trip jitter<br />
        Samples: 491354, Minimum: 0 usec, Maximum: 983440 usec, Average: 4496 usec, Peak to peak: 983440 usec, Stddev: 11249 usec, Sum: 2209222966 usec<br />
      Measurement: Negative round trip jitter<br />
        Samples: 489232, Minimum: 1 usec, Maximum: 983726 usec, Average: 4516 usec, Peak to peak: 983725 usec, Stddev: 11274 usec, Sum: 2209221859 usec<br />
[/cc]</p>
<h2>А какой с этого прок?</h2>
<p>IP SLA хорош тем, что позволяет на основе результатов проб выполнять различные действия &#8211; в т.ч. включать или выключать маршруты. В Juniper тоже есть такая функция, называется IP monitoring.<br />
Настраивается вот так:<br />
[cc]<br />
set services rpm probe BRANCH test ICMP-PROBE probe-type icmp-ping<br />
set services rpm probe BRANCH test ICMP-PROBE target address 8.8.8.8<br />
set services rpm probe BRANCH test ICMP-PROBE probe-count 5<br />
set services rpm probe BRANCH test ICMP-PROBE probe-interval 5<br />
set services rpm probe BRANCH test ICMP-PROBE test-interval 5<br />
set services rpm probe BRANCH test ICMP-PROBE thresholds successive-loss 5<br />
set services rpm probe BRANCH test ICMP-PROBE next-hop 192.168.1.1<br />
set services ip-monitoring policy ISP-CHECK match rpm-probe BRANCH<br />
set services ip-monitoring policy ISP-CHECK then preferred-route route 0.0.0.0/0 next-hop 192.168.2.1<br />
[/cc]<br />
Т.е. если группа тестов возвращает fail, то происходит переключение. Как только проба восстанавливается, возвращается и &#8220;нормальный&#8221; маршрут.</p>
<p>Выглядеть это будет примерно так:<br />
[cc]<br />
root@srx340-01> show services ip-monitoring status </p>
<p>Policy &#8211; ISP-CHECK (Status: PASS)<br />
  RPM Probes:<br />
    Probe name             Test Name       Address          Status<br />
    &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;<br />
    BRANCH                   ICMP-PROBE      8.8.8.8          PASS<br />
  Route-Action:<br />
    route-instance    route             next-hop         state<br />
    &#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;-<br />
    inet.0            0.0.0.0/0         192.168.2.1   NOT-APPLIED  </p>
<p>[/cc]</p>
<p>Посмотреть последние переключения:<br />
[cc]root@srx340-01> show services rpm history-results<br />
Owner, Test            Probe received             Round trip time<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:04 2018     1753 usec<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:06 2018     7318 usec<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:07 2018     1891 usec<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:09 2018     7575 usec<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:11 2018     1695 usec<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:13 2018   Internal error<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:15 2018   Internal error<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:18 2018   Internal error<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:20 2018   Internal error<br />
BRANCH, ICMP-PROBE     Mon Jan 15 14:30:22 2018   Internal error<br />
[/cc]</p>
<p>На этом, собственно, всё. Спасибо за внимание <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>The post <a href="https://nixman.info/?p=2826">Мониторинг с помощью RPM probe в Juniper</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2826</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Juniper SRX и Libreswan (и ещё StrongSwan)</title>
		<link>https://nixman.info/?p=2816</link>
					<comments>https://nixman.info/?p=2816#comments</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Thu, 14 Dec 2017 15:32:02 +0000</pubDate>
				<category><![CDATA[Hard]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[ipsec]]></category>
		<category><![CDATA[juniper]]></category>
		<category><![CDATA[libreswan]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[storngswan]]></category>
		<category><![CDATA[vpn]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2816</guid>

					<description><![CDATA[<p>Тема ipsec в этом блоге поднимается часто, особенно в последнее время. Это и неудивительно &#8211; мне по работе частенько приходится объединять разные роутеры и виртуалки через IPSec (например, Mikrotik и libreswan, Mikrotik и Juniper, или Juniper и Cisco). А теперь мы попробуем ещё одну связку &#8211; Juniper SRX и linux-виртуалку. В качестве ipsec-демона будем использовать&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2816">Juniper SRX и Libreswan (и ещё StrongSwan)</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Тема ipsec в этом блоге поднимается часто, особенно в последнее время. Это и неудивительно &#8211; мне по работе частенько приходится объединять разные роутеры и виртуалки через IPSec (например, <a href="https://nixman.info/?p=2633" rel="noopener" target="_blank">Mikrotik и libreswan</a>, <a href="https://nixman.info/?p=2604" rel="noopener" target="_blank">Mikrotik и Juniper</a>, или <a href="https://nixman.info/?p=2356" rel="noopener" target="_blank">Juniper и Cisco</a>).</p>
<p>А теперь мы попробуем ещё одну связку &#8211; Juniper SRX и linux-виртуалку. В качестве ipsec-демона будем использовать Libreswan и Strongswan (кому что больше нравится).</p>
<p>Итак, поехали!<br />
<span id="more-2816"></span></p>
<p>Для начала сконфигурирем наш SRX. Я использую последний доступный софт из ветки 15.1X49: JUNOS 15.1X49-D120.3. Связано это с тем, что связка IKEv2+Traffic selectors не работает на более младшем софте, а без IKEv2 у меня не получилось запустить туннель из-за NAT. Предполагаается, что у SRX есть белый статический адрес.<br />
[cc]<br />
set security ike policy IKE-NIXMAN mode main<br />
set security ike policy IKE-NIXMAN proposals MD5-AES128-2-86400<br />
set security ike policy IKE-NIXMAN pre-shared-key ascii-text &#8220;$9$vW38-wgoZk.569RclKx7.Pf5Q369tuBR/CX-b2JZfTzF9pEcyKWXRE87&#8221;<br />
set security ike gateway GW-NIXMAN ike-policy IKE-NIXMAN<br />
set security ike gateway GW-NIXMAN address 1.2.3.4<br />
set security ike gateway GW-NIXMAN external-interface ge-0/0/0.0<br />
set security ike gateway GW-NIXMAN version v2-only<br />
set security ipsec vpn VPN-NIXMAN bind-interface st0.1<br />
set security ipsec vpn VPN-NIXMAN ike gateway GW-NIXMAN<br />
set security ipsec vpn VPN-NIXMAN ike ipsec-policy MD5-AES128-3600-2-policy<br />
set security ipsec vpn VPN-NIXMAN traffic-selector TS-01 local-ip 10.0.0.0/8<br />
set security ipsec vpn VPN-NIXMAN traffic-selector TS-01 remote-ip 172.16.43.254/32<br />
set security ipsec vpn VPN-NIXMAN establish-tunnels immediately</p>
<p>set security ike proposal MD5-AES128-2-86400 description ike-phase1-proposal1<br />
set security ike proposal MD5-AES128-2-86400 authentication-method pre-shared-keys<br />
set security ike proposal MD5-AES128-2-86400 dh-group group2<br />
set security ike proposal MD5-AES128-2-86400 authentication-algorithm md5<br />
set security ike proposal MD5-AES128-2-86400 encryption-algorithm aes-128-cbc<br />
set security ike proposal MD5-AES128-2-86400 lifetime-seconds 86400<br />
set security ike policy IKE-NIXMAN proposals MD5-AES128-2-86400</p>
<p>set security ipsec proposal MD5-AES128-3600 description ipsec-phase2-proposal<br />
set security ipsec proposal MD5-AES128-3600 protocol esp<br />
set security ipsec proposal MD5-AES128-3600 authentication-algorithm hmac-md5-96<br />
set security ipsec proposal MD5-AES128-3600 encryption-algorithm aes-128-cbc<br />
set security ipsec proposal MD5-AES128-3600 lifetime-seconds 3600<br />
set security ipsec policy MD5-AES128-3600-2-policy description ipsec-phase2-policy<br />
set security ipsec policy MD5-AES128-3600-2-policy perfect-forward-secrecy keys group2<br />
set security ipsec policy MD5-AES128-3600-2-policy proposals MD5-AES128-3600<br />
[/cc]</p>
<p>Здесь 1.2.3.4 &#8211; адрес удалённого пира<br />
10.0.0.0/8 &#8211; сеть на нашей стороне<br />
172.16.43.254/32 &#8211; сеть на удалённой стороне<br />
Шифрование можно выбрать и посильнее, но тут надо учитывать </p>
<p>Конфигурация удалённого пира (в случае libreswan) будет следующая (/etc/ipsec.d/nixman.conf):<br />
[cc]<br />
conn srx<br />
     authby=secret<br />
     auto=start<br />
     type=tunnel<br />
     esp=aes128-md5;modp1024<br />
     ike=aes128-md5;modp1024<br />
     ikelifetime=86400s<br />
     keylife=3600s<br />
     rekey=no<br />
     dpddelay=30<br />
     dpdtimeout=120<br />
     dpdaction=clear<br />
     fragmentation=yes<br />
     ikev2=insist<br />
     narrowing=yes<br />
     leftid=1.2.3.4<br />
     left=172.16.43.254<br />
     leftsourceip=172.16.43.254<br />
     right=4.3.2.1<br />
     leftsubnet=172.16.43.254/32<br />
     rightsubnet=10.0.0.0/8<br />
[/cc]</p>
<p>Наша виртуалка располагается за NAT, и имеет адрес 172.16.43.254 (что мы и указываем).<br />
Если бы у нас была виртуалка с честным белым адресом, конфиг выглядел бы чуть-чуть иначе :<br />
[cc]<br />
conn srx<br />
     authby=secret<br />
     auto=start<br />
     type=tunnel<br />
     esp=aes128-md5;modp1024<br />
     ike=aes128-md5;modp1024<br />
     ikelifetime=86400s<br />
     keylife=3600s<br />
     rekey=no<br />
     dpddelay=30<br />
     dpdtimeout=120<br />
     dpdaction=clear<br />
     fragmentation=yes<br />
     ikev2=insist<br />
     narrowing=yes<br />
     left=1.2.3.4<br />
     right=4.3.2.1<br />
     leftsubnet=172.16.43.254/32<br />
     rightsubnet=10.0.0.0/8<br />
[/cc]<br />
В принципе, при этом даже не обязательно использовать ikev2 (я его включил просто по той причине, что с v1 не работал NAT-T).</p>
<p>Файл /etc/ipsec.secrets:<br />
[cc]1.2.3.4 4.3.2.1 : PSK &#8220;VeRy$tR0nGp@s$w0rD&#8221;[/cc]</p>
<p>А вот так будет выглядеть конфиг для StrongSwan (/etc/ipsec.d/nixman.conf):<br />
[cc]config setup</p>
<p>conn %default<br />
	keyexchange = ikev2<br />
	authby = psk<br />
	keyingtries = %forever<br />
        ike = aes128-md5-modp1024!<br />
	ikelifetime = 24h<br />
        esp = aes128-md5-modp1024!<br />
	keylife = 1h<br />
	right = 4.3.2.1<br />
	dpdaction = restart<br />
	closeaction = restart<br />
	rightsubnet = 10.0.0.0/8<br />
	auto = start</p>
<p>conn ts-01<br />
	leftsubnet = 172.16.43.254/32<br />
[/cc]</p>
<p>/etc/ipsec.d/nixman.secret:<br />
[cc]1.2.3.4 : PSK &#8220;VeRy$tR0nGp@s$w0rD&#8221;<br />
4.3.2.1 : PSK &#8220;VeRy$tR0nGp@s$w0rD&#8221;[/cc]</p>
<p>При успешном подключении должно быть так:<br />
[cc]<br />
admin@srx340-02> show security ike security-associations<br />
Index   State  Initiator cookie  Responder cookie  Mode           Remote Address<br />
7937209 UP     8fb291a33b5bcbb4  742ad541fcbb8f2c  IKEv2          1.2.3.4</p>
<p>admin@srx340-02> show security ipsec security-associations<br />
  Total active tunnels: 2<br />
  ID    Algorithm       SPI      Life:sec/kb  Mon lsys Port  Gateway<br />
  <67108867 ESP:aes-cbc-128/md5 cd9e67ad 3169/ unlim - root 4500 1.2.3.4    
  >67108867 ESP:aes-cbc-128/md5 e57ed5c1 3169/ unlim &#8211; root 4500 1.2.3.4<br />
[/cc]</p>
<p>и вот так (пример для libreswan):<br />
[cc]</p>
<p>root@server:~# ipsec status<br />
000 using kernel interface: netkey<br />
000 interface lo/lo ::1@500<br />
000 interface lo/lo 127.0.0.1@4500<br />
000 interface lo/lo 127.0.0.1@500<br />
000 interface eth0/eth0 172.16.43.254@4500<br />
000 interface eth0/eth0 172.16.43.254@500<br />
000<br />
000<br />
000 fips mode=disabled;<br />
000 SElinux=disabled<br />
000<br />
000 config setup options:<br />
000<br />
000 configdir=/etc, configfile=/etc/ipsec.conf, secrets=/etc/ipsec.secrets, ipsecdir=/etc/ipsec.d, dumpdir=/var/run/pluto/, statsbin=unset<br />
000 sbindir=/usr/sbin, libexecdir=/usr/lib/ipsec<br />
000 pluto_version=3.16, pluto_vendorid=OE-Libreswan-3.16<br />
000 nhelpers=-1, uniqueids=yes, perpeerlog=no, shuntlifetime=900s, xfrmlifetime=300s<br />
000 ddos-cookies-treshold=50000, ddos-max-halfopen=25000, ddos-mode=auto<br />
000 ikeport=500, strictcrlpolicy=no, crlcheckinterval=0, listen=<any>, nflog-all=0<br />
000 secctx-attr-type=<unsupported><br />
000 myid = (none)<br />
000 debug none<br />
000<br />
000 nat-traversal=yes, keep-alive=20, nat-ikeport=4500<br />
000 virtual-private (%priv):<br />
000 &#8211; allowed subnets: 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 25.0.0.0/8, 100.64.0.0/10, fd00::/8, fe80::/10<br />
000<br />
000 ESP algorithms supported:<br />
000<br />
000 algorithm ESP encrypt: id=3, name=ESP_3DES, ivlen=8, keysizemin=192, keysizemax=192<br />
000 algorithm ESP encrypt: id=6, name=ESP_CAST, ivlen=8, keysizemin=128, keysizemax=128<br />
000 algorithm ESP encrypt: id=11, name=ESP_NULL, ivlen=0, keysizemin=0, keysizemax=0<br />
000 algorithm ESP encrypt: id=12, name=ESP_AES, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=13, name=ESP_AES_CTR, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=14, name=ESP_AES_CCM_A, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=15, name=ESP_AES_CCM_B, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=16, name=ESP_AES_CCM_C, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=18, name=ESP_AES_GCM_A, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=19, name=ESP_AES_GCM_B, ivlen=12, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=20, name=ESP_AES_GCM_C, ivlen=16, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=22, name=ESP_CAMELLIA, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=252, name=ESP_SERPENT, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm ESP encrypt: id=253, name=ESP_TWOFISH, ivlen=8, keysizemin=128, keysizemax=256<br />
000 algorithm AH/ESP auth: id=1, name=AUTH_ALGORITHM_HMAC_MD5, keysizemin=128, keysizemax=128<br />
000 algorithm AH/ESP auth: id=2, name=AUTH_ALGORITHM_HMAC_SHA1, keysizemin=160, keysizemax=160<br />
000 algorithm AH/ESP auth: id=5, name=AUTH_ALGORITHM_HMAC_SHA2_256, keysizemin=256, keysizemax=256<br />
000 algorithm AH/ESP auth: id=6, name=AUTH_ALGORITHM_HMAC_SHA2_384, keysizemin=384, keysizemax=384<br />
000 algorithm AH/ESP auth: id=7, name=AUTH_ALGORITHM_HMAC_SHA2_512, keysizemin=512, keysizemax=512<br />
000 algorithm AH/ESP auth: id=8, name=AUTH_ALGORITHM_HMAC_RIPEMD, keysizemin=160, keysizemax=160<br />
000 algorithm AH/ESP auth: id=9, name=AUTH_ALGORITHM_AES_XCBC, keysizemin=128, keysizemax=128<br />
000 algorithm AH/ESP auth: id=251, name=AUTH_ALGORITHM_NULL_KAME, keysizemin=0, keysizemax=0<br />
000<br />
000 IKE algorithms supported:<br />
000<br />
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=16, v2name=AES_CCM_C, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=15, v2name=AES_CCM_B, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=0, v1name=0??, v2id=14, v2name=AES_CCM_A, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=5, v1name=OAKLEY_3DES_CBC, v2id=3, v2name=3DES, blocksize=8, keydeflen=192<br />
000 algorithm IKE encrypt: v1id=24, v1name=OAKLEY_CAMELLIA_CTR, v2id=24, v2name=CAMELLIA_CTR, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=8, v1name=OAKLEY_CAMELLIA_CBC, v2id=23, v2name=CAMELLIA_CBC, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=20, v1name=OAKLEY_AES_GCM_C, v2id=20, v2name=AES_GCM_C, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=19, v1name=OAKLEY_AES_GCM_B, v2id=19, v2name=AES_GCM_B, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=18, v1name=OAKLEY_AES_GCM_A, v2id=18, v2name=AES_GCM_A, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=13, v1name=OAKLEY_AES_CTR, v2id=13, v2name=AES_CTR, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=7, v1name=OAKLEY_AES_CBC, v2id=12, v2name=AES_CBC, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=65004, v1name=OAKLEY_SERPENT_CBC, v2id=65004, v2name=SERPENT_CBC, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=65005, v1name=OAKLEY_TWOFISH_CBC, v2id=65005, v2name=TWOFISH_CBC, blocksize=16, keydeflen=128<br />
000 algorithm IKE encrypt: v1id=65289, v1name=OAKLEY_TWOFISH_CBC_SSH, v2id=65289, v2name=TWOFISH_CBC_SSH, blocksize=16, keydeflen=128<br />
000 algorithm IKE hash: id=1, name=OAKLEY_MD5, hashlen=16<br />
000 algorithm IKE hash: id=2, name=OAKLEY_SHA1, hashlen=20<br />
000 algorithm IKE hash: id=4, name=OAKLEY_SHA2_256, hashlen=32<br />
000 algorithm IKE hash: id=5, name=OAKLEY_SHA2_384, hashlen=48<br />
000 algorithm IKE hash: id=6, name=OAKLEY_SHA2_512, hashlen=64<br />
000 algorithm IKE hash: id=9, name=DISABLED-OAKLEY_AES_XCBC, hashlen=16<br />
000 algorithm IKE dh group: id=2, name=OAKLEY_GROUP_MODP1024, bits=1024<br />
000 algorithm IKE dh group: id=5, name=OAKLEY_GROUP_MODP1536, bits=1536<br />
000 algorithm IKE dh group: id=14, name=OAKLEY_GROUP_MODP2048, bits=2048<br />
000 algorithm IKE dh group: id=15, name=OAKLEY_GROUP_MODP3072, bits=3072<br />
000 algorithm IKE dh group: id=16, name=OAKLEY_GROUP_MODP4096, bits=4096<br />
000 algorithm IKE dh group: id=17, name=OAKLEY_GROUP_MODP6144, bits=6144<br />
000 algorithm IKE dh group: id=18, name=OAKLEY_GROUP_MODP8192, bits=8192<br />
000 algorithm IKE dh group: id=22, name=OAKLEY_GROUP_DH22, bits=1024<br />
000 algorithm IKE dh group: id=23, name=OAKLEY_GROUP_DH23, bits=2048<br />
000 algorithm IKE dh group: id=24, name=OAKLEY_GROUP_DH24, bits=2048<br />
000<br />
000 stats db_ops: {curr_cnt, total_cnt, maxsz} :context={0,201,64} trans={0,201,6144} attrs={0,201,4096}<br />
000<br />
000 Connection list:<br />
000<br />
000 &#8220;srx&#8221;: 172.16.43.254/32===172.16.43.254<172.16.43.254>[1.2.3.4]&#8230;4.3.2.1<4.3.2.1>===10.0.0.0/8; prospective erouted; eroute owner: #0<br />
000 &#8220;srx&#8221;:     oriented; my_ip=unset; their_ip=unset<br />
000 &#8220;srx&#8221;:   xauth info: us:none, them:none,  my_xauthuser=[any]; their_xauthuser=[any]<br />
000 &#8220;srx&#8221;:   modecfg info: us:none, them:none, modecfg policy:push, dns1:unset, dns2:unset, domain:unset, banner:unset;<br />
000 &#8220;srx&#8221;:   labeled_ipsec:no;<br />
000 &#8220;srx&#8221;:   policy_label:unset;<br />
000 &#8220;srx&#8221;:   ike_life: 86400s; ipsec_life: 3600s; replay_window: 32; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0;<br />
000 &#8220;srx&#8221;:   retransmit-interval: 500ms; retransmit-timeout: 60s;<br />
000 &#8220;srx&#8221;:   sha2_truncbug:no; initial_contact:no; cisco_unity:no; fake_strongswan:no; send_vendorid:no;<br />
000 &#8220;srx&#8221;:   policy: PSK+ENCRYPT+TUNNEL+PFS+DONT_REKEY+IKEV2_ALLOW+IKEV2_PROPOSE+IKEV2_ALLOW_NARROWING+SAREF_TRACK+IKE_FRAG_ALLOW;<br />
000 &#8220;srx&#8221;:   conn_prio: 32,8; interface: eth0; metric: 0; mtu: unset; sa_prio:auto; nflog-group: unset; mark: unset;<br />
000 &#8220;srx&#8221;:   dpd: action:clear; delay:30; timeout:120; nat-t: force_encaps:no; nat_keepalive:yes; ikev1_natt:both<br />
000 &#8220;srx&#8221;:   newest ISAKMP SA: #0; newest IPsec SA: #0;<br />
000 &#8220;srx&#8221;:   IKE algorithms wanted: AES_CBC(7)_128-MD5(1)_000-MODP1024(2)<br />
000 &#8220;srx&#8221;:   IKE algorithms found:  AES_CBC(7)_128-MD5(1)_128-MODP1024(2)<br />
000 &#8220;srx&#8221;:   ESP algorithms wanted: AES(12)_128-MD5(1)_000; pfsgroup=MODP1024(2)<br />
000 &#8220;srx&#8221;:   ESP algorithms loaded: AES(12)_128-MD5(1)_000<br />
000 &#8220;srx&#8221;[1]: 172.16.43.254<172.16.43.254>[1.2.3.4]&#8230;4.3.2.1<4.3.2.1>===10.0.0.0/8; erouted; eroute owner: #398<br />
000 &#8220;srx&#8221;[1]:     oriented; my_ip=unset; their_ip=unset<br />
000 &#8220;srx&#8221;[1]:   xauth info: us:none, them:none,  my_xauthuser=[any]; their_xauthuser=[any]<br />
000 &#8220;srx&#8221;[1]:   modecfg info: us:none, them:none, modecfg policy:push, dns1:unset, dns2:unset, domain:unset, banner:unset;<br />
000 &#8220;srx&#8221;[1]:   labeled_ipsec:no;<br />
000 &#8220;srx&#8221;[1]:   policy_label:unset;<br />
000 &#8220;srx&#8221;[1]:   ike_life: 86400s; ipsec_life: 3600s; replay_window: 32; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0;<br />
000 &#8220;srx&#8221;[1]:   retransmit-interval: 500ms; retransmit-timeout: 60s;<br />
000 &#8220;srx&#8221;[1]:   sha2_truncbug:no; initial_contact:no; cisco_unity:no; fake_strongswan:no; send_vendorid:no;<br />
000 &#8220;srx&#8221;[1]:   policy: PSK+ENCRYPT+TUNNEL+PFS+DONT_REKEY+UP+IKEV2_ALLOW+IKEV2_PROPOSE+IKEV2_ALLOW_NARROWING+SAREF_TRACK+IKE_FRAG_ALLOW;<br />
000 &#8220;srx&#8221;[1]:   conn_prio: 32,8; interface: eth0; metric: 0; mtu: unset; sa_prio:auto; nflog-group: unset; mark: unset;<br />
000 &#8220;srx&#8221;[1]:   dpd: action:clear; delay:30; timeout:120; nat-t: force_encaps:no; nat_keepalive:yes; ikev1_natt:both<br />
000 &#8220;srx&#8221;[1]:   newest ISAKMP SA: #397; newest IPsec SA: #398;<br />
000 &#8220;srx&#8221;[1]:   IKE algorithms wanted: AES_CBC(7)_128-MD5(1)_000-MODP1024(2)<br />
000 &#8220;srx&#8221;[1]:   IKE algorithms found:  AES_CBC(7)_128-MD5(1)_128-MODP1024(2)<br />
000 &#8220;srx&#8221;[1]:   IKEv2 algorithm newest: AES_CBC_128-AUTH_HMAC_MD5_96-PRF_HMAC_MD5-MODP1024<br />
000 &#8220;srx&#8221;[1]:   ESP algorithms wanted: AES(12)_128-MD5(1)_000; pfsgroup=MODP1024(2)<br />
000 &#8220;srx&#8221;[1]:   ESP algorithms loaded: AES(12)_128-MD5(1)_000<br />
000 &#8220;srx&#8221;[1]:   ESP algorithm newest: AES_128-HMAC_MD5; pfsgroup=MODP1024<br />
000 &#8220;v6neighbor-hole-in&#8221;: ::/0===::1<::1>:58/34560&#8230;%any:58/34816===::/0; prospective erouted; eroute owner: #0<br />
000 &#8220;v6neighbor-hole-in&#8221;:     oriented; my_ip=unset; their_ip=unset<br />
000 &#8220;v6neighbor-hole-in&#8221;:   xauth info: us:none, them:none,  my_xauthuser=[any]; their_xauthuser=[any]<br />
000 &#8220;v6neighbor-hole-in&#8221;:   modecfg info: us:none, them:none, modecfg policy:push, dns1:unset, dns2:unset, domain:unset, banner:unset;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   labeled_ipsec:no;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   policy_label:unset;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   ike_life: 0s; ipsec_life: 0s; replay_window: 0; rekey_margin: 0s; rekey_fuzz: 0%; keyingtries: 0;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   retransmit-interval: 0ms; retransmit-timeout: 0s;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   sha2_truncbug:no; initial_contact:no; cisco_unity:no; fake_strongswan:no; send_vendorid:no;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   policy: PFS+IKEV1_ALLOW+IKEV2_ALLOW+SAREF_TRACK+IKE_FRAG_ALLOW+PASS+NEVER_NEGOTIATE;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   conn_prio: 0,0; interface: lo; metric: 0; mtu: unset; sa_prio:1; nflog-group: unset; mark: unset;<br />
000 &#8220;v6neighbor-hole-in&#8221;:   newest ISAKMP SA: #0; newest IPsec SA: #0;<br />
000 &#8220;v6neighbor-hole-out&#8221;: ::/0===::1<::1>:58/34816&#8230;%any:58/34560===::/0; prospective erouted; eroute owner: #0<br />
000 &#8220;v6neighbor-hole-out&#8221;:     oriented; my_ip=unset; their_ip=unset<br />
000 &#8220;v6neighbor-hole-out&#8221;:   xauth info: us:none, them:none,  my_xauthuser=[any]; their_xauthuser=[any]<br />
000 &#8220;v6neighbor-hole-out&#8221;:   modecfg info: us:none, them:none, modecfg policy:push, dns1:unset, dns2:unset, domain:unset, banner:unset;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   labeled_ipsec:no;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   policy_label:unset;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   ike_life: 0s; ipsec_life: 0s; replay_window: 0; rekey_margin: 0s; rekey_fuzz: 0%; keyingtries: 0;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   retransmit-interval: 0ms; retransmit-timeout: 0s;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   sha2_truncbug:no; initial_contact:no; cisco_unity:no; fake_strongswan:no; send_vendorid:no;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   policy: PFS+IKEV1_ALLOW+IKEV2_ALLOW+SAREF_TRACK+IKE_FRAG_ALLOW+PASS+NEVER_NEGOTIATE;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   conn_prio: 0,0; interface: lo; metric: 0; mtu: unset; sa_prio:1; nflog-group: unset; mark: unset;<br />
000 &#8220;v6neighbor-hole-out&#8221;:   newest ISAKMP SA: #0; newest IPsec SA: #0;<br />
000<br />
000 Total IPsec connections: loaded 4, active 1<br />
000<br />
000 State Information: DDoS cookies not required, Accepting new IKE connections<br />
000 IKE SAs: total(1), half-open(0), open(0), authenticated(1), anonymous(0)<br />
000 IPsec SAs: total(1), authenticated(1), anonymous(0)<br />
000<br />
000 #398: &#8220;srx&#8221;[1] 4.3.2.1:4500 STATE_PARENT_R2 (received v2I2, PARENT SA established); EVENT_SA_EXPIRE in 2818s; newest IPSEC; eroute owner; isakmp#397; idle; import:respond to stranger<br />
000 #398: &#8220;srx&#8221;[1] 4.3.2.1 esp.cd9e67ad@4.3.2.1 esp.e57ed5c1@172.16.43.254 tun.0@4.3.2.1 tun.0@172.16.43.254 ref=0 refhim=4294901761 Traffic: ESPin=33KB ESPout=304KB! ESPmax=0B<br />
000 #397: &#8220;srx&#8221;[1] 4.3.2.1:4500 STATE_PARENT_R2 (received v2I2, PARENT SA established); EVENT_SA_EXPIRE in 85618s; newest ISAKMP; isakmp#0; idle; import:respond to stranger<br />
000 #397: &#8220;srx&#8221;[1] 4.3.2.1 ref=0 refhim=0 Traffic:<br />
000<br />
000 Bare Shunt list:<br />
000<br />
[/cc]</p>
<p>наконец, проверяем, что пинги ходят в обе стороны (не забудьте про маршруты) и защищённые сети доступны с обеих сторон.</p>
<p>Вот, собственно, всё =)</p>
<p>The post <a href="https://nixman.info/?p=2816">Juniper SRX и Libreswan (и ещё StrongSwan)</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2816</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Mikrotik и ansible: устанавливаем сертификаты</title>
		<link>https://nixman.info/?p=2792</link>
					<comments>https://nixman.info/?p=2792#comments</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Mon, 26 Jun 2017 07:19:19 +0000</pubDate>
				<category><![CDATA[Mikrotik]]></category>
		<category><![CDATA[ansible]]></category>
		<category><![CDATA[certificates]]></category>
		<category><![CDATA[hotspot]]></category>
		<category><![CDATA[mikrotik]]></category>
		<category><![CDATA[ssl]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2792</guid>

					<description><![CDATA[<p>У Mikrotik, как и у каждого уважающего себя вендора, есть API для работы со своими продуктами. Cтоит признать, этот API даже весьма рабочий. Я, в своё время, успел поработать с perl и python реализациями этого API, но процессе написания статей из цикла &#8220;Hotspot для самых маленьких&#8221; появилось стойкое убеждение, что, в большинстве случаев, это всё&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2792">Mikrotik и ansible: устанавливаем сертификаты</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>У Mikrotik, как и у каждого уважающего себя вендора, есть API для работы со своими продуктами. Cтоит признать, этот API даже весьма рабочий.<br />
Я, в своё время, успел поработать с perl и python реализациями этого API, но процессе написания статей из цикла &#8220;<a href="https://nixman.info/?tag=hotspot" target="_blank" rel="noopener">Hotspot для самых маленьких</a>&#8221; появилось стойкое убеждение, что, в большинстве случаев, это всё то же забивание консольной команды и получение результата в какой-нибудь удобоваримой форме (хотя и есть, вроде, ООП-реализации, но и они далеки от идеала). Плюс само API несёт некоторые ограничения (например, нельзя с его помощью вызывать команды встроенного интерпретатора RouterOS).</p>
<p>Однако же, далеко не всегда нужно использовать API. Например, если нужно просто выполнить определённую последовательность действий (пусть и параметризованную), гораздо быстрее, удобнее и надёжнее использовать ansbile (как я уже показал в <a href="http://nixman.info/?p=2736" target="_blank" rel="noopener">прошлой статье</a>).</p>
<p>А тут как раз подвернулась задачка &#8211; нужно раз в три месяца обновлять сертификаты на нашем микротике, которые мы получаем от let&#8217;s encrypt.<br />
Хотите узнать, как? Прошу под кат <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><span id="more-2792"></span><br />
Для начала определимся, что у нас уже есть микротик, debian и certbot, через который мы и получаем сертификаты от let&#8217;s encrypt. Вместо certbot можно использовать любое другое, удобное для вас решение. Так же подразумевается, что вы уже получили сертификат любым удобным вам образом (например через webroot).</p>
<p>Т.к. нативного модуля для Mikrotik у Ansible нет, то приходится выкручиваться. Один из способов &#8211; это выполнение команд на устройстве последовательно через ssh. Можно было бы, конечно, залить rsc-файл и сделать import, но это лишает нас возможности получить хоть какую-то отладочную информацию.<br />
На эту идею меня натолкнул пользователь <a href="https://github.com/0x566164696D" target="_blank" rel="noopener">0x566164696D</a>, за что ему большое спасибо.</p>
<p>ansible.cfg будет примерно таким:<br />
<code><br />
[defaults]<br />
inventory	= inventory<br />
remote_tmp     = $HOME/.ansible/tmp<br />
pattern        = *<br />
forks          = 20<br />
poll_interval  = 15<br />
transport      = smart<br />
remote_port    = 22<br />
roles_path    = ./roles<br />
host_key_checking = False<br />
sudo_exe = sudo<br />
timeout = 10<br />
remote_user = hspot_admin<br />
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}<br />
action_plugins     = /usr/share/ansible_plugins/action_plugins<br />
callback_plugins   = /usr/share/ansible_plugins/callback_plugins<br />
connection_plugins = /usr/share/ansible_plugins/connection_plugins<br />
lookup_plugins     = /usr/share/ansible_plugins/lookup_plugins<br />
vars_plugins       = /usr/share/ansible_plugins/vars_plugins<br />
filter_plugins     = /usr/share/ansible_plugins/filter_plugins<br />
etcd_url = 'http://127.0.0.1:4001'<br />
retry_files_save_path = ~/ansible/.ansible-retry<br />
</code><br />
Особое внимание обратите на remote_user (его мы создадим на микротике и roles_path &#8211; в этой папке будут лежать наши роли.</p>
<p>Сначала зададим переменные:<br />
<code><br />
rsa_key_file: "ansible_user.key"<br />
mkt_user_name: "hspot_admin"<br />
mkt_user_key: "{{ lookup('file', rsa_key_file) }}"<br />
cert_dir: "/etc/letsencrypt/live/oauth.{{ hspot_domain }}/"<br />
cert_file: cert.pem<br />
key_file: privkey.pem<br />
chain_file: fullchain.pem<br />
</code><br />
в ansible_user.key лежит мой публичный ssh-ключ.</p>
<p>Теперь создадим пользователя и добавим ему ssh-ключ, чтобы ходить на устройство без ввода пароля:<br />
<code><br />
#file=tasks/main.yml<br />
---<br />
- name: Generate random password via pwgen<br />
  command: "pwgen -s 19 1"<br />
  register: random_passwd</p>
<p>- name: Generate .rsc to check and add user<br />
  template: src=add_ansible_user.rsc.j2 dest=/tmp/{{inventory_hostname}}.rsc</p>
<p>- name: Run .rsc script<br />
  command: bash -c "cat /tmp/{{inventory_hostname}}.rsc | sshpass -p "{{ros_passwd}}" ssh {{ros_login}}@{{ansible_host}} -p {{ansible_ssh_port}} -T -o StrictHostKeyChecking=no -o NumberOfPasswordPrompts=1"</p>
<p>- name: Delete temp .rsc file<br />
  file: path=/tmp/{{inventory_hostname}}.rsc state=absent</p>
<p>#file=templates/add_ansible_user.rsc.j2<br />
:if ([/user find name={{mkt_user_name}}] ="") do={ :log info "User {{mkt_user_name}} not found... Add it"}<br />
:if ([/user find name={{mkt_user_name}}] ="") do={/file print file=ansible_key.txt; :delay 2; /file set ansible_key.txt contents="{{mkt_user_key}}";}<br />
:if ([/user find name={{mkt_user_name}}] ="") do={/user add name={{mkt_user_name}} group=full password="{{random_passwd.stdout}}"; :delay 2; /user ssh-keys import user={{mkt_user_name}} public-key-file=ansible_key.txt}<br />
</code></p>
<p>Прогоняем плейбук. Если всё отработало штатно, то у нас на микротике будет наш пользователь:<br />
<code><br />
PLAY [all] *********************************************************************</p>
<p>TASK [add-to-ansible : Generate random password via pwgen] *********************<br />
changed: [hotspot]</p>
<p>TASK [add-to-ansible : Generate .rsc to check and add user] ********************<br />
changed: [hotspot]</p>
<p>TASK [add-to-ansible : Run .rsc script] ****************************************<br />
changed: [hotspot]</p>
<p>TASK [add-to-ansible : Delete temp .rsc file] **********************************<br />
changed: [hotspot]</p>
<p>PLAY RECAP *********************************************************************<br />
hotspot                    : ok=4    changed=4    unreachable=0    failed=0<br />
</code></p>
<p>Теперь, наконец, можно приступить к заливке сертификатов. Роль будет вот такая:<br />
<code><br />
#file=tasks/main.yml<br />
---<br />
- name: Generate .rsc to add certs<br />
  template: src=cert_install.rsc.j2 dest=/tmp/{{inventory_hostname}}.rsc</p>
<p>- name: Copy certs to device<br />
  copy:<br />
    src: "{{cert_dir}}/{{item}}"<br />
    dest: /<br />
    with_items:<br />
      - "{{cert_file}}"<br />
      - "{{key_file}}"<br />
      - "{{chain_file}}"<br />
- name: Activate certs on device<br />
  action: shell "cat /tmp/{{inventory_hostname}}.rsc | ssh -T {{inventory_hostname}} -p {{ansible_ssh_port}}"</p>
<p>- name: Delete temp .rsc file<br />
  file: path=/tmp/{{inventory_hostname}}.rsc state=absent</p>
<p>#file=templates/cert_install.rsc.j2<br />
#1. Remove cert file with same common-name (You need to define it below)<br />
/foreach i in=[/certificate find common-name="Let's Encrypt Authority X3"] do {/certificate remove $i}<br />
/foreach i in=[/certificate find common-name="{{hspot_oauth}}"] do {/certificate remove $i}<br />
#2. install new certs (cert.pem, privkey.pem, chain.pem)<br />
/certificate import file={{cert_file}}<br />
/certificate import file={{key_file}}<br />
/certificate import file={{chain_file}}<br />
#3. check www-ssl and hotspot certs (set new cert at www-ssl and hotspot you need to define common-name)<br />
/foreach i in=[/ip hotspot profile find login-by=https] do {/ip hotspot profile set $i ssl-certificate=[/certificate find common-name={{hspot_oauth}}]}<br />
/foreach i in=[/ip service find name=www-ssl] do {/ip service set $i certificate=[/certificate find common-name={{hspot_oauth}}]}<br />
</code></p>
<p>Запускаем наш плейбук:<br />
<code><br />
PLAY [all-mkt] **************************************************************** </p>
<p>TASK: [cert_install | Generate .rsc to add certs] *****************************<br />
ok: [10.0.2.7]</p>
<p>TASK: [cert_install | Copy certs to device] ***********************************<br />
changed: [10.0.2.7] => (item=cert.pem)<br />
changed: [10.0.2.7] => (item=privkey.pem)<br />
changed: [10.0.2.7] => (item=chain.pem)</p>
<p>TASK: [cert_install | Activate certs on device] *******************************<br />
changed: [10.0.2.7]</p>
<p>TASK: [cert_install | Delete temp .rsc file] **********************************<br />
ok: [10.0.2.7]</p>
<p>PLAY RECAP ********************************************************************<br />
10.0.2.7                   : ok=4    changed=2    unreachable=0    failed=0<br />
</code></p>
<p>Если всё ок, то на микротике мы увидим свежие сертификаты.</p>
<p>В этой статье я разобрал довольно простой случай, поле для улучшения обширное, как и для написания других плейбуков, упрощающих работу с микротиками. К сожалению, для ansible ещё нет нативного модуля router-os, поэтому все операции выполняются через shell, что совсем не best way. Но, будем надеяться на лучшее, а пока просто лучше продумывать логику плейбуков, дабы повторный накат ничего не сломал.</p>
<p>Мой форк репо mikroansible можно найти на <a href="https://github.com/nightsnake/mikroansible">github</a>. Там же лежат роли, описанные в этой статье.</p>
<p>The post <a href="https://nixman.info/?p=2792">Mikrotik и ansible: устанавливаем сертификаты</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2792</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Подкаст Linkmeup: Сетевики не нужны?</title>
		<link>https://nixman.info/?p=2795</link>
					<comments>https://nixman.info/?p=2795#respond</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Fri, 26 May 2017 08:08:11 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[linkmeup]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2795</guid>

					<description><![CDATA[<p>Вчера ребята из LinkMeUp выложили запись подкаста, в котором ваш покорный слуга размышлял на тему, останутся ли сетевики в чистом виде, или их время прошло, а впереди нас ждёт DevOPS и SRE. Разумеется, уже после записи пришло осознание, что ещё можно было рассказать и обсудить. Но и без этого, я думаю, поговорили весьма неплохо. Качаем,&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2795">Подкаст Linkmeup: Сетевики не нужны?</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Вчера ребята из LinkMeUp выложили запись подкаста, в котором ваш покорный слуга размышлял на тему, останутся ли сетевики в чистом виде, или их время прошло, а впереди нас ждёт DevOPS и SRE.<br />
Разумеется, уже после записи пришло осознание, что ещё можно было рассказать и обсудить.<br />
Но и без этого, я думаю, поговорили весьма неплохо.</p>
<p>Качаем, слушаем, пишем в комментарии своё мнение!</p>
<p><a href="http://linkmeup.ru/blog/283.html" target="_blank" rel="noopener">Ссылка на сайт</a><br />
<a href="https://archive.org/download/linkmeup-V051/linkmeup-V051.mp3" target="_blank" rel="noopener">Ссылка на подкаст</a></p>
<p>The post <a href="https://nixman.info/?p=2795">Подкаст Linkmeup: Сетевики не нужны?</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2795</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure length="0" type="audio/mpeg" url="https://archive.org/download/linkmeup-V051/linkmeup-V051.mp3"/>

			</item>
		<item>
		<title>Mikrotik для небольшого офиса</title>
		<link>https://nixman.info/?p=2752</link>
					<comments>https://nixman.info/?p=2752#comments</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Sun, 19 Mar 2017 07:18:27 +0000</pubDate>
				<category><![CDATA[Mikrotik]]></category>
		<category><![CDATA[dhcp]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[lan]]></category>
		<category><![CDATA[mikrotik]]></category>
		<category><![CDATA[nat]]></category>
		<category><![CDATA[router]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2752</guid>

					<description><![CDATA[<p>Вводная: небольшой офис. В наличии имеется один канал от провайдера (впрочем, их может быть два), проводная сеть, служебный и гостевой WiFi. При этом к проводной сети подключены сервера (ну и админ, конечно ;)), а сотрудники сидят через служебный WiFi. Для гостей (и личных устройств сотрудников) есть гостевой WiFi (может быть, даже с hotspot) c обычной&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2752">Mikrotik для небольшого офиса</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Вводная: небольшой офис. В наличии имеется один канал от провайдера (впрочем, их может быть <a href="http://nixman.info/?p=2736" target="_blank" rel="noopener">два</a>), проводная сеть, служебный и гостевой WiFi.<br />
При этом к проводной сети подключены сервера (ну и админ, конечно ;)), а сотрудники сидят через служебный WiFi. Для гостей (и личных устройств сотрудников) есть гостевой WiFi (может быть, даже с <a href="https://nixman.info/?tag=hotspot" target="_blank" rel="noopener">hotspot</a>) c обычной PSK-аутентификацией или без неё.<br />
Чтобы было ещё веселее &#8211; добавим DMZ с почтовым сервером (как его настроить, можно почтитать, например, <a href="https://nixman.info/?tag=mail" target="_blank" rel="noopener">тут</a>). По организации DMZ есть много толковых мануалов, так что заострять на этом внимания не буду &#8211; для простоты, почтовый сервер будет жить в одной сети со всеми остальными.</p>
<p>В этой статье я намеренно не буду пытаться охватить все аспекты существования офисного роутера (например, обеспечение резервирования или <a href="https://nixman.info/?p=2308" target="_blank" rel="noopener">удалённого доступа сотрудников</a>) &#8211; вы без труда найдёте на этом сайте нужную информацию воспользовавшись поиском или облаком тэгов.<br />
<a href="https://nixman.info/wp-content/uploads/2017/03/netdiag2.png"><img fetchpriority="high" decoding="async" src="https://nixman.info/wp-content/uploads/2017/03/netdiag2.png" alt="netdiag2" width="611" height="392" class="aligncenter size-full wp-image-2783" /></a><br />
Мы же остановимся именно на разграничении трафика между тремя сетями &#8211; для каждой будет отдельное адресное пространство, интерфейсы и правила фаервола.<br />
Хорошей идеей было бы ограничить гостевую сеть с помощью очередей (queues), но это оставим для следующей статьи.<br />
Приступим?<br />
<span id="more-2752"></span></p>
<h2>0. Обновление, установка ntp server</h2>
<p>Для начала, нужно установить актуальную версию Router OS (я использую bugfix-ветку, но можно и current) и обновить firmware.<br />
Т.к. микротик в нашей локалке будет ещё и ntp-сервером, установим соответствующий пакет.<br />
В моём случае это следуюшие пакеты<br />
<code><br />
ntp-6.37.5-mipsbe.npk<br />
routeros-mipsbe-6.37.5.npk<br />
</code><br />
С помощью WinBox (или веб-интерфейса) кладём файлы в корень ФС устройства, перезагружаемся.<br />
<a href="https://nixman.info/wp-content/uploads/2017/03/winbox2-1.png"><img decoding="async" src="https://nixman.info/wp-content/uploads/2017/03/winbox2-1.png" alt="winbox2" width="556" height="328" class="aligncenter size-full wp-image-2780" /></a></p>
<h2>1. Настройка с нуля</h2>
<p>Теперь сбросим конфигурацию, чтобы настроить с нуля. Зачем? Всё просто &#8211; настраиваем мы не просто домашний роутер, а роутер для офиса, тем более с претензией на защищённость, и настройки необходимо держать под контролем.<br />
После сброоса конфигурации, подключиться к устройству можно через WinBox и функцию mac-telnet (я надеюсь, как это сделать, вы знаете).<br />
<a href="https://nixman.info/wp-content/uploads/2017/03/winbox.png"><img decoding="async" src="https://nixman.info/wp-content/uploads/2017/03/winbox.png" alt="winbox" width="659" height="340" class="aligncenter size-full wp-image-2776" /></a><br />
Интерфейсы<br />
<code><br />
#Настройки интерфейсов приведены для роутера RB951<br />
#На вашем роутере настройки интерфейсов могут отличаться<br />
/interface ethernet<br />
set [ find default-name=ether1 ] comment=Internet name=ether1<br />
set [ find default-name=ether2 ] name=ether2<br />
set [ find default-name=ether3 ] master-port=ether2 name=ether3<br />
set [ find default-name=ether4 ] master-port=ether2 name=ether4<br />
set [ find default-name=ether5 ] master-port=ether2 name=ether5<br />
</code><br />
IP, DHCP-сервер<br />
<code><br />
/ip address<br />
add address=192.168.88.1/24 comment="servers" interface=ether2 network=192.168.88.0<br />
/ip pool<br />
add name=guest ranges=192.168.88.10-192.168.88.254<br />
/ip dhcp-server network<br />
add address=192.168.88.0/24 comment="servers" dns-server=192.168.88.1 gateway=192.168.88.1 ntp-server=192.168.88.1<br />
/ip dhcp-server<br />
add address-pool=servers disabled=no interface=ether2 lease-time=3d name=servers<br />
</code><br />
<code><br />
/ip address<br />
add address=192.168.89.1/24 comment="Stuff WiFi" interface=wlan1 network=192.168.89.0<br />
/ip pool<br />
add name=stuff ranges=192.168.89.10-192.168.89.254<br />
/ip dhcp-server network<br />
add address=192.168.89.0/24 comment="stuff wifi" dns-server=192.168.89.1 gateway=192.168.89.1 ntp-server=192.168.89.1<br />
/ip dhcp-server<br />
add address-pool=stuff disabled=no interface=wlan1 lease-time=3d name=stuff<br />
</code></p>
<p>NTP-сервер<br />
<code>/system ntp client<br />
set enabled=yes primary-ntp=95.104.192.10 secondary-ntp=93.180.6.3<br />
/system ntp server<br />
set enabled=yes</code></p>
<p>5. WiFi (channel, psk)<br />
<code>/interface wireless<br />
#Выставляем режим 2.4GHz b/g/n (у вас, возможно, будет другая модель роутера, например с поддержкой 5GHz-диапазона.<br />
#В таком случае, настройки будут отличаться<br />
#Также, возможно, придётся поменять частоту<br />
set [ find default-name=wlan1 ] band=2ghz-b/g/n comment=hs-ap-default disabled=no distance=indoors frequency=2437 guard-interval=long mode=ap-bridge ssid=Stuff wireless-protocol=802.11<br />
/interface wireless security-profiles<br />
set [ find default=yes ] authentication-types=wpa2-psk group-ciphers=aes-ccm mode=dynamic-keys supplicant-identity=MikroTik unicast-ciphers=aes-ccm wpa2-pre-shared-key=123WiFi321<br />
</code></p>
<p>Задаём пароль админа<br />
<code>[admin@snake-mikrotik] > /user set 0 password=VeRy$tR0nGp@s$</code></p>
<p>NAT &#8211; он у нас будет один на всех<br />
<code>/ip firewall nat<br />
add action=masquerade chain=srcnat comment="NAT Internet" out-interface=ether1 src-address-list=internal-nets dst-address-list=!internal-nets</code></p>
<h2>2. Гостевой wifi (virtual ap, shaping, отдельная сеть)</h2>
<p>Т.к. стоит задача изолировать беспроводных клиентов от проводной сети, а их всех вместе &#8211; от гостевой, то сетей у нас будет три (можно и больше), с разными правилами доступа для каждой.<br />
Создаем виртуальную точку доступа и security profile<br />
<code>/interface wireless security-profiles<br />
add name=hs-ap-prof-nixman authentication-types=wpa2-psk group-ciphers=aes-ccm mode=dynamic-keys supplicant-identity=MikroTik unicast-ciphers=aes-ccm wpa2-pre-shared-key=WiFiPaSsWoRd<br />
/interface wireless<br />
add master-interface=wlan1 mode=ap-bridge name=hs-ap-nixman security-profile=hs-ap-prof-nixman ssid="Guest WiFi"</code></p>
<p>IP, DHCP-сервер<br />
<code><br />
/ip address<br />
add address=192.168.90.1/24 comment="Guest WiFi" interface=hs-ap-nixman network=192.168.90.0 arp=reply-only<br />
/ip pool<br />
add name=guest ranges=192.168.90.10-192.168.90.254<br />
/ip dhcp-server network<br />
add address=192.168.90.0/24 comment="guest wifi" dns-server=8.8.8.8 gateway=192.168.90.1<br />
/ip dhcp-server<br />
add address-pool=guest disabled=no interface=hs-ap-nixman lease-time=1h name=guest add-arp=yes<br />
</code></p>
<h2>3. Защищаем роутер</h2>
<p>Отключаем ненужные службы.<br />
<code>/ip service<br />
set telnet disabled=yes<br />
set ftp disabled=yes<br />
set api disabled=yes<br />
set api-ssl disabled=yes</code><br />
Для нужных &#8211; меняем порты (либо ограничиваем доступ только списком администраторов &#8211; см. правила фаервола ниже)<br />
<code>/ip service<br />
set www port=8080<br />
set ssh port=2222</code></p>
<p>Теперь настраиваем фаервол. Я воспользовался правилами от <a href="http://gregsowell.com/?p=4013" target="_blank" rel="noopener">Грега</a>, только немного изменив &#8220;под себя&#8221;. У вас, вполне вероятно, получится что-то своё.<br />
<code><br />
/ip firewall address-list<br />
#rfc 1918, loopback, мультикаст и прочие bogon networks<br />
add address=0.0.0.0/8 comment="" disabled=no list=rfc-1918<br />
add address=127.0.0.0/8 comment="" disabled=no list=rfc-1918<br />
add address=100.64.0.0/10 comment="" disabled=no list=rfc-1918<br />
add address=10.0.0.0/8 comment="" disabled=no list=rfc-1918<br />
add address=169.254.0.0/16 comment="" disabled=no list=rfc-1918<br />
add address=172.16.0.0/12 comment="" disabled=no list=rfc-1918<br />
add address=192.0.0.0/24 comment="" disabled=no list=rfc-1918<br />
add address=192.0.2.0/24 comment="" disabled=no list=rfc-1918<br />
add address=192.168.0.0/16 comment="" disabled=no list=rfc-1918<br />
add address=198.18.0.0/15 comment="" disabled=no list=rfc-1918<br />
add address=198.51.100.0/24 comment="" disabled=no list=rfc-1918<br />
add address=203.0.113.0/24 comment="" disabled=no list=rfc-1918<br />
add address=224.0.0.0/3 comment="" disabled=no list=rfc-1918 </p>
<p>#наш внешний адрес<br />
add address=X.X.X.X comment="" disabled=no list=public-add</p>
<p>#внутренние сети<br />
add address=192.168.88.0/24 comment="Servers" disabled=no list=internal-nets<br />
add address=192.168.88.0/24 comment="Servers" disabled=no list=servers<br />
add address=192.168.89.0/24 comment="LAN" disabled=no list=internal-nets<br />
add address=192.168.89.0/24 comment="LAN" disabled=no list=lan<br />
add address=192.168.90.0/24 comment="Guest WiFi" disabled=no list=internal-nets<br />
add address=192.168.90.0/24 comment="Guest WiFi" disabled=no list=guest</p>
<p>#Список доверенных адресов<br />
add address=Y.Y.Y.Y comment="" disabled=no list=admins</p>
<p>#Исключения для SMTP-сервера<br />
add address=192.168.88.5 comment="" disabled=no list=smtp-bypass</p>
<p>#DMZ<br />
add address=192.168.88.5 comment="" disabled=no list=dmz</p>
<p>/ip firewall filter<br />
#Защищаемся от icmp-flood<br />
add action=accept chain=input comment="start of greg rules up to 5 pings in 5 seconds" disabled=no limit=5,5 protocol=icmp<br />
add action=add-src-to-address-list address-list=icmp-attack address-list-timeout=12h chain=input comment="add all other icmp input into icmp-attack address list." \<br />
    disabled=no protocol=icmp<br />
add action=drop chain=input comment="drop excessive icmp traffic for 12 hours" disabled=no src-address-list=icmp-attack protocol=icmp<br />
add action=drop chain=forward comment="drop excessive icmp traffic for 12 hours" disabled=yes src-address-list=icmp-attack protocol=icmp</p>
<p>#Запрещаем снаружи сети, которых там быть не должно<br />
add action=drop chain=forward comment="block rfc 1918 and multicast inbound" disabled=no in-interface=ether1 src-address-list=rfc-1918<br />
add action=drop chain=forward comment="block our addressing inbound - spoofed" disabled=no in-interface=ether1 src-address-list=public-add<br />
add action=drop chain=input comment="block rfc 1918 and multicast inbound" disabled=no in-interface=ether1 src-address-list=rfc-1918<br />
add action=drop chain=input comment="block our addressing inbound - spoofed" disabled=no in-interface=ether1 src-address-list=public-add</p>
<p>#Защищаемся от сканирования портов и DoS-атак<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="add port scannes to port-scan list" disabled=no \<br />
    in-interface=ether1 protocol=tcp psd=21,3s,3,1 src-address-list=!internal-nets<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="NMAP FIN Stealth scan" disabled=no protocol=tcp \<br />
    tcp-flags=fin,!syn,!rst,!psh,!ack,!urg<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="SYN/FIN scan" disabled=no protocol=tcp tcp-flags=\<br />
    fin,syn<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="SYN/RST scan" disabled=no protocol=tcp tcp-flags=\<br />
    syn,rst<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="FIN/PSH/URG scan" disabled=no protocol=tcp tcp-flags=\<br />
    fin,psh,urg,!syn,!rst,!ack<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="ALL/ALL scan" disabled=no protocol=tcp tcp-flags=\<br />
    fin,syn,rst,psh,ack,urg<br />
add action=add-src-to-address-list address-list=port-scan address-list-timeout=2w chain=input comment="NMAP NULL scan" disabled=no protocol=tcp tcp-flags=\<br />
    !fin,!syn,!rst,!psh,!ack,!urg<br />
add action=tarpit chain=input comment="tarpit port-scan address list to router" disabled=no protocol=tcp src-address-list=port-scan<br />
add action=drop chain=input comment="drop port-scan address list to our router" disabled=no src-address-list=port-scan<br />
add action=drop chain=forward comment="drop port-scan address list to our infrastructure" disabled=no src-address-list=port-scan</p>
<p>#Разрешаем established и related<br />
add action=accept chain=input comment="allow established,related" connection-state=established,related<br />
add action=accept chain=forward comment="allow established,related" connection-state=established,related</p>
<p>#Разрешаем доступ администраторам (если вы меняли порты для служб, здесь тоже нужно поменять)<br />
add action=accept chain=input comment="allow management for admins" disabled=no dst-port=8291,22,80 protocol=tcp src-address-list=admins</p>
<p>#Ограничиваем число коннектов наружу для SMTP. SMTP-серверу можно больше, чем другим<br />
add action=accept chain=forward comment="allow smtp-bypass list to create multiple sessions" disabled=no dst-port=25 protocol=tcp src-address-list=smtp-bypass<br />
add action=drop chain=forward comment="drop smtp traffic marked as spam" disabled=no dst-port=25 protocol=tcp src-address-list=spam-block<br />
add action=add-src-to-address-list address-list=spam-block address-list-timeout=2h chain=forward comment=\<br />
    "more than 5 smtp connections out as spam.  add to address list" connection-limit=30,32 disabled=no dst-port=25 limit=50,5 protocol=tcp \<br />
    src-address-list=rfc-1918</p>
<p>#Запрещаем локалке и серверам ходить в гостевую сеть<br />
add action=drop chain=forward comment="deny from LAN,SERVERS to GUEST" src-address-list=internal-nets dst-address-list=guest<br />
#Гостевой сети можно ходить только в интернет, и совсем нельзя в локалку и к серверам<br />
add action=drop chain=forward comment="deny from GUEST to LAN,SERVERS" src-address-list=guest dst-address-list=internal-nets<br />
#Сервера и локалка могут общаться без ограничений, но из локалки нельзя ходить на почтовый сервер по ssh<br />
add action=drop chain=forward comment="Deny SSH to mailserver" src-address-list=internal-nets dst-address-list=dmz<br />
add action=accept chain=forward comment="accept from LAN,SERVERS to LAN,SERVERS" src-address-list=internal-nets dst-address-list=internal-nets<br />
#Сервера и локалка могут ходить в интернет<br />
add action=accept chain=forward comment="deny from LAN,SERVERS to INTERNET" src-address-list=internal-nets dst-address-list=!internal-nets<br />
#Сервера и локалка могут спрашивать у микротика DNS и NTP<br />
add action=accept chain=input comment="allow DNS, NTP for LAN,SERVERS" src-address-list=lan protocol=udp dst-port=53,123<br />
add action=accept chain=input comment="allow DNS, NTP for LAN,SERVERS" src-address-list=servers protocol=udp dst-port=53,123</p>
<p>#Снаружи можно зайти в DMZ<br />
add action=accept chain=input dst-address-list=public-add dst-port=80,443,25,587,465,995 protocol=tcp<br />
add action=accept chain=forward dst-address-list=dmz connection-nat-state=dstnat dst-port=80,443,25,587,465,995 protocol=tcp</p>
<p>#Запрещаем несанкционированную активность<br />
add action=drop chain=forward comment="block disallowed forward" disabled=no<br />
add action=drop chain=input comment="block inbound traffic from everyone else" disabled=no<br />
</code></p>
<p>Теперь настраиваем NAT. Помимо обычного маскарадинга (его мы настроили выше) нам еще нужно сделать проброс портов к нашему почтовому серверу в DMZ.<br />
<code>/ip firewall nat<br />
add action=dst-nat chain=dstnat comment="HTTPS" dst-address-list=public-add dst-port=443 protocol=tcp to-addresses=192.168.88.5 to-ports=443<br />
add action=dst-nat chain=dstnat comment="HTTP" dst-address-list=public-add dst-port=80 protocol=tcp to-addresses=192.168.88.5 to-ports=80<br />
add action=dst-nat chain=dstnat comment="Mail" dst-address-list=public-add dst-port=25 protocol=tcp to-addresses=192.168.88.5 to-ports=25<br />
add action=dst-nat chain=dstnat comment="Mail" dst-address-list=public-add dst-port=465 protocol=tcp to-addresses=192.168.88.5 to-ports=465<br />
add action=dst-nat chain=dstnat comment="Mail" dst-address-list=public-add dst-port=587 protocol=tcp to-addresses=192.168.88.5 to-ports=587<br />
add action=dst-nat chain=dstnat comment="Mail" dst-address-list=public-add dst-port=995 protocol=tcp to-addresses=192.168.88.5 to-ports=995<br />
</code><br />
В заключение &#8211; отключаем mac-telnet и neighbor discovery. При желании можете оставить для проводной сети, но только если вы твёрдо уверены, что вам оно нужно.<br />
<code>/ip neighbor discovery settings set default=n default-for-dynamic=no</code></p>
<p><code>[admin@snake-mikrotik] > /tool mac-server mac-winbox print<br />
Flags: X - disabled, * - default<br />
 #    INTERFACE<br />
 0 X* all<br />
 1    ether2-master-local<br />
 2    ether3-slave-local<br />
 3    ether4-slave-local<br />
 4    ether5-slave-local<br />
 5    wlan1<br />
 6    bridge-local<br />
[admin@snake-mikrotik] > /tool mac-server mac-winbox set 1,2,3,4,5,6 disabled=y</code></p>
<p><code>[admin@snake-mikrotik] > /tool mac-server print<br />
Flags: X - disabled, * - default<br />
 #    INTERFACE<br />
 0 X* all<br />
 1    ether2-master-local<br />
 2    ether3-slave-local<br />
 3    ether4-slave-local<br />
 4    ether5-slave-local<br />
 5    wlan1<br />
 6    bridge-local<br />
[admin@snake-mikrotik] > /tool mac-server set 1,2,3,4,5,6 disabled=y</code><br />
На этом всё. Надеюсь, руководство окажется для вас полезным.</p>
<p>The post <a href="https://nixman.info/?p=2752">Mikrotik для небольшого офиса</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2752</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Yet another debootstrap manual</title>
		<link>https://nixman.info/?p=2759</link>
					<comments>https://nixman.info/?p=2759#respond</comments>
		
		<dc:creator><![CDATA[snakeslair]]></dc:creator>
		<pubDate>Wed, 15 Mar 2017 06:36:25 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[apt]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[debootstrap]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">http://nixman.info/?p=2759</guid>

					<description><![CDATA[<p>Казалось бы мануалов по debootstrap чуть более, чем достаточно, зачем нужен ещё один? Для себя я скажу, что некоторые вещи показались мне неоднозначными, кое-какие &#8220;умолчания&#8221; пришлось додумывать самому. Поэтому и родилась идея сделать шпаргалку &#8220;на будущее&#8221;, авось ещё кому пригодится. Диспозиция: dedicated-сервер с одним диском, загруженный с rescue CD. Задача: сделать lvm, разметить диск нужным&#8230;</p>
<p>The post <a href="https://nixman.info/?p=2759">Yet another debootstrap manual</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Казалось бы мануалов по debootstrap чуть более, чем достаточно, зачем нужен ещё один?<br />
Для себя я скажу, что некоторые вещи показались мне неоднозначными, кое-какие &#8220;умолчания&#8221; пришлось додумывать самому. Поэтому и родилась идея сделать шпаргалку &#8220;на будущее&#8221;, авось ещё кому пригодится.</p>
<p><span id="more-2759"></span><br />
Диспозиция: dedicated-сервер с одним диском, загруженный с rescue CD. Задача: сделать lvm, разметить диск нужным нам образом и поставить чистую операционку (Debian Jessie).</p>
<h2>Шаг 1. Собираем lvm</h2>
<p>Размечаем диск. Не забываем установить правильный partition type и загрузочный флаг.<br />
<code><br />
Command (m for help): p<br />
Disk /dev/sda: 1,8 TiB, 2000398934016 bytes, 3907029168 sectors<br />
Units: sectors of 1 * 512 = 512 bytes<br />
Sector size (logical/physical): 512 bytes / 512 bytes<br />
I/O size (minimum/optimal): 512 bytes / 512 bytes<br />
Disklabel type: dos<br />
Disk identifier: 0x472be2a1</p>
<p>Device     Boot  Start        End    Sectors  Size Id Type<br />
/dev/sda1  *      2048     526335     524288  256M 83 Linux<br />
/dev/sda2       526336 3907029167 3906502832  1,8T 8e Linux LVM<br />
</code></p>
<p>Создаём lvm<br />
<code>pvcreate /dev/sda2<br />
vgcreate vgstorage  /dev/sda2<br />
lvcreate -L20G -n lvroot vgstorage<br />
lvcreate -L20G -n lvvar vgstorage<br />
lvcreate -L1G -n lvswap vgstorage<br />
lvcreate -l100%FREE -n lvhome vgstorage<br />
vgchange -a y vgstorage<br />
</code></p>
<p>Создаем файловые системы.<br />
<code>mkfs.ext2 /dev/sda1<br />
mkfs.ext4 /dev/vgstorage/lvroot<br />
mkfs.ext4 /dev/vgstorage/lvvar<br />
mkfs.ext4 /dev/vgstorage/lvhome<br />
</code></p>
<h2>Шаг 2. Ставим систему</h2>
<p>Пишем скрипт, который поставит нам систему. Я воспользовался скриптами уважаемго <a href="https://github.com/derlaft/debootstrap.sh" target="_blank" rel="noopener">@derlaft</a>, за что ему большое спасибо, и немного изменил их под себя.<br />
Скрипт можно положить, например, в /root </p>
<p>install.sh<br />
<code><br />
#!/bin/bash</p>
<p>ARCH=amd64</p>
<p>#Ставим актуальный стабильный релиз<br />
#На момент написания статьи это был Jessie 8.7<br />
OS=debian<br />
DISTRO=stable</p>
<p>## место для установки системы<br />
TARGET=/mnt/debian<br />
export $TARGET</p>
<p>##Ставить будем с зеркала в интернете<br />
debootstrap --include=sudo,nano,wget --arch $ARCH $DISTRO $TARGET http://deb.debian.org/$OS/</p>
<p>## строчки ниже трогать не нужно, они монтируют системные директории в новый /<br />
mount -o bind /dev $TARGET/dev<br />
mount -o bind /sys $TARGET/sys<br />
</code></p>
<p>Создаем окружение для установки системы<br />
<code>mkdir /mnt/debian<br />
mkdir /mnt/debian/boot<br />
mkdir /mnt/debian/home<br />
mkdir /mnt/debian/var<br />
mount /dev/vgstorage/lvroot /mnt/debian<br />
mount /dev/sda1 /mnt/debian/boot<br />
mount /dev/vgstorage/lvvar /mnt/debian/var<br />
mount /dev/vgstorage/lvhome /mnt/debian/home<br />
</code></p>
<p>Теперь просто запускаем скрипт:<br />
<code>bash ./install.sh<br />
</code></p>
<p>Система скачана и установлена. Теперь делаем ещё один скрипт, который поставит нам ядро, загрузчик и некоторые доп. пакеты.<br />
Его можно сразу поместить в $TARGET, чтобы было удобнее запускать из chroot</p>
<p>postinst.sh<br />
<code><br />
#!/bin/bash<br />
## обновление индекса репозитария<br />
apt-get update<br />
## настройка часовых поясов<br />
dpkg-reconfigure tzdata<br />
## монтирование файловых систем<br />
mount -t proc /proc /proc<br />
mount -a</p>
<p>## установка hostname, обязательный шаг<br />
HOST='mysuperhost'</p>
<p>echo "$HOST" > /etc/hostname<br />
echo -e "\n127.0.0.1 localhost $HOST" >> /etc/hosts</p>
<p>## добавление пользователя, добавление его в sudo<br />
USER='myfirstuser'</p>
<p>echo 'Добавление пользователя'</p>
<p>adduser $USER<br />
usermod -a -G sudo $USER</p>
<p>## установка пароля root<br />
echo 'Установка пароля root'<br />
passwd</p>
<p>## установка ядра и загрузчика<br />
ARCH=amd64 #варианты: i386, i486, i686, amd64</p>
<p>## Необходиме для сервера Debian пакеты. У вас список может быть свой:<br />
apt-get -y install linux-base linux-image-$ARCH grub-pc lvm2 sudo openssh-server aptitude</p>
<p>## Завершающий этап - установка загрузчика:<br />
grub-install /dev/sda<br />
update-grub<br />
</code></p>
<p>Запускается скрипт командой:<br />
<code>env LANG=C env HOME=/root chroot $TARGET /bin/bash /postinst.sh</code></p>
<p>Осталось немного:<br />
Добавляем информацию в /etc/fstab<br />
<code><br />
/dev/sda1       /boot           ext2        defaults        0       0<br />
/dev/mapper/vgstorage-lvroot       /               ext4        errors=remount-ro,relatime        0       1<br />
/dev/mapper/vgstorage-lvhome       /home           ext4        defaults ,relatime       0       2<br />
/dev/mapper/vgstorage-lvvar       /var           ext4        defaults        0       0<br />
/dev/mapper/vgstorage-lvswap       none            swap        sw              0       0<br />
proc		/proc	proc	defaults		0	0<br />
sysfs		/sys	sysfs	defaults		0	0<br />
tmpfs		/dev/shm	tmpfs	defaults	0	0<br />
devpts		/dev/pts	devpts	defaults	0	0<br />
</code><br />
Настраиваем сеть (в простейшем случае это будет dhcp, однако, бывает всякое)<br />
/etc/network/interfaces<br />
<code><br />
auto lo<br />
iface lo inet loopback</p>
<p>auto eth0<br />
iface eth0 inet dhcp<br />
</code><br />
Наконец, настраиваем /etc/apt/sources.list<br />
<code><br />
deb http://deb.debian.org/debian stable main</p>
<p>deb http://deb.debian.org/debian/ jessie main contrib non-free<br />
deb-src http://deb.debian.org/debian/ jessie main contrib non-free</p>
<p>deb http://security.debian.org/ jessie/updates main<br />
deb-src http://security.debian.org/ jessie/updates main</p>
<p># jessie-updates, previously known as 'volatile'<br />
deb http://deb.debian.org/debian/ jessie-updates main contrib non-free<br />
deb-src http://deb.debian.org/debian/ jessie-updates main contrib non-free</p>
<p># jessie-backports<br />
deb http://deb.debian.org/debian/ jessie-backports main contrib non-free<br />
deb-src http://deb.debian.org/debian/ jessie-backports main contrib non-free<br />
</code></p>
<p>Выходим из chroot, перезагружаемся. После ребута нас должна встретить свежеустановленная система <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><a href="https://habrahabr.ru/post/147522/" target="_blank" rel="noopener">Пост</a> на хабре, который был источником вдохновения</p>
<p>The post <a href="https://nixman.info/?p=2759">Yet another debootstrap manual</a> appeared first on <a href="https://nixman.info">Логово (а)социальной твари</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://nixman.info/?feed=rss2&amp;p=2759</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>