Быстро перекодировать пачку видео для просмотра на iPad – ffmpeg в помощь

На Маке понадобилось залить сезон сериала жене на iPad. Тратить деньги на программы перекодирования видео как-то не хочется. Вспоминаем про старый добрый ffmpeg:
$ brew install ffmpeg
$ for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done

Для *.mkv иногда достаточно сменить контейнер. Операция происходит очень быстро, но есть шанс, что на планшете не заработает.
$ for i in *.mkv; do ffmpeg -i "$i" -codec copy "${i%.*}.mp4"; done

Получившиеся файлы слегка переименовываем – ставим индекс серии в начало названия, так как проигрыватель на iOS сильно обрезает имена файлов. Заливаем на устройство через iTunes.

Еще парочку нюансов:
1. Иногда при перекодировании avi в mp4 убивается звук. Можно попробовать звуковую дорожку просто скопировать:
$ for i in *.avi; do ffmpeg -i "$i" -acodec copy "${i%.*}.mp4"; done
2. Теги mp4 частенько не совпадают с названием файла, можно поправить:
$ for i in *.mp4; do mp4tags -s `basename "$i" .mp4` $i; done

Автоматизация резервного копирования сайта по расписанию. FTP

Некоторые провайдеры не дают доступ к размещенным сайтам по SFTP, поэтому всем удобный rsync работать не будет. Придется довольствоваться старым небезопасным ftp. Самый удобный инструмент – wget. Делаем примитивный однострочник:
$ wget --no-passive -r -l 0 -q 0 ftp://isp3.service.tld/web/ -P /tmp; zip -q -r /var/backup/sites/site1/backup_`date +\%Y\%m\%d\%H\%M\%S`.zip /tmp/isp3.service.tld; rm -fr /tmp/isp3.service.tld

Опция --no-passive включает активный режим. В пассивном режиме, который включается по умолчанию, траффик ftp может быть зарезан файерволом. Если все работает без этой опции, то в активном режиме режиме нет необходимости.
Комбинация опций -r -l 0 указывает рекурсивность и неограниченную глубину дерева каталогов.

Как видно, логин и пароль в командной строке отсутствуют. Их, конечно, можно указать как параметры wget, например --user="serviceftp" --password="$uperPa$$w0rd", но лучше так не делать.
Специально для хранения логинов и паролей ftp/http есть файл .netrc. И wget будет читать информацию из этого файла при получении запроса авторизации от сервера.

$ touch ~/.netrc
$ chmod 600 ~/.netrc
$ echo 'machine isp3.service.tld login serviceftp password $uperPa$$w0rd' >> ~/.netrc

Сайт в моем случае статичный и обновляется редко. Резервные копии нужны на случай, если пользователь сайт поломает, а у провайдера не будет рабочего бекапа. Бекап Шредингера, так сказать.

Добавим такую строчку в crontab (5:30 каждого первого числа):

30 5 1 * * /usr/bin/wget --no-passive -r -l 0 -q 0 ftp://isp3.service.tld/web/ -P /tmp; zip -q -r /var/backup/sites/site1/backup_`date +\%Y\%m\%d\%H\%M\%S`.zip /tmp/isp3.service.tld;rm -fr /tmp/isp3.service.tld > /dev/null

Debian 8 и старое ядро OpenVZ

UPD: конфигурация нерабочая – сервисы не стартуют! Так как проблема заключается в старой версии vzctl, а менять ядро на хост-системе никто не будет, то от идеи Debian 8 со старым ядром придется отказаться.

В далекой-далекой Галактике… не, не так… на далеком-далеком хостинге, на древнем-древнем сервере…
Короче, на действительно древнем сервере, корый я настраивал для клиента в 2009 году и обновлял в 2014, понадобилось поднять для экспериментов контейнер OpenVZ. Точнее, он уже был создан в 2014 на шаблоне Debian 6.0, но с тех пор не обновлялся. Самое простое – уничтожить контейнер и создать заново с новым шаблоном. Здесь надо быть особенно внимательным – Debian 9 со старым ядром (2.6.32-5-openvz-amd64 #1 SMP Tue May 13 17:16:50 UTC 2014 x86_64 GNU/Linux) не дружит(!) и напрочь теряет сеть. Поэтому ставим Debian 8, для работы более чем достаточно.
$ sudo /usr/sbin/vzctl stop 1009
$ sudo /usr/sbin/vzctl destroy 1009
$ wget http://download.openvz.org/template/precreated/debian-8.0-x86_64-minimal.tar.gz
$ sudo mv debian-8.0-x86_64* /var/lib/vz/template/cache/
$ sudo /usr/sbin/vzctl create 1009 --ostemplate debian-8.0-x86_64-minimal

Старый конфиг сохраняем, необходимо только поменять название шаблона (OSTEMPLATE=”debian-6.0-amd64-minimal” -> OSTEMPLATE=”debian-8.0-x86_64-minimal”)

Пытаемся запустить и обламываемся:
$ sudo /usr/sbin/vzctl start 1009
Starting container ...
Container is unmounted
Container is mounted
Failed to set upstart as init: No such file or directory

Проблема в том, что vzctl пропускает init и использует upstart напрямую, а его у нас в системе нет.
Не мешает добавить DNS-сервер в /etc/resolv.conf, если там пусто. 8.8.8.8 подойдет.
$ sudo -i
# cd /var/lib/vz/root/1009
# chroot .
# vim /etc/resolv.conf
# apt-get update
# apt-get install upstart

Теперь другое дело:
$ sudo /usr/sbin/vzctl start 1009
Starting container ...
Container is unmounted
Container is mounted
Adding IP address(es): 123.45.67.89
Setting CPU units: 1000
Container start in progress...

Автоматизация для бедных. Часть 3 – обработка входящей почты. Fetchmail, procmail и другие

Понадобилось автоматизировать прием некоторой специфической почты. Содержание тела письма не важно, вложения необходимо сохранить на сервере для дальнейшего использования.

Выбор связки fetchmail / procmail в качестве решения вполне очевиден.
$ sudo apt-get install fetchmail procmail incron

Дальше начинается интересное – fetchmail не работает для отдельного пользователя, если нет глобальной конфигурации в /etc/fetchmailrc. И права тоже должны быть установлены корректно.

$ ls -l /etc/fetchmailrc
-rw------- 1 fetchmail root 271 Jan 11 22:08 /etc/fetchmailrc

Нам необходимо забирать всю почту, протокол pop3s с использованием SSL, отдать на обработку юзеру mailman. Период обращения к почтовому серверу – 3 минуты:

$ sudo cat /etc/fetchmailrc
#### .fetchmailrc

set daemon 180
set logfile /var/log/fetchmail.log

poll mail.domail.tld proto POP3
user "robot@domain.tld" pass "password" is "mailman" preconnect "date >> /var/log/fetchmail.log"
ssl
fetchall
no keep
no rewrite
mda "/usr/bin/procmail -f %F -d %T";

На стороне mailman находится конфигурация procmail. Сохраняем все входящие сообщения и отдельно сохраняем вложения, передавая их uudeview для распаковки:
$ cat .procmailrc
:0
*^content-Type:
{
:0c
$HOME/emailbackup
:0fw
| uudeview -i +a +o -p $HOME/attachments -
}

Каталоги ~/emailbackup и ~/attachments необходимо создать заранее.

После создания файлов на диске incron их положит на сервер. Это гораздо быстрее и эффективнее, чем обработка по crontab.
$ incrontab -l
/home/mailman/attachments/ IN_CREATE mv $@/$# /mnt/files/INBOX/

Подробная информация по incron на IBM Developer: “Планирование операций обработки событий в файловой системе”

Теперь начинаются костыли.
Иногда, по какой-то непонятной причине, incron не перемещает файлы на сервер. Приходится их подбирать по расписанию, каждые 5 минут:
*/5 * * * * /usr/bin/find /home/mailman/attachments -mmin +1 -type f -exec mv '{}' /mnt/files/INBOX/ \; > /dev/null

Еще один костыль для латышского языка. Файлы с неправильными названиями на национальных языках иногда не обрабатываются скриптами. Есть замечательная утилита для переименования файлов со слетевшими кодировками:
*/5 * * * * /usr/bin/find /home/mailman/attachments -mmin +1 -type f -exec /usr/bin/convmv -f cp1257 -t utf8 -r --notest '{}' \; > /dev/null

Может, не самое оптимальное решение, но работает. Буду рад советам и предложениям.

Кусочки скриптов Bash. Обработка строк.

Несколько примеров обработки строк на Bash.
Была задача проверять содержимое шифрованных ZIP-архивов, описание создания которых дано в предыдущей заметке, доставать каким-то образом оттуда референс-код партнера, вставлять в заголовок письма и писать отдельно в лог.
Код партнера должен быть в названии документа, но, так как документы создаются вручную и собираются со всего мира, то никакой системы нет. Хорошо, что все партнеры используют собственную систему кодов, это позволяет вести поиск по шаблону.

В общем виде для кода фиксированной длинны L-M999999.99 это выглядит примерно так:
str1=`zipinfo -1 $filenamе | grep "L-M" | head -1`
if [ -z "$str1" ]
then
ref='NONREF'
else
idx=`echo $str1 | grep -b -o "L-M" | cut -d: -f1`
bgn=$(( $idx + 1 ))
end=$(( $idx + 12 ))
ref=`echo $str1 | cut -c $bgn-$end`
fi

[ -z "$str1" ] – проверка определена ли и не пустая ли переменная
grep -b -o "L-M" | cut -d: -f1 – определение после какой позиции начинается искомая подстрока

Вообще, grep очень мощная и гибкая утилита. Но не все параметры очевидны.
Например, wildcard обозначается точкой: echo $str1 | grep -b -o "XZ.-"
Очень полезный туториал по grep можно найти на Digital Ocean: “Using Grep & Regular Expressions to Search for Text Patterns in Linux”.

Более сложный вариант со “славянской спецификой”. Мало того, что начальная часть кода переменной длины (99999-DDMMYY-AAA / 99999А-DDMMYY-AAA), так она еще может содержать как латинскую, так и кириллическую букву “А”, какая раскладка была включена, так и вбили.

str1=`zipinfo -1 $filename | sed 's/\xd0\x90/A/g'|grep -E "[[:digit:]]{6}-[[:alnum:]]{3}" | head -1`
if [ -z "$str1" ]
then
ref='NONREF'
else
idx=`echo $str1 | grep -E -b -o "[[:digit:]]{6}-[[:alnum:]]{3}" | cut -d: -f1`
# if reference number contains letter 'A' it is one character longer
char=`echo $str1 | grep -E -b -o "[[:digit:]]{6}-[[:alnum:]]{3}" | cut -c $(( $idx - 1 ))`
if [ "$(echo $char | grep "^[ [:digit:] ]*$")" ]
then
bgn=$(( $idx - 5 ))
else
bgn=$(( $idx - 6 ))
fi
end=$(( $idx + 10 ))
ref=`echo $str1 | cut -c $bgn-$end`
fi

grep -E "[[:digit:]]{6}-[[:alnum:]]{3}" – поиск по шаблону 6 цифр “-” 3 цифро-буквенных символа
[ "$(echo $char | grep "^[ [:digit:] ]*$")" ] – проверка является ли символ цифрой
sed 's/\xd0\x90/A/g' – замена кириллической “А” на латинскую “A”, используются шестнадцатиричные коды.

Более продвинутый вариант, так как партнеры все делают вручную и никак не могут определиться в каком регистре будут символы и надо ли ставить в коде дефис. Код вида 99-YYlv, где первая часть варьируется по длине от 2 до 3 цифр:

str1=`zipinfo -1 $filename | tr [A-Z] [a-z]| sed 's/-//g' | grep -E "[[:digit:]]{4}lv" | head -1`
if [ -z "$str1" ]
then
ref='NONREF'
else
idx=`echo $str1 | tr [A-Z] [a-z]| sed 's/-//g' | grep -E -b -o "[[:digit:]]{4}lv" | cut -d: -f1`
char=`echo $str1 | tr [A-Z] [a-z]| sed 's/-//g' | grep -E "[[:digit:]]{4}lv" | cut -c $idx`
if [ "$(echo $char | grep "^[ [:digit:] ]*$")" ]
then
bgn=$idx
else
bgn=$(( $idx + 1 ))
fi
end=$(( $idx + 6 ))
ref=`echo $str1 | cut -c $bgn-$(( $end -4 ))`-`echo $str1 | cut -c $(( $end -3 ))-$end`
fi

tr [A-Z] [a-z] – самый простой способ поменять регистр строки.

По идее, проверяя не цифра ли символ перед началом искомой строки, мы вылезаем за пределы массива. За такое в серьезном программировании отрывают руки, но в bash все работает без проблем.

Самый извращенный вариант обработки, первая часть кода варьируется от 3 до 6 цифр – простой счетчик без заполняющих нулей вида 999999-YYYY.

str1=`zipinfo -1 $filename | grep -E "[[:digit:]]{3}-[[:digit:]]{4}" | head -1`
if [ -z "$str1" ]
then
ref='NONREF'
else
idx=`echo $str1 | grep -E -b -o "[[:digit:]]{3}-[[:digit:]]{4}" | cut -d: -f1`
# partner code left part can be up to 6 digits long
char1=`echo $str1 | grep -E "[[:digit:]]{3}-[[:digit:]]{4}" | cut -c $idx`
char2=`echo $str1 | grep -E "[[:digit:]]{3}-[[:digit:]]{4}" | cut -c $(( $idx - 1 ))`
char3=`echo $str1 | grep -E "[[:digit:]]{3}-[[:digit:]]{4}" | cut -c $(( $idx - 2 ))`
if [ "$(echo $char1 | grep "^[ [:digit:] ]*$")" ]
then
if [ "$(echo $char2 | grep "^[ [:digit:] ]*$")" ]
then
if [ "$(echo $char3 | grep "^[ [:digit:] ]*$")" ]
then
bgn=$(( $idx - 2 ))
else
bgn=$(( $idx - 1 ))
fi
else
bgn=$idx
fi
else
bgn=$(( $idx + 1 ))
fi

end=$(( $idx + 8 ))
ref=`echo $str1 | cut -c $bgn-$end`
fi

Полный код высчитывается итерационно. Ничего более приличного в голову не приходит.

P.S.Краткий справочник по арифметическим операциям в bash: “Bash:Perform arithmetic operations”

Автоматизация для бедных. Часть 2 – отсылка файлов на SFTP

Первая часть была о том, как простенько сделать автоматическую отправку документов с приложением в виде шифрованных архивов ZIP. Пока заметка писалась, один из партнеров согласился открыть доступ по SFTP.
Офисные сотрудники и протоколы Интернета по определению не совместимы, поэтому даже такую несложную операцию лучше автоматизировать.
Конфигурация серверов остается полностью той же, добавляется один скрипт пересылки файлов, дополнительная задача в crontab и пару рабочих каталогов. Для использования SFTP в скриптах необходимо, чтобы вход на удаленный сервер проходил без пароля, по ключу. Как настроить такую удобную штуку, я писал здесь 10 лет назад.

1. Структура каталогов и рабочие файлы
/var/transfer/partner2/
/var/transfer/partner2/out/ <- очередь на пересылку
/var/transfer/partner2/backup/ <- копии отправленных файлов
/var/transfer/partner2/transfer <- скрипт отсылки
/var/transfer/partner2/sftp.job <- батник для sftp

2. Скрипт отсылки
#!/bin/sh

# Find and deliver files to Partner2

src=/mnt/company/#secure_transfer_partner2/
dst=/var/transfer/partner2/out/
bkp=/var/transfer/partner2/backup/

# Только файлы старше 3 минут, игнорировать каталоги, подкаталоги и скрытые dot-файлы
/usr/bin/find $src -maxdepth 1 -not -path '*/\.*' -mmin +3 -type f -exec mv '{}' $dst \;
/usr/bin/sftp -b /var/transfer/partner2/sftp.job company@ftp.partner2.com
if [ $? -eq 0 ]
then
mv $dst/* $bkp/
fi

3. Батник для sftp
rat@assistant:~$ cat /var/transfer/partner2/sftp.job
lcd /var/transfer/partner2/out
cd /in
put *

Кстати, одним бантиком можно файлы положить, забрать, перенести. Причем, из множества каталогов.

4. Crontab
rat@assistant:~$ cat /etc/cron.d/securetransfer
# /etc/cron.d/securetransfer: crontab entry to deliver files to Partner2 SFTP

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*/5 * * * * root /usr/bin/test -x /var/transfer/partner2/transfer && /var/transfer/partner2/transfer >/dev/null 2>&1

Логирование, нотификации передающей и принимающей сторонам не включены, но в планах.

Теперь небольшой хак как использовать sftp в скриптах, но на принимающей стороне нет возможности прописать свой публичный ключ. Есть утилитка sshpass, которая позволяет подать пароль для ssh, sftp или scp из переменной, из файла или (для безмозглых) в открытом виде.
rat@assistant:~$ sudo apt-get update && sudo apt-get install sshpass

Тогда вызов SFTP из скрипта без ручного ввода пароля может выглядеть так:
rat@assistant:~$ /usr/bin/sshpass -f ~/.partner2 /usr/bin/sftp -b ~/partner2_sftp.job customer@ftp.partner2.com, где:
~/.partner2 – пароль к аккаунту customer@ftp.partner2.com, -f – чтение из файла;
~/partner2_sftp.job – батник со списком sftp-команд, например:
lcd /var/transfer/partner2/out
cd /in
put *

SCP в таком случае выглядит предпочтительнее, но, если удаленный сервер сконфигурирован “sftp only”, scp и ssh работать не будут.

Еще пара любопытных примеров как положить или скачать отдельный файл с удаленного сервера по sftp, не вводя дополнительных команд:
Скачать: sftp {user}@{host}:{remoteFileName} {localFileName}
Положить: sftp {user}@{host}:{remote_dir} <<< $'put {local_file_path}'

Пример взят со StackOverflow в "Single Line sftp from Terminal".

Автоматизация для бедных. Часть 1 – отсылка почты с шифрованными приложениями

В соответствии с требованиями европейской регулы по защите данных GDPR данные частных лиц не могут передаваться в публичной сети в открытом виде. Это в первую очередь относится к операторам данных. Если необходимо передать информацию третьей стороне, то она должна быть в защищенном виде.
Пришлось помочь одной дружественной фирме. У них обмен данными с партнерами идет по электронной почте, и теперь вся информация, содержащая персональные данные клиента, должна быть зашифрована. Самое простое – пересылка шифрованных архивов ZIP. Несмотря на слабость алгоритмов шифрования ZIP, использование длинных сложных паролей делает атаку перебором малопривлекательной – данные не стоят ресурсов, необходимых для взлома. Но шифровать файлы вручную с правильным ключом (партнеров > 10) – то еще занятие. Уровень ошибок и время, уходящее на вроде простую операцию – неадекватно высокие.
Идея автоматизации очень простая – на сервере документов (Windows Server) делаются папки для каждого партнера, куда сотрудники складывают документы, которые необходимо зашифровать и отослать партнерам, а все автоматические задачи выполняет маленький офисный “сервер” под Linux.

Как поставить и настроить сервер (в данном случае подойдет и старый ноутбук, и Raspberry Pi) написаны тысячи статей разной степени полезности. Поэтому примем, что настроенный сервер у нас есть, дистрибутив Linux – Debian или Ubuntu. Так же у нас есть сторонний SMTP сервер, через который будем отправлять почту.

Задача – периодически заглядывать в папку и, если там что-то есть, зазимовать это “что-то” с паролем и отправить заданному адресату по электронной почте. Так как файловая система удаленная (cifs), мониторить ее события по inotify не получится, придется опрашивать по расписанию.

1. Как подмонтировать файловую систему с Windows Server
Необходимо добавить информацию о новой файловой системе в /etc/fstab:
# Company documents
//172.16.171.10/company /mnt/company cifs credentials=/etc/.credentials 0 0

Раньше тип файловой системы указывался как smbfs, но эти времена прошли.
Файл /etc/.credentials содержит всю информацию для подключения к “шаре” Windows Server:
rat@assistant:~$ sudo cat /etc/.credentials
domain=domainname
username=username
password=userpassword

Пользователь должен иметь права на запись и удаление файлов.

После того, как информация добавлена, подключим новую файловую систему:
rat@assistant:~$ sudo mount -a

Если все настроено правильно, новая файловая система будет доступна:
rat@assistant:~$ df -h
Filesystem Size Used Avail Use% Mounted on
udev 989M 0 989M 0% /dev
tmpfs 202M 22M 180M 11% /run
/dev/sda5 9.1G 6.2G 2.5G 72% /
tmpfs 1007M 124K 1007M 1% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 1007M 0 1007M 0% /sys/fs/cgroup
/dev/sda6 136G 25G 105G 19% /var
tmpfs 202M 8.0K 202M 1% /run/user/1000
//172.16.171.10/company 80G 30G 51G 38% /mnt/company

2. Как настроить компоненты почтовой системы.
Для отправки почты понадобятся mutt и ssmtp.
rat@assistant:~$ sudo apt-get update && sudo apt-get install ssmtp mutt

Mutt – отличный консольный почтовый клиент, а sSMTP – хитрая штука, которая прикидывается полноценным почтовым сервером, но для операций использует ресурсы стороннего сервера (Google, Yandex, etc.). Настраивать еще один почтовый сервер и заботиться о его безопасности в наши планы не входит. Тем более, что наш сервер “assistant” находится далеко за брандмауэром и NAT:
rat@assistant:~$ ifconfig enp1s0
enp1s0 Link encap:Ethernet HWaddr 00:0f:1f:ab:c3:9c
inet addr:192.168.88.3 Bcast:192.168.88.255 Mask:255.255.255.0

sSMTP настраивается тривиально, вся конфигурация в одном файле, обычно /etc/ssmtp/ssmtp.conf. Реверсные алиасы не трогаем.
rat@assistant:~$ sudo cat /etc/ssmtp/ssmtp.conf|grep -v '#'
root=postmaster
rewriteDomain=domainname.lv
FromLineOverride=YES
mailhub=mail.provider.lv:587
AuthUser=robot@domainname.lv
AuthPass=strongpassword

Mutt тоже потребует настройки, иначе не получится корректно указывать желаемый адрес отправителя.
Файл настройки находится в каталоге пользователя, от которого будут запускаться скрипты. В данном случае /root/.muttrc
rat@assistant:~$ sudo cat /root/.muttrc
set content_type="text/html"
set realname="CompanyName Accounting"
set from="accounting@domainname.lv"

Первый параметр указывает на формат сообщения. Если форматирование и фирменный стиль не важны, можно оставить plain text, не указывая параметр content_type.

3. Структура каталогов и скрипты запуска.

Рабочие каталоги и файлы конфигурации разместим в /var/transfer/email:
/var/transfer/email/
/var/transfer/email/fetch <- скрипт обработки
/var/transfer/email/message_body <- тело письма
/var/transfer/email/partner1/ <- файлы и конфигурация для партнера
/var/transfer/email/partner1/recipient <- файл с адресом получателя
/var/transfer/email/partner1/.pswd <- понятно
/var/transfer/email/partner1/out/ <- очередь архивов на отсылку
/var/transfer/email/partner1/spool/ <- локальный спулер файлов для архивирования
/var/transfer/email/partner1/backup/ <- архив полученных и отосланных файлов (в основном на время отладки)

В текстовом редакторе создадим содержимое тела письма (простейший HTML):
rat@assistant:~$ sudo vim /var/transfer/email/message_body

Файлы recipient и .pswd содержат адрес получателя и пароль шифрования соответственно.

Скрипт архивирования и отсылки:
rat@assistant:~$ sudo vim /var/transfer/email/fetch
#!/bin/sh

# Find and fetch files for processing over email

# Partner1 #################################
pswd=`cat /var/transfer/email/partner1/.pswd`
rcpt=`cat /var/transfer/email/partner1/recipient`
src='/mnt/company/#encrypted_email_partner1/'
spool='/var/transfer/email/partner1/spool/'
out='/var/transfer/email/partner1/out/'
bkp='/var/transfer/email/partner1/backup/'

# Files only, no subfolders, older than 3 min, ignore hidden files
/usr/bin/find $src -maxdepth 1 -not -path '*/\.*' -mmin +3 -type f -exec mv '{}' $spool \;

# Files should be moved from spool to backup only on successful archiving
if [ "$(ls -A $spool)" ]
then
/usr/bin/zip -j -P $pswd $out/company_transfer_`date +\%Y\%m\%d\%H\%M\%S`.zip $spool/*
if [ $? -eq 0 ]
then
mv $spool/* $bkp
fi
fi

# Archives should be removed from outbox only on successful transfer
if [ "$(ls -A $out)" ]
then
cd $out
for i in `ls -A $out`
do
/usr/bin/mutt -s "CompanyName secure document transfer `date +\%Y\%m\%d\%H\%M`" $rcpt -a "$i" < /var/transfer/email/message_body if [ $? -eq 0 ] then mv $i $bkp fi done fi

Запуск скрипта по расписанию, каждые 5 минут:
rat@assistant:~$ cat /etc/cron.d/securemail
# /etc/cron.d/fetch: crontab entry to deliver files for encryption and sending over email

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*/5 * * * * root test -x /var/transfer/email/fetch && /var/transfer/email/fetch >/dev/null

Если все настроено правильно, файлы будут забираться с сервера, архивироваться с паролем и отсылаться получателю, указанному в файле recipient, с адреса, указанного в .muttrc.

Логгинг добавить по вкусу. Отправку почты на CC, BCC и список адресов смотрим в документации к Mutt.
Хотя, отсылка на список адресов в Mutt выглядит так:
a="address1@mail.com, address2@mail.com"
mutt -s "subject" -a file.pdf -- $a

Про корректные права на каталоги, исполняемые файлы и особо чувствительные данные все и так все знают.

P.S. Скрипты в данной конфигурации работают от root'a, но, так как сторонний контент не выполняется, решение достаточно безопасное. При желании можно создать отдельного пользователя под задачи автоматизации.
P.S.S. Mutt сохраняет отосланные сообщения в файле sent в каталоге того пользователя, от которого работает Mutt. Так что при серьезном потоке сообщений место на диске съедается очень заметно. Отключение сохранения отосланных сообщений в Mutt делается директивой в .muttrc:
set copy=no

Умная розетка Tp-Link Wi-Fi Smart Plug HS100

Заметка планировалась как очень краткий обзор умной розетки и использование дополнительных возможностей управления Tp-Link Wi-Fi Smart Plug HS100 по сети, а вылилась в анализ ситуации с безопасностью этих самых “умных” девайсов. И ситуация, мягко говоря, не очень хорошая.

Такие розетки нельзя использовать в сети, которую вы не контролируете, например в публичной сети или сети без шифрования (а так же WEP, WPA) или со слабым паролем. Категорически не рекомендуется использовать всю линейку Tp-Link Wi-Fi Smart Plug для подключения оборудования, неожиданное включение или выключение которого может нанести вред самому оборудованию или другому имуществу владельца (холодильники, нагреватели, насосы, и т.д.)!

Во-первых, для доступа к оборудованию не используется какая-либо идентификация. Вообще. Любое устройство в локальной сети может послать команду на включение, выключение, изменение параметров или сброс настроек.
Во-вторых, протокол передачи команд между смартфоном с установленной программой “Kasa” или облаком и розеткой использует алгоритм шифрования 16 века с известным ключом. Можно сказать, что его практически нет.

Во всех нюансах управления этими розетками разобрались до меня. В интернете полно материалов для самостоятельного чтения. Самое интересное – это, конечно же, реверс-инжениринг от softScheck

Есть 2 интересных проекта, которые позволят познакомиться с проблемами IoT поближе:

  1. iot-toolkit – набор утилит для обнаружения “умных” устройств в сети и организации атак;
  2. tplink-smartplug – клиентская часть для управления розетками TP-Link, написанная на Python;

Рабочая машина – Ubuntu Server 16.04 LTS.

Для сборки iot-tools понадобятся дополнительные библиотеки.
$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install clang libpcap-dev libssl-dev
$ cd ~/projects
$ git clone https://github.com/fgont/iot-toolkit.git
$ cd iot-toolkit
$ make all

Tplink-smartplug тоже забираем с GitHub, там много полезной информации:
$ cd ~/projects
$ git clone https://github.com/softScheck/tplink-smartplug.git

Посмотрим что у нас в сети (enp0s3), где-то там “умная” розетка:
$ sudo ~/projects/iot-toolkit/iot-scan -v -L -i enp0s3
192.168.88.102 # IOT.SMARTPLUGSWITCH: TP-Link HS100(EU): Wi-Fi Smart Plug: "Smart Gnome"

Набор команд управления довольно большой. Можно сделать все что угодно, авторизации нет как класса.
Данные передаются и принимаются в JSON.

Начнем с безобидных, спросим сколько времени:
$ ~/projects/tplink-smartplug/tplink_smartplug.py -t 192.168.88.102 -c time
Sent: {"time":{"get_time":{}}}
Received: {"time":{"get_time":{"err_code":0,"year":2018,"month":8,"mday":9,"wday":4,"hour":20,"min":23,"sec":39}}}

Просмотр общей информации, запрос в виде JSON:
$ ~/projects/tplink-smartplug/tplink_smartplug.py -t 192.168.88.102 -j '{"system":{"get_sysinfo":{}}}'
Sent: {"system":{"get_sysinfo":{}}}
Received: {"system":{"get_sysinfo":{"err_code":0,"sw_ver":"1.2.5 Build 171213 Rel.101415","hw_ver":"1.0","type":"IOT.SMARTPLUGSWITCH","model":"HS100(EU)",
"mac":"50:C7:BF:XX:XX:XX","deviceId":"800665D682EB40DC3FA09799XXXXXXXXXXXXXXXX",
"hwId":"22603EA5E716DEAEXXXXXXXXXXXXXXXX","fwId":"00000000000000000000000000000000",
"oemId":"812A90EB2FCF306AXXXXXXXXXXXXXXXX","alias":"Smart Gnome","dev_name":"Wi-Fi Smart Plug",
"icon_hash":"","relay_state":1,"on_time":130083,"active_mode":"none","feature":"TIM",
"updating":0,"rssi":-81,"led_off":0,"latitude":0,"longitude":0}}}

Как поменять настройки или сбросить все можно посмотреть в документации к tplink-smartplug.
Как организовать атаку и положить сеть можно узнать из документации к iot-tools.

Несколько интересных презентаций

Дополнительная информация по взлому розеток tp-link, других устройств, рекомендации по обеспечению безопасности устройств – Hacking TP-Link Devices
Дополнительная информация от аналитиков везопасности из softScheck – Internet of (dangerous) Things

Резервное копирование сайта по расписанию (WordPress)

Настраиваем резервное копирование любимого сайтика. Сайтик расположен на дружественном shared-хостинге (Debian Linux). Но есть нюансы: администратор хостинга ничего не гарантирует. Один раз он просто сменил номер телефона и пропал на месяц. Практически целый месяц сервер был недоступен. Это не коммерческий проект, но, все равно, очень неприятно.
Есть доступ по ssh (sftp, scp) и права запускать программы.
Резервное копирование разделим на 2 этапа: создание копии на удаленном сервере и перенос в безопасное место.

Резервное копирование на удаленном сервере

Данные WordPress разделены на 2 компонента: база (в моем случае MySQL) и файлы, как картинки, так и специальные.

Создание архива, в общем виде команда такая:
$ /usr/bin/zip -v -r /home/user/site.tld.`date +%Y-%m-%dT%H:%M:%S`.zip /home/user/site.tld/htdocs

Дамп базы. Несмотря на то, что пароль и так хранится в явном виде в файле wp-config.php, светить его лишний раз не стоит.
Для запуска mysqldump без пароля создадим файл конфигурации:
$ vim ~/.my.cnf

[mysqldump]
user = mysqluser
password = mysqlpassword

Ставим корректные права на файл
$ chmod 600 ~/.my.cnf

Проверим, что все работает
$ /usr/bin/mysqldump -u mysqluser dbname > /home/user/site.tld.`date +%Y-%m-%dT%H:%M:%S`.sql

Создаем расписание срабатывания команд через crontab (особое внимание на форматирование параметров команды date!)
$ crontab -e

# m h dom mon dow command
0 3 * * 6 /usr/bin/mysqldump -u mysqluser dbname > /home/user/site.tld.`date +\%Y-\%m-\%dT\%H:\%M:\%S`.sql
5 3 * * 6 /usr/bin/zip -r /home/user/sitename.tld.`date +\%Y-\%m-\%dT\%H:\%M:\%S`.zip /home/user/site.tld/htdocs

Еженедельное копирование в субботу в 3:00 и 3:05 соответственно.

Перенос данных с удаленного сервера

Перво-наперво избавимся от необходимости вводить пароль при удаленном подключении по ssh/scp. Когда-то в древности я уже писал как настроить подключение по сертификату.

Забирать файлы будем через rsync + ssh. Порт ssh на удаленной системе нестандартный – 2222. Файлы будем перемещать, а не копировать.

$ rsync -avz --remove-source-files -e "ssh -p 2222" user@remote:site.tld.\* /home/user/backup

1. Wildcard!
2. На удаленной системе так же должен быть установлен rsync. Иначе любые попытки скачать файлы будут заканчиваться вот такой проблемой:
bash: rsync: command not found
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: remote command not found (code 127) at io.c(226) [Receiver=3.1.1]

Запись в crontab выглядит так:
$ crontab -e

# m h dom mon dow command
30 3 * * 6 /usr/bin/rsync -avz --remove-source-files -e "/usr/bin/ssh -p 2222" user@remote:site.tld.\* /home/user/backup >/dev/null 2>&1

Проблема с установкой Zabbix Agent на Windows 10

На Windows 10 Pro 64-bit Zabbix Agent не хочет устанавливаться в соответствии с официальной документацией.

c:\zabbix\bin\win64>.\zabbix_agentd.exe -c c:\zabbix\conf\zabbix_agentd.conf --install
zabbix_agentd.exe [5104]: ERROR: cannot connect to Service Manager: [0x00000005] Access is denied.

Ошибка появляется несмотря на достаточные права у пользователя, от которого идет установка.

Для корректной установки все действия необходимо проводить с правами Администратора:
Search -> cmd -> Run as Administrator
c:\zabbix\bin\win64>.\zabbix_agentd.exe --config "c:\zabbix\conf\zabbix_agentd.conf" --install
zabbix_agentd.exe [4260]: service [Zabbix Agent] installed successfully
zabbix_agentd.exe [4260]: event source [Zabbix Agent] installed successfully
c:\zabbix\bin\win64>.\zabbix_agentd.exe --start
zabbix_agentd.exe [3684]: service [Zabbix Agent] started successfully

←Older