<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Компы и автомобили (Posts about FreeBSD)</title><link>https://at-hacker.in/</link><description></description><atom:link href="https://at-hacker.in/categories/freebsd.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:"&gt;at-hacker&lt;/a&gt; </copyright><lastBuildDate>Sat, 16 May 2026 20:41:21 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Пофиксили баг в pf на FreeBSD</title><link>https://at-hacker.in/posts/pofiksili-bag-v-pf-na-freebsd/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;На выходных пришло оповещение, что баг, про который я &lt;a href="https://at-hacker.in/posts/bag-v-fayrvole-pf/"&gt;писал в прошлом году, починили:&lt;/a&gt;&lt;a href="https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=201519"&gt;https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=201519&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Пока только для releng/10.3&lt;/p&gt;</description><category>FreeBSD</category><guid>https://at-hacker.in/posts/pofiksili-bag-v-pf-na-freebsd/</guid><pubDate>Tue, 24 May 2016 09:28:00 GMT</pubDate></item><item><title>pf и ipfw одновременно — последовательность обработки пакетов</title><link>https://at-hacker.in/posts/fayrvoly-pf-i-ipfw-odnovremenno-posledovatelnost-obrabotki-paket/</link><dc:creator>at-hacker</dc:creator><description>&lt;h3&gt;Вводная информация. Зачем нужны два файрвола.&lt;/h3&gt;
&lt;p&gt;Так исторически сложилось, что на ряде FreeBSD-серверов в конторе мы используем одновременно два файрвола. Иногда это связано с ограничением функционала, иногда — с багами в работе конкретного файрвола.&lt;/p&gt;
&lt;p&gt;Например, на pf гораздо проще организовать NAT в несколько внешних IP, причём разбрасывать клиентов по IP он может разными алгоритмами. Мы используем source hash — когда файрвол выбирает IP, в который будет NATиться конкретный пользователь, исходя из IP-адреса этого пользователя. Т. е. в рамках одной PPPoE-сессии конкретный клиент всегда будет ходить с одного и того же IP.&lt;/p&gt;
&lt;p&gt;Или, например, у pf есть возможность ограничивать количество соединений в секунду. Так мы блокируем активность ботов по рассылке спама на пользовательских компах — число соединений с одного пользовательского IP на любой 25-ый порт в интернете ограничено не более чем 10 соединений в 30 секунд. Если пользователь превышает этот лимит — его IP заносится в табличку и ему доступ к любому 25-му порту блокируется на 1 час. По истечении часа скрипт очищает эту табличку, и всё начинается заново.&lt;/p&gt;
&lt;p&gt;Но есть у pf и проблемы. Например, у него до сих пор нет connection tracker'a для протокола PPTP. Что делает невозможным использование пользователями PPTP-туннелей. Точнее, не так. Пользователь может юзать PPTP-туннель, но это доступно будет только одному пользователю на конкретном BRAS'e. Соответственно — кто раньше туннель установил, того и тапки. У остальных туннели работать уже не будут — файрвол не в состоянии отличить идущие внутри туннеля пакеты и правильно раскидать их по пользователям. Поэтому задачу NAT'a PPTP и GRE трафика мы решаем с помощью IPFW.&lt;/p&gt;
&lt;p&gt;Также в процессе эксплуатации в файрволе pf выявилось несколько багов. Про один я уже &lt;a href="https://at-hacker.in/posts/bag-v-fayrvole-pf/"&gt;писал&lt;/a&gt;, про второй написать пока только планирую. Коротко — суть бага в том, что при использовании в pf правила route-to для пакетов, пришедших через PPPoE и прошедших NAT криво просчитывается контрольная сумма. Старший и младший байт контрольной суммы меняются местами (т. е. если сумма должна быть 0xABDC, то в результирующем пакете после обработки его PF контрольная сумма проставлялась 0xCDAB), и получатель такого пакета его просто молча дропает. Поэтому этот функционал также пришлось запилить на IPFW., про второй написать пока только планирую. Коротко — суть бага в том, что при использовании в pf правила route-to для пакетов, пришедших через PPPoE и прошедших NAT криво просчитывается контрольная сумма. Старший и младший байт контрольной суммы меняются местами (т. е. если сумма должна быть 0xABDC, то в результирующем пакете после обработки его PF контрольная сумма проставлялась 0xCDAB), и получатель такого пакета его просто молча дропает. Поэтому этот функционал также пришлось запилить на IPFW.&lt;/p&gt;
&lt;h3&gt;К чему я это всё?&lt;/h3&gt;
&lt;p&gt;А вот к чему. Когда используешь два файрвола одновременно, то возникает вопрос последовательности обработки пакетов файрволами, чтобы правила одного файрвола не мешали работать правилам другого файрвола. Поэтому в какой-то момент пришлось разбираться с тем, как всё это работает.&lt;/p&gt;
&lt;h3&gt;Как это работает&lt;/h3&gt;
&lt;p&gt;Было бы логично предположить, что последовательность обработки пакетов двумя файрволами будет зависеть от последовательности загрузки соответствующих модулей ядра. Но, как говорит наш школьный физик: «Мысль хорошая. Но неправильная». На самом деле, последовательность обработки будет зависеть от того, в какой последовательности файрволы встраивают свои обработчики (hooks) в цепочки обработчиков фреймворка pfil (подробности можно почитать в &lt;em&gt;man 9 pfil&lt;/em&gt;). Эти цепочки представляют собой очереди, отдельно для обработки входящих пакетов, и отдельно — для исходящих.). Эти цепочки представляют собой очереди, отдельно для обработки входящих пакетов, и отдельно — для исходящих.&lt;/p&gt;
&lt;p&gt;Причём каждый файрвол вставляет свой обработчик в цепочку в разные моменты своей загрузки. IPFW вставляет сразу при загрузке модуля, а pf при загрузке модуля ничего не делает, и встраивает обработчик только когда мы говорим &lt;em&gt;pfctl -e&lt;/em&gt;, т. е. собственно включаем файрвол., т. е. собственно включаем файрвол.&lt;/p&gt;
&lt;p&gt;Соответственно, если посмотреть на &lt;em&gt;rcoderd&lt;/em&gt;, то файрволы грузятся в следующем порядке:, то файрволы грузятся в следующем порядке:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="gh"&gt;#&lt;/span&gt; rcorder /etc/rc.d/* |  grep -nE '/i?pfw?$'
41:/etc/rc.d/pf
57:/etc/rc.d/ipfw
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Соответственно, в этом случае обработка будет происходить так:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://at-hacker.in/assets/images/pf_ipfw_rc.png"&gt;&lt;/p&gt;
&lt;p&gt;Как следует из картинки, при стандартной схеме загрузки файрволов &lt;strong&gt;для входящих пакетов&lt;/strong&gt; первым будет отрабатывать IPFW, а для  первым будет отрабатывать IPFW, а для &lt;strong&gt;исходящих&lt;/strong&gt; первым будет работать PF. первым будет работать PF.&lt;/p&gt;
&lt;p&gt;Также нужно понимать, что если вы перезапустите файрвол pf, то последовательность обработки поменяется, так как в момент останова pf уберёт обработчики из очереди, а при запуске опять вставит их, но уже вот так:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://at-hacker.in/assets/images/pf_ipfw1.png"&gt;&lt;/p&gt;
&lt;p&gt;Соответственно, входящие пакеты первым будут попадать в PF, а исходящие — сначала обрабатываться IPFW.&lt;/p&gt;
&lt;p&gt;Так что нужно понимать, что и в каком порядке обрабатывается, где у вас выполняется NAT (и для каких пакетов — входящих или исходящих), и учитывать это взаимное влияние при написании конфигурации файрволов.&lt;/p&gt;
&lt;p&gt;При желании, можно изменить порядок начальной инициализации файрволов таким образом, чтобы IPFW стартовал первым. Для этого не обязательно править &lt;em&gt;rcorder&lt;/em&gt;, достаточно в /, достаточно в /&lt;em&gt;boot/loader.conf&lt;/em&gt; вписать загрузку модуля IPFW. Пользуясь тем, что IPFW ставит свои обработчики при загрузке модуля, получится, что IPFW будет стартовать первым. вписать загрузку модуля IPFW. Пользуясь тем, что IPFW ставит свои обработчики при загрузке модуля, получится, что IPFW будет стартовать первым.&lt;/p&gt;</description><category>FreeBSD</category><category>IPFW</category><category>PF</category><category>Tips&amp;Tricks</category><category>Файрвол</category><guid>https://at-hacker.in/posts/fayrvoly-pf-i-ipfw-odnovremenno-posledovatelnost-obrabotki-paket/</guid><pubDate>Thu, 29 Oct 2015 12:01:00 GMT</pubDate></item><item><title>Время, вперёд!</title><link>https://at-hacker.in/posts/vremya-vperyod/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;Коллега недавно наткнулся на забавный косяк. Прописывает он задание в кроне, а оно не отрабатывает. Он уже и так, и так, и всё проверил — в логах запись об очередном запуске других (периодических) заданий крона есть, а его задание не отрабатывает.&lt;/p&gt;
&lt;p&gt;Полезли смотреть всей толпой. Выявили, что в логах факт отработки крона логируется с указанием времени, на час опережающем текущее. Т. е. если, например, выполнить &lt;em&gt;date&lt;/em&gt;, то получаем 17 часов, а крон в лог пишет, что запустился в 18 часов. Вспомнили, что мы этот сервак не перезагружали после обновления time zone data. Я сделал , то получаем 17 часов, а крон в лог пишет, что запустился в 18 часов. Вспомнили, что мы этот сервак не перезагружали после обновления time zone data. Я сделал &lt;em&gt;service syslogd restart&lt;/em&gt;. Смотрю в логи — ну, вроде как факт очередного редактирования crontab записался с правильным временем . Должно задание отработать. Однако нифига :-) В логах стало вот так:. Смотрю в логи — ну, вроде как факт очередного редактирования crontab записался с правильным временем . Должно задание отработать. Однако нифига :-) В логах стало вот так:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;lesnoy&lt;/span&gt; &lt;span class="n"&gt;crontab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63631&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;BEGIN&lt;/span&gt; &lt;span class="n"&gt;EDIT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="n"&gt;crontab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63631&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;REPLACE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="n"&gt;crontab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63631&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;END&lt;/span&gt; &lt;span class="n"&gt;EDIT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="n"&gt;crontab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63646&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;BEGIN&lt;/span&gt; &lt;span class="n"&gt;EDIT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;52&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="n"&gt;crontab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63646&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;END&lt;/span&gt; &lt;span class="n"&gt;EDIT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sbin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;992&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RELOAD&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tabs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="n"&gt;crontab&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63677&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LIST&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sbin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63721&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libexec&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;entropy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Oct&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt; &lt;span class="n"&gt;vpn2&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sbin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;cron&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;63763&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;libexec&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;atrun&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Т. е. время скачет очень внезапно :-) Перезапуск крона этот вопрос решил, и время везде синхронизировалось. Т. е. задание не отрабатывало потому, что коллега устанавливал срабатывание задания на 17 часов, а крон считал, что уже 18 часов.&lt;/p&gt;</description><category>FreeBSD</category><category>Troubleshooting</category><category>Администрирование</category><guid>https://at-hacker.in/posts/vremya-vperyod/</guid><pubDate>Fri, 23 Oct 2015 18:31:00 GMT</pubDate></item><item><title>Баг в файрволе pf</title><link>https://at-hacker.in/posts/bag-v-fayrvole-pf/</link><dc:creator>at-hacker</dc:creator><description>&lt;h3&gt;Предисловие&lt;/h3&gt;
&lt;p&gt;В конторе мы вынужденно используем FreeBSD 9.3 на BRAS'ах. Вызвано это тем, что на 10-ой фре есть какой-то косяк с mpd (у нас с его помощью PPPoE-соединения от клиентов обслуживаются). И mpd периодически виснет при значительном изменении числа подключений. Т. е. когда много клиентов одновременно подключается или отключается, &lt;a href="https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=186114"&gt;mpd зависает в состоянии umtxn&lt;/a&gt;. Я писал по этому поводу в уже открытый PR, но движухи по нему нет.. Я писал по этому поводу в уже открытый PR, но движухи по нему нет.&lt;/p&gt;
&lt;h3&gt;О проблеме&lt;/h3&gt;
&lt;p&gt;Но речь не об этом. В общем, на фре 9.3 в файрволе pf обнаружился занятный баг. Баг относится к работе NAT на pf. Проявляется так:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Клиент шлёт через NAT запрос на какой-то сервер в интернете;&lt;/li&gt;
&lt;li&gt;Сервер ему отвечает;&lt;/li&gt;
&lt;li&gt;Но за время ответа у клиента этот порт, с которого он отправлял свой запрос, почему-то закрылся;&lt;/li&gt;
&lt;li&gt;Клиент примет пакет от сервера и ответит серверу ICMP пакетом с типом &lt;em&gt;port unreachable&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Тут-то и проявляется баг — pf'овский NAT некорректно натит этот ответный ICMP-пакет, и в итоге с внешнего интерфейса улетает ICMP-пакет с серым SRC IP клиента и белым DST IP того сервера, куда этот пакет должен быть доставлен.&lt;/p&gt;
&lt;p&gt;Т. е. допустим, у вас адрес NAT-интерфейса — 1.1.1.1, адрес сервера в интернете 2.2.2.2. И адрес клиента 192.168.0.1. В итоге с ВНЕШНЕГО интерфейса NAT'a улетит пакет с адреса 192.168.0.1 на адрес 2.2.2.2. Т. е. трансляции адреса клиента во внешний адрес NAT (1.1.1.1) не произойдёт.&lt;/p&gt;
&lt;h3&gt;Кровавые подробности&lt;/h3&gt;
&lt;p&gt;Если быть совсем точным, то трансляция ICMP-пакета таки происходит. Но не везде и не до конца :-)&lt;/p&gt;
&lt;h4&gt;Немного теории&lt;/h4&gt;
&lt;p&gt;ICMP-пакеты подразделяются на несколько типов. Причём в каждом типе есть ещё несколько подтипов. В данном случае клиент генерирует пакет типа 3 «destination unreachable». И подтипа тоже 3 — «port unreacable». Подробности можно почитать в man icmp, там есть табличка с типами и подтипами (подтипы называются codes, коды). В пакет типа port unreacahble клиент вкладывает заголовок того пакета, который вызвал генерацию сообщения ICMP «port unrecahable» (назовём для краткости такой пакет «пакетом-инициатором»). Ну, чтобы сервер, получивший от клиента ICMP destination unreachable понимал, на какой конкретно его пакет клиент ответил, что порт недоступен. И вот расследование показало, что как раз этот заголовок, пакета-инициатора транслируется файрволом нормально. Но сам ICMP-пакет — нет.&lt;/p&gt;
&lt;h4&gt;Суровая практическая реальность&lt;/h4&gt;
&lt;p&gt;Итак, мы приняли, что локальный IP клиента у нас 192.168.0.1, а внешний IP, в который NAT'ится клиентский трафик — 1.1.1.1. Таким образом, получается примерно такой формат ICMP-пакета от клиента обратно на сервер 2.2.2.2 (до трансляции):&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tr&gt;
&lt;td&gt;Заголовок ICMP&lt;/td&gt;
&lt;td&gt;SRC IP: 192.168.0.1&lt;/td&gt;
&lt;td&gt;DST IP: 2.2.2.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Заголовок пакета-инициатора&lt;/td&gt;
&lt;td&gt;SRC IP: 2.2.2.2 port 80&lt;/td&gt;
&lt;td&gt;DST IP: 192.168.0.1 port 12345&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;То есть, клиент со своего адреса 192.168.0.1 оповещает сервер 2.2.2.2, что типа, «бро, ты мне отправил пакет со своего IP 2.2.2.2 и порта 80 на мой адрес 192.168.0.1 и порт 12345. Ну так вот, довожу до твоего сведения, что этот порт у меня закрыт».&lt;/p&gt;
&lt;p&gt;После трансляции через NAT пакет должен модифицироваться следующим образом:&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tr&gt;
&lt;td&gt;Заголовок ICMP&lt;/td&gt;
&lt;td&gt;SRC IP: 1.1.1.1&lt;/td&gt;
&lt;td&gt;DST IP: 2.2.2.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Заголовок пакета-инициатора&lt;/td&gt;
&lt;td&gt;SRC IP: 2.2.2.2 port 80&lt;/td&gt;
&lt;td&gt;DST IP: 1.1.1.1 port 54321&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;То есть, NAT уже от своего имени проговаривает серверу 2.2.2.2: «бро, ты мне отправил пакет со своего IP 2.2.2.2 и порта 80 на мой адрес 1.1.1.1 и порт 54321. Ну так вот, довожу до твоего сведения, что этот порт у меня закрыт».&lt;/p&gt;
&lt;p&gt;Обращаю внимание, что порт на клиентской стороне ДО и ПОСЛЕ трансляции могут отличаться. Т. е. то, что у клиента слушает на порту 12345, на NAT'е будет на порту 54321 (ну, или на любом другой, который будет свободен на момент установки соединения клиентом, и который NAT выберет для трансляции). Ну это так, для сведения, сейчас это роли не играет.&lt;/p&gt;
&lt;p&gt;Так вот, из-за бага в pf пакет транслируется следующим образом:&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tr&gt;
&lt;td&gt;Заголовок ICMP&lt;/td&gt;
&lt;td&gt;SRC IP: 192.168.0.1&lt;/td&gt;
&lt;td&gt;DST IP: 2.2.2.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Заголовок пакета-инициатора&lt;/td&gt;
&lt;td&gt;SRC IP: 2.2.2.2 port 80&lt;/td&gt;
&lt;td&gt;DST IP: 1.1.1.1 port 54321&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Т. е. NAT в pf транслирует только заголовок пакета-инициатора, идущий нагрузкой в ICMP-пакете типа «destination unreachable», но не транслирует заголовок самого ICMP-пакета.&lt;/p&gt;
&lt;h3&gt;Заключение&lt;/h3&gt;
&lt;p&gt;Написал сообщение в рассылку freebsd-net. Там товарищ Kristof Provost попросил проверить, есть ли такое же поведение в -CURRENT, и если да, то он посмотрит, в чём там проблема. Ну, соберу -CURRENT на досуге, попробую.&lt;/p&gt;
&lt;p&gt;А, кстати, ещё один момент. pf не только некорректно натит такие пакеты, но и также не может блокировать этот трафик. Т. е. правило вида&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;block out quick inet proto icmp from 192.168.0.0/24 to any
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;тоже не работает для таких пакетов. Похоже, pf анализирует только содержащийся в нагрузке заголовок пакета-инициатора, а не самого ICMP-пакета.&lt;/p&gt;
&lt;h3&gt;UPDATE&lt;/h3&gt;
&lt;p&gt;Собрал -CURRENT, проверил. Это поведение полностью повторяется и в -CURRENT. Нарисовал багрепорт по этому поводу, авось когда-нибудь починят. На текущий момент подобный пытающийся улететь наружу трафик блокируется с помощью IPFW.&lt;/p&gt;</description><category>FreeBSD</category><category>Troubleshooting</category><category>Администрирование</category><guid>https://at-hacker.in/posts/bag-v-fayrvole-pf/</guid><pubDate>Wed, 08 Jul 2015 11:25:00 GMT</pubDate></item><item><title>Виртуализация FreeBSD на Hyper-V</title><link>https://at-hacker.in/posts/virtualizaciya-freebsd-na-hyper-v/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;Решил побаловаться с SCVMM 2012 R2, посмотреть, что это такое и с чем его едят. Развернул два хоста с Hyper-V Server 2012 R2, и один хост с Win2012 R2 под общее хранилище кластера виртуализации.&lt;/p&gt;
&lt;p&gt;Первым делом поставил в виртуалку фрю, чтобы посмотреть, как оно себя там чувствует. Оказалось, что чувствует фря себя там относительно неплохо. Прямо из коробки есть синтетический сетевой, и синтетический же дисковый адаптер. Правда, с последним возник касичок, о чём и пойдёт речь ниже.&lt;/p&gt;
&lt;p&gt;Суть косяка в том, что фря видит ДВА диска там, где по факту он всего один. На этапе установки это выглядит так:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://at-hacker.in/assets/images/device_selection.png"&gt;&lt;/p&gt;
&lt;p&gt;Я выбрал при установке da0, и поставил систему туда, и всё отлично заработало. Но решил разобраться, в чём тут дело. Первое предположение было, что фря видит два диска из-за проблем в драйвере. И ada0 — это эмулируемый дисковый контроллер, а da0 — синтетический. Гуглинг ничего не показал, кроме указаний на &lt;a href="http://blogs.msdn.com/b/kylie/archive/2014/12/25/running-freebsd-on-hyper-v.aspx"&gt;статью в MSDN&lt;/a&gt;. Но там никакого внимания этой проблеме не уделено, просто скриншот (это как раз он выше) представлен, и всё. И пользователь в комментариях задаёт вопрос, типа, «why attached virtual disk to guest is visible twice? It's visiblle as ada0 and da0». Или, иными словами, а почему диск виден дважды под разными именами? Но ответа на этот вопрос не последовало.. Но там никакого внимания этой проблеме не уделено, просто скриншот (это как раз он выше) представлен, и всё. И пользователь в комментариях задаёт вопрос, типа, «why attached virtual disk to guest is visible twice? It's visiblle as ada0 and da0». Или, иными словами, а почему диск виден дважды под разными именами? Но ответа на этот вопрос не последовало.&lt;/p&gt;
&lt;p&gt;Больше никакой информации найти не удалось, поэтому я решил написать команде разработчиков в Microsoft, которые пилят поддержку гостевых компонентов Hyper-V во фре. Написал безо всякой надежды на ответ, однако на следующий день мне ответили.&lt;/p&gt;
&lt;p&gt;В общем, по итогам общения выяснилось, что действительно, два диска представляют по сути один диск, но видимый через разные дисковые контроллеры. ada0 — это эмулируемый контроллер, da0 — синтетический. Разработчики рекомендовали использовать da0, так как будет выше производительность и ниже нагрузка на процессор. И можно слегка поправить исходники соответствующего модуля, чтобы система перестала видеть диск ada0 вообще, и остался только da0. Для этого нужно сделать следующее: в файле /&lt;em&gt;usr/src/sys/dev/hyperv/stordisengage/hv_ata_pci_disengage.c&lt;/em&gt; необходимо найти функцию необходимо найти функцию &lt;em&gt;v_ata_pci_probe()&lt;/em&gt;, и заменить в ней возвращаемое значение (return value) с BUS_PROBE_DEFAULT на BUS_PROBE_VENDOR. После этого пересобрать и установить ядро. Я проделал это, и проблема исчезла., и заменить в ней возвращаемое значение (return value) с BUS_PROBE_DEFAULT на BUS_PROBE_VENDOR. После этого пересобрать и установить ядро. Я проделал это, и проблема исчезла.&lt;/p&gt;
&lt;p&gt;Также был затронут вопрос про KVP daemon. Это процесс, который умеет из гостевой фри общаться с гипервизором, и принимать/передавать туда-сюда key-values pairs. Т. е. какие-то параметры конфигурации. В частности, он используется для того, чтобы в Hyper-V manager можно было видеть IP-адрес, который имеет гостевая фря. И, по слухам, также может получать статические IP из пула, назначаемого из SCVMM, и прописывать его в гостевую систему. Но это я ещё не проверял, поэтому не знаю.&lt;/p&gt;
&lt;p&gt;В общем, с KVP (процесс hv_kvp_daemon) тоже проблемка — он стартует только один раз после установки системы, а потом отказывается. Я порылся, и выяснил, что при запуске hv_kvp_daemon пытается создавать директорию /&lt;em&gt;var/db/hyperv/pool&lt;/em&gt;. И если эта директория уже существует, (и следовательно, создать её не удаётся), то hv_kvp_daemon не запускается. Налицо просто некорректная обработка ошибки при попытке создания каталога. Т. е. вместо проверки на существование каталога делается попытка создания, и если она неудачная, то fail. Удаление каталога руками проблему решает — hv_kvp_daemon запускается. Непонятно, почему в системе нет стартового скрипта для этого демона, и его нужно запускать ручками. Возможно, считается, что демон ещё не доведён до ума, поэтому и стартового скрипта нет. В принципе, эту проблему с создание каталога можно обойти в стартовом скрипте — удалять каталог после остановки демона, и проверять каталог на существование при старте, и если он есть — опять таки, удаляем, hv_kvp_daemon его создаст себе сам.. И если эта директория уже существует, (и следовательно, создать её не удаётся), то hv_kvp_daemon не запускается. Налицо просто некорректная обработка ошибки при попытке создания каталога. Т. е. вместо проверки на существование каталога делается попытка создания, и если она неудачная, то fail. Удаление каталога руками проблему решает — hv_kvp_daemon запускается. Непонятно, почему в системе нет стартового скрипта для этого демона, и его нужно запускать ручками. Возможно, считается, что демон ещё не доведён до ума, поэтому и стартового скрипта нет. В принципе, эту проблему с создание каталога можно обойти в стартовом скрипте — удалять каталог после остановки демона, и проверять каталог на существование при старте, и если он есть — опять таки, удаляем, hv_kvp_daemon его создаст себе сам.&lt;/p&gt;
&lt;p&gt;Мораль: фрю вполне можно использовать в качестве гостевой ОС внутри Hyper-V. Я вижу в коммитах фрёвых исходников, что какая-то работа потихоньку, поддержка Hyper-V во фре допиливается, медленно, но верно. Остаётся дождаться только работы динамической памяти в гостевой фре, и можно совершенно смело гостевать фрю на Hyper-V. Сейчас оно всё работает — сетка и диски видны из коробки (на фре 10.1), крутится довольно стабильно. Правда, я нагрузки большой не давал, но в рамках той нагрузки, что есть, всё работает.&lt;/p&gt;</description><category>FreeBSD</category><category>Hyper-V</category><category>Troubleshooting</category><guid>https://at-hacker.in/posts/virtualizaciya-freebsd-na-hyper-v/</guid><pubDate>Mon, 06 Jul 2015 09:29:00 GMT</pubDate></item><item><title>Samba и ZFS: расширенные ACL и их правка из винды</title><link>https://at-hacker.in/posts/samba-zfs-acl/</link><dc:creator>at-hacker</dc:creator><description>&lt;h3&gt;Постановка задачи&lt;/h3&gt;
&lt;p&gt;Возникла необходимость запилить файл-сервер на Samba и дать ряду пользователей возможность рулить правами доступа на отдельные каталоги. Система — FreeBSD 10.1 amd64, файло будет лежать на ZFS. Версия Samba — 3.6.24.&lt;/p&gt;
&lt;p&gt;Исследование задачи показало, что стандартными правами Unix (aka «Unix mode») тут не обойтись. Надо использовать расширенный набор ACL. Например, нужно, чтобы к каталогу имели доступ более одной группы, но не все группы (т. е. разрешения для other тут не прокатит). Ну и на некоторые папки нужно давать доступ не отдельным группам, а прямо отдельным пользователям.&lt;/p&gt;
&lt;h3&gt;Общие сведения&lt;/h3&gt;
&lt;p&gt;По дефолту, как известно, в юниксах права на файлы и каталоги расставляются по схеме «ugo» — «user-group-other»). Во фре с помощью утилиты &lt;em&gt;setfacl&lt;/em&gt; можно задавать права по двум схемам — POSIX 1.E и NFSv4, в зависимости от файловой системы. По факту же POSIX 1.E  здесь сильно редуцирован — до этой самой схемы ugo. Тогда как в действительности POSIX 1.E слегка побогаче (подробности можно вкурить можно задавать права по двум схемам — POSIX 1.E и NFSv4, в зависимости от файловой системы. По факту же POSIX 1.E  здесь сильно редуцирован — до этой самой схемы ugo. Тогда как в действительности POSIX 1.E слегка побогаче (подробности можно вкурить &lt;a href="http://wt.tuxomania.net/publications/posix.1e/download/Posix_1003.1e-990310.pdf.gz"&gt;отсюда&lt;/a&gt;). Как гласит ). Как гласит &lt;em&gt;man setfacl&lt;/em&gt;::&lt;/p&gt;
&lt;p&gt;&lt;em&gt;access permissions&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Что в переводе означает: «Поля с разрешениями содержат букавки r, w или x для чтения, записи или выполнения соответственно».&lt;/p&gt;
&lt;p&gt;Но это всё нам не очень интересно, так как у нас ZFS, а на ZFS ACL по умолчанию соответствуют схеме NFSv4.&lt;/p&gt;
&lt;h3&gt;Тюнинг ZFS&lt;/h3&gt;
&lt;p&gt;Поэтому прежде чем заюзать всю эту красоту с крутыми ACL на ZFS, необходимо ZFS слегка потюнить. А именно, проделать такое:&lt;/p&gt;
&lt;p&gt;zfs set aclmode=passthrough storage0  &lt;/p&gt;
&lt;p&gt;zfs set aclinherit=passtrhough storage0
В данном случае &lt;em&gt;storage0&lt;/em&gt; — это имя моего ZFS-пула — это имя моего ZFS-пула&lt;/p&gt;
&lt;p&gt;&lt;em&gt;zfs set aclmode=passthrough&lt;/em&gt; делает так, что если над папкой выполняется chmod, то при наличии у папки расширенных ACEs (access control entries) (расширенные — это те, которые помимо стандартных @owner, @group, @other), то эти ACL при этом НЕ ИЗМЕНЯЮТСЯ. делает так, что если над папкой выполняется chmod, то при наличии у папки расширенных ACEs (access control entries) (расширенные — это те, которые помимо стандартных @owner, @group, @other), то эти ACL при этом НЕ ИЗМЕНЯЮТСЯ.&lt;/p&gt;
&lt;p&gt;Также там есть режимы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;discard&lt;/em&gt; — т. е. никаких ACL сверх стандартного unix mode сохраняться не будет; — т. е. никаких ACL сверх стандартного unix mode сохраняться не будет;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;groupmask&lt;/em&gt; — новые ACL по итогу будут выставляться так, чтобы они не превышали тех, которые принадлежат @group, за исключением случая, если UID пользователя в ACL совпадает с UID владельца каталога или файла. В этом случае выставляются права не выше, чем у владельца файла. Пока даже не могу предположить, для чего такой режим может использоваться. — новые ACL по итогу будут выставляться так, чтобы они не превышали тех, которые принадлежат @group, за исключением случая, если UID пользователя в ACL совпадает с UID владельца каталога или файла. В этом случае выставляются права не выше, чем у владельца файла. Пока даже не могу предположить, для чего такой режим может использоваться.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если коротко, то &lt;em&gt;zfs set aclinherit=passthrough&lt;/em&gt; необходима, для того, чтобы ACL свежесоздаваемых файлов и каталогов наследовались от каталога, в котором они создаются. Есть ещё режим passthrough-x — то же самое, что passthrough, только бит «executable» выставляется только в случае, если создающее файл приложение явным образом требует у создаваемого файла выставить бит «executable». Подробности можно необходима, для того, чтобы ACL свежесоздаваемых файлов и каталогов наследовались от каталога, в котором они создаются. Есть ещё режим passthrough-x — то же самое, что passthrough, только бит «executable» выставляется только в случае, если создающее файл приложение явным образом требует у создаваемого файла выставить бит «executable». Подробности можно &lt;a href="http://docs.oracle.com/cd/E19120-01/open.solaris/817-2271/gbaaz/index.html"&gt;вкурить тут&lt;/a&gt;..&lt;/p&gt;
&lt;h3&gt;Правка прав доступа из винды&lt;/h3&gt;
&lt;p&gt;В условиях задачи была заявлена необходимость дать некоему пользователю возможность управления доступом на каталоги в расшаренных папках. Причём от тонкостей командной строки пользователь бесконечно далёк, но может пользоваться виндовым диалогом прав доступа (который в свойствах папок или файлов в винде на вкладке «Безопасность» находится).&lt;/p&gt;
&lt;p&gt;Поэтому устанавливаем владельца всех папок в шаре на определённый аккаунт, который будет админским. Допустим, это будет учётка i.ivanov. Тогда делаем так:&lt;/p&gt;
&lt;p&gt;find /mnt/storage0/share -type d -exec setfacl -m u:i.ivanov:full_set:fd:allow {} \;  &lt;/p&gt;
&lt;p&gt;find /mnt/storage0/share -type f -exec setfacl -m u:i.ivanov:full_set:allow {} \;
Первый find выставляет права full_set (это сокращение на «Полный доступ») на каталоги, а второй find — на файлы. Два find необходимы потому, что в синтаксисе команды &lt;em&gt;setfacl&lt;/em&gt; при установке прав на каталог есть ещё модификатор «:fd:». Он означает, что права нижележащих каталогов должны наследоваться от вышестоящих. У файлов такого модификатора нет (т. е. в ACL на файлы он не предусмотрен). Если попытаться задать права на файл в формате при установке прав на каталог есть ещё модификатор «:fd:». Он означает, что права нижележащих каталогов должны наследоваться от вышестоящих. У файлов такого модификатора нет (т. е. в ACL на файлы он не предусмотрен). Если попытаться задать права на файл в формате &lt;em&gt;-m u:i.ivanov:full_set:fd:allow&lt;/em&gt;, то , то &lt;em&gt;setfacl&lt;/em&gt; выдаст ошибку. выдаст ошибку.&lt;/p&gt;
&lt;p&gt;Далее нам надо замапить группы Unix на группы в Samba. Если этого не сделать, то в диалоге «Безопасность» на винде будут видны пользователи файл-сервера (их отдаёт Самба), но не будет видно групп. Если же назначить группу руками через setfacl, то группа будет видна как «Unix Group\unixgroup»:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://at-hacker.in/assets/images/samba1.png"&gt;&lt;/p&gt;
&lt;p&gt;Но из виндового диалога добавить юниксовые группы не удастся — их там просто не видно. Чтобы они стали видны в этом диалоге, необходимы дополнительные телодвижения. Допустим, у нас есть на файл-сервере группы buhgalteria, common, engineers и bosses. Чтобы эти группы стали видны на Windows, делаем так:&lt;/p&gt;
&lt;p&gt;net groupmap add unixgroup=buhgalteria type=local ntgroup="Бухгалтерия"  &lt;/p&gt;
&lt;p&gt;net groupmap add unixgroup=common type=local ntgroup="Все юзеры"  &lt;/p&gt;
&lt;p&gt;net groupmap add unixgroup=engineers type=local ntgroup="Инженеры"  &lt;/p&gt;
&lt;p&gt;net groupmap add unixgroup=bosses type=local ntgroup="Начальство"
И после этого в диалоге добавления прав будут присутствовать соответствующие группы. Обращаю внимание, что если имена групп NT у вас на русском, то добавлять их в маппинг надо в кодировке UTF-8.&lt;/p&gt;
&lt;h3&gt;Настройка собственно Samba&lt;/h3&gt;
&lt;p&gt;Отключаем маппинг атрибутов DOS в файлах на exec-биты и включаем хранение атрибутов DOS в виде дополнительных файлов с атрибутами. Это не обязательно, просто меня бесит, что свеже-создаваемые в SMB-шарах файлы имеют атрибут «исполняемых» при просмотре прямо в консоли сервера. Это криво и несекурно — мало ли, кто там чо зальёт.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;# Disable mapping DOS bits
    map hidden = no
    map system = no
    map archive = no

# Use extended attributes to store file modes
    store dos attributes = yes
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Отключаем unix extensions (они нужны для того, чтобы Самба могла работать с расширениями CIFS от HP — там можно реализовывать симлинки, хардлинки и прочее. Эти расширения могут использовать разные другие SMB-клиенты, но винда их не поддерживает. Клиенты у нас в основном на винде — поэтому unix extensions нам ни к чему. Также выставляем параметры наследования и режима обработки ACL:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;inherited&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ACLs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;directories&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;nt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;support&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;inherit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;acls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;inherit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;owner&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;inherit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;permissions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;inherit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;unix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;extensions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;no&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;nt acl support&lt;/em&gt; — включает режим маппинга NT-like ACL на ACL файловой системы; — включает режим маппинга NT-like ACL на ACL файловой системы;&lt;/li&gt;
&lt;li&gt;inherit acls — включает режим наследования ACL от каталога, в котором создаются новые файлы и каталоги. Без этого параметра дополнительные ACL не будут наследоваться для новых файлов, будут наследоваться только unix mode разрешения;&lt;/li&gt;
&lt;li&gt;inherit owner — включает режим наследования владельца каталога, в котором создаётся файл. Без этого параметра владельцем будет становиться тот пользователь, который этот файл создаёт. В рамках нашей задачи наследование требуется, поэтому включаем;&lt;/li&gt;
&lt;li&gt;inherit permissions — включает наследование unix mode разрешений;&lt;/li&gt;
&lt;li&gt;map acl inherit — Самба будет мапить флаги «наследовать права от родительского каталога» в NT acls на файловую систему.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;И в настройках шары делаем так:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    vfs objects = zfsacl #включаем модуль zfsacl, чтобы самба мог работать с ACL на ZFS
    nfs4:acedup = merge # сливать в одну запись дублирующиеся ACE
    nfs4:chown = yes # разрешаем менять влалельца файлов
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;На этом, собственно, всё. А теперь — дискотека! :-)&lt;/p&gt;
&lt;h3&gt;Источники&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://daniel.washburn.at/docs/howtos/freebsd-samba4-zfs-recipe"&gt;Samba и ZFS ACL&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.metager.de/source/xref/samba/source3/modules/README.nfs4acls.txt"&gt;параметры ACL NFSv4 в Samba&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://wt.tuxomania.net/publications/posix.1e/download/Posix_1003.1e-990310.pdf.gz"&gt;POSIX 1.E&lt;/a&gt;&lt;/p&gt;</description><category>FreeBSD</category><category>Samba</category><category>ZFS</category><guid>https://at-hacker.in/posts/samba-zfs-acl/</guid><pubDate>Wed, 28 Jan 2015 12:19:00 GMT</pubDate></item><item><title>Unbound, DNSSEC и локальные зоны</title><link>https://at-hacker.in/posts/unbound-dnssec/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;На домашнем сервере крутится Unbound, на котором я включил DNSSEC для корневых зон. Для смелых и столь же бесчеловечных экспериментов поднял в виртуалках виндовый домен homelab.local. И решил прописать в Unbound локальные зоны. Точнее — stub-зоны, чтобы с домашних компов можно было обращаться к компам из зоны homelab.local по именам.&lt;/p&gt;
&lt;p&gt;Прописал всё как положено:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"homelab.local"&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;stub&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m m-Double"&gt;192.168.2.3&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Но имена так и не резолвились. Начал копать вокруг файрволов — нет, не файрволы, все запросы проходят, сервера отвечают. То есть, я вижу, как идёт запрос с Unbound на DNS-сервер 192.168.2.3 (это контроллер домена homelab.local), и даже вижу, как на Unbound с контроллера приходит ответ, но фактически же Unbound мне возвращает SERVFAIL.&lt;/p&gt;
&lt;p&gt;Что, в общем-то, логично, если подумать. Корневая зона .local не имеет подписи, соответственно, Unbound трактовал её как паленую. Указание в конфиге:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;domain-insecure: "homelab.local"
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;указанную проблему сняло, и имена зоны homelab.local начали разрешаться.&lt;/p&gt;</description><category>DNS</category><category>FreeBSD</category><category>Troubleshooting</category><category>Unbound</category><guid>https://at-hacker.in/posts/unbound-dnssec/</guid><pubDate>Sun, 05 Oct 2014 13:15:00 GMT</pubDate></item><item><title>Ремонт файловой системы UFS2</title><link>https://at-hacker.in/posts/remont-faylovoy-sistemy-ufs2/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;Поимел сейчас неясного происхождения баг — домашнее хранилище, организованное на основе неттопа, зависло. Система там стоит на флэшке, на винте только своп и юзерские файлы. Перезагрузил, начал чинить ошибки на файловой системе флэшки. Ну, всё как обычно:&lt;/p&gt;
&lt;h2&gt;fsck -fy /dev/da0a&lt;/h2&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;после одного из разделов fsck доложил, что часть ошибок исправлена, но filesystem is still dirty, please rerun fsck. Я перезапустил, а в ответ мне:&lt;/p&gt;
&lt;h2&gt;fsck -fy /dev/da0d&lt;/h2&gt;
&lt;p&gt;ioctl (GCINFO): Inappropriate ioctl for device  &lt;/p&gt;
&lt;p&gt;fsck_ufs: /dev/da0d: can't read disk label 
Хотя визуально все разделы на месте, о чём подтверждали все утилиты. Поиск по интернету конкретного рецепта не принёс, но навёл на размышления о повреждённом суперблоке. В итоге вылечил таки.&lt;/p&gt;
&lt;p&gt;Сначала надо выяснить, где размещаются копии суперблока. Делаем раз:&lt;/p&gt;
&lt;h2&gt;newfs -N /dev/da0d&lt;/h2&gt;
&lt;p&gt;/dev/da0d: 1024.0MB (2097152 sectors) block size 32768, fragment size 4096  &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;    using 4 cylinder groups of 256.03MB, 8193 blks, 32896 inodes.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;super-block backups (for fsck -b #) at:  &lt;/p&gt;
&lt;p&gt;192, 524544, 1048896, 1573248
Нужно починить файловую систему с правильным суперблоком. Сделать это можно командой &lt;em&gt;fsck_ffs&lt;/em&gt;::&lt;/p&gt;
&lt;h2&gt;fsck_ffs -b 1573248 /dev/da0d&lt;/h2&gt;
&lt;p&gt;Ключ &lt;em&gt;-b 1573248&lt;/em&gt; указывает, что нужно при ремонте ФС нужно использовать не первый суперблок, а тот, который лежит по смещению 1573248. После этого система починилась нормально. указывает, что нужно при ремонте ФС нужно использовать не первый суперблок, а тот, который лежит по смещению 1573248. После этого система починилась нормально.&lt;/p&gt;</description><category>FileSystem</category><category>FreeBSD</category><category>Troubleshooting</category><guid>https://at-hacker.in/posts/remont-faylovoy-sistemy-ufs2/</guid><pubDate>Wed, 13 Aug 2014 08:48:00 GMT</pubDate></item><item><title>Зашифровать файл</title><link>https://at-hacker.in/posts/zashifrovat-fayl/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;Задался вопросом, а как можно зашифровать отдельный файл на фре. Про geli или gbde всё ясно, а вот так, чтобы отдельный файл? Раньше шифровал с помощью rar — запихивал в зашифрованый архив. В свете того, что нужно на домашнем хранилище кое-что бэкапить, причём желательно так, чтобы «никто не нашёл», а лишние сущности плодить (сиречь ставить rar) не хочется, изыскал на просторах интернетов рецепт &lt;del&gt;щастья&lt;/del&gt; шифрования отдельных файлов. Рецепт незамысловат — функцией шифрования обладает openssl. Чтобы зашифровать файл, нужно сделать раз: шифрования отдельных файлов. Рецепт незамысловат — функцией шифрования обладает openssl. Чтобы зашифровать файл, нужно сделать раз:&lt;/p&gt;
&lt;p&gt;openssl enc -aes-256-xts -in file.dat -out file.dat.enc
Шифрует файл &lt;em&gt;file.dat&lt;/em&gt; с помощью алгоритма AES-256 и сохраняет шифрованный файл в файле с помощью алгоритма AES-256 и сохраняет шифрованный файл в файле &lt;em&gt;file.dat.enc&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Чтобы расшифровать, делаем два:&lt;/p&gt;
&lt;p&gt;openssl enc -d -aes-256-xts -in file.dat.enc -out file.dat
Ещё у openssl enc есть прикольная функция — оно умеет преобразовывать бинарники в base64. Делается это с помощью ключа -a. Например, рассмотрим ситуацию, когда надо передать бинарник, а воспользоваться scp или подобными утилитами нет возможности. Тогда можно сделать так:&lt;/p&gt;
&lt;p&gt;openssl enc -a -in file.dat -out file.dat.base64
И получившийся в результате &lt;em&gt;file.dat.base64&lt;/em&gt; можно просто передать хоть прямо через буфер между двумя терминалами, а на принимаемой стороне потом сделать: можно просто передать хоть прямо через буфер между двумя терминалами, а на принимаемой стороне потом сделать:&lt;/p&gt;
&lt;p&gt;openssl enc -a -d -in file.dat.base64 -out file.dat&lt;/p&gt;</description><category>FreeBSD</category><category>Tips&amp;Tricks</category><category>Безопасность</category><guid>https://at-hacker.in/posts/zashifrovat-fayl/</guid><pubDate>Thu, 31 Jul 2014 07:39:00 GMT</pubDate></item><item><title>rtorrent + ruTorrent + HTTPRPC + scgi_local</title><link>https://at-hacker.in/posts/rtorrent-rutorrent-httprpc-scgi-local/</link><dc:creator>at-hacker</dc:creator><description>&lt;p&gt;На домашнем сервере запилил себе rtorrent+ruTorrent. Сначала делал по старинке — через mod_scgi. Потом обнаружил, что ruTorrent периодически жалуется, что, дескать, «rtorrent не отвечает». В интернетах утверждают, что связаны эти грабли с тем, что для mod_scgi нынешние скорости закачки (а следовательно, и обновления информации) зело велики и оно не справляется. Не то что бы это сильно влияло на функционал, но ведь косячок-с налицо. Поэтому решил с этим побороться. Для борьбы рекомендуется использовать специальный плагин для ruTorrent, который называется &lt;a href="https://code.google.com/p/rutorrent/wiki/PluginHTTPRPC"&gt;HTTPRPC&lt;/a&gt;..&lt;/p&gt;
&lt;p&gt;Установка плагина нехитрая — нужно просто скопировать папку плагина в подкаталог plugins внутри каталога ruTorrent. После этого можно отключить в конфигах апача модуль mod_scgi (ежели был подключён) и убрать строку&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;SCGIMount /RPC2 127.0.0.1:5000
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Я решил пойти ещё дальше. Вычитал, что работа через сетевой сокет (даже если он висит на localhost) — это «несекурненько». И есть возможность организовать обмен информацией между rtorrent и ruTorrent через файловый сокет. Для этого требуется в конфиге rtorrent вписать такое:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;scgi_local = /mnt/storage0/sys/tmp/rtorrent-rpc.socket
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Где /&lt;em&gt;mnt/storage0/sys/tmp/rtorrent-rpc.socket&lt;/em&gt; — путь к файлу сокета. — путь к файлу сокета.&lt;/p&gt;
&lt;p&gt;После перезапуска rtorrent будет создан файл /mnt/storage0/sys/tmp/rtorrent-rpc.socket&lt;/p&gt;
&lt;p&gt;Чтобы ruTorrent вкурил, что ему теперь надо работать не через сетевой сокет, а через файловый, нужно в конфиге &lt;em&gt;config.php&lt;/em&gt; от ruTorrent изобразить следующее: от ruTorrent изобразить следующее:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;scgi_port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;scgi_host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unix:///mnt/storage0/sys/tmp/rtorrent-rpc.socket"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Строчку&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;$XMLRPCMountPoint = "/RPC2";
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ОСТАВЛЯЕМ КАК ЕСТЬ. То есть, её не трогаем.&lt;/p&gt;
&lt;p&gt;После этого запускаем rtorrent, перезапускаем апач (если вносились изменения в его конфиг) и наслаждаемся.&lt;/p&gt;
&lt;p&gt;У меня ещё возникли грабли с тем, что права на создаваемый сокет не позволяли туда писать пользователю www, от которого работает апач. Пришлось немного доработать скрипт запуска rtorrent.&lt;/p&gt;
&lt;p&gt;Добавил в rc.conf переменную rtorrent_socket:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;rtorrent_socket="/mnt/storage0/sys/tmp/rtorrent-rpc.socket"
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;А в скрипте запуска добавил проверку на существование сокета при запуске rtorrent, и если сокет существует, то меняем ему владельца на rtorrent:www. В целом скрипт запуска rtorrent выглядит так (нужные строки, относящиеся к правам на файловый сокет выделены красным):&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="c1"&gt;# PROVIDE: rtorrent&lt;/span&gt;
&lt;span class="c1"&gt;# REQUIRE: NETWORKING SERVERS&lt;/span&gt;
&lt;span class="c1"&gt;# BEFORE: DAEMON&lt;/span&gt;
&lt;span class="c1"&gt;# KEYWORD: shutdown&lt;/span&gt;

&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Add the following lines to /etc/rc.conf to enable rtorrent at startup&lt;/span&gt;
&lt;span class="c1"&gt;# rtorrent (bool): Set to "NO" by default.&lt;/span&gt;
&lt;span class="c1"&gt;#                Set it to "YES" to enable rtorrent&lt;/span&gt;
&lt;span class="c1"&gt;# rtorrent_user (str): Set to user running rtorrent&lt;/span&gt;
&lt;span class="c1"&gt;#                    (default 'p2p')&lt;/span&gt;
&lt;span class="c1"&gt;# rtorrent_home (str): Set to home directory of user running rtorrent&lt;/span&gt;
&lt;span class="c1"&gt;#                    (default /home/${rtorrent_user})&lt;/span&gt;

.&lt;span class="w"&gt; &lt;/span&gt;/etc/rc.subr

&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"rtorrent"&lt;/span&gt;
&lt;span class="nv"&gt;rcvar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rtorrent_enable

load_rc_config&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;

&lt;span class="nv"&gt;rtorrent_enable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_enable&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;"NO"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;rtorrent_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_user&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;"rtorrent"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;rtorrent_home&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_home&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;"/home/&lt;/span&gt;&lt;span class="nv"&gt;$rtorrent_user&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;rtorrent_socket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_socket&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;"/tmp/rtorrent-rpc.socket"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;required_dirs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_home&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;required_files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_home&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.rtorrent.rc"&lt;/span&gt;

&lt;span class="nv"&gt;start_cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_start"&lt;/span&gt;
&lt;span class="nv"&gt;stop_cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_stop"&lt;/span&gt;

rtorrent_start&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;/var/run/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.run&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_home&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/usr/local/bin/screen -dmS rtorrent_init /usr/local/bin/rtorrent"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;/var/run/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.run
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Started &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seems to be already running — remove /var/run/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.run manually if needed."&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_socket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;chown&lt;span class="w"&gt; &lt;/span&gt;rtorrent:www&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;rtorrent_socket&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

rtorrent_stop&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;/var/run/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.run&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;kill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-SIGINT&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;ps&lt;span class="w"&gt; &lt;/span&gt;-xa&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/rtorrent/ &amp;amp;&amp;amp; ! /rtorrent_init/ &amp;amp;&amp;amp; ! /stop/ { print $1 }'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;/var/run/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;.run
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stopped &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;."&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; doesn't seem to be running — create /var/run/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.run if needed."&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

run_rc_command&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;sleep 3&lt;/em&gt; добавлен, чтобы дать возможность rtorrent запуститься и создать сокет. У меня в роли сервера комп слабенький, система стоит на флэшке, поэтому иногда процесс создания сокета требует секунду-другую. добавлен, чтобы дать возможность rtorrent запуститься и создать сокет. У меня в роли сервера комп слабенький, система стоит на флэшке, поэтому иногда процесс создания сокета требует секунду-другую.&lt;/p&gt;</description><category>Apache</category><category>FreeBSD</category><category>Torrent</category><guid>https://at-hacker.in/posts/rtorrent-rutorrent-httprpc-scgi-local/</guid><pubDate>Fri, 11 Jul 2014 11:47:00 GMT</pubDate></item></channel></rss>