Заметки в категории How To

How To: Проксируем весь трафик через ssh

Иногда надо отправить весь трафик через удаленный сервер. VPN'а и ничего другого, кроме ssh, нет. Чтоб провернуть этот фокус одной коммандой нам понадобится только python на обоих концах "туннеля" и ssh доступ.

Устанавливаем пакетный менеджер pip:

$ sudo apt install python-pip

Устанавливаем sshuttle:

$ sudo pip install sshuttle

Запускаем туннель:

$ sshuttle -r user@example.com 0.0.0.0/0

Все. С этого момента весь траффик пойдет через сервер example.com. И да, для консольных утилит тоже.

Чтоб DNS трафик пошел туда же надо добавить опцию --dns. Учтите, что если вы используете провайдерский DNS, то он может перестать отдавать записи:

$ sshuttle --dns -r user@example.com 0.0.0.0/0

Более подробное описание смотрите в официальной документации.

HowTo: использование команды grep в Linux - примеры

grep — утилита командной строки, которая находит на вводе строки, отвечающие заданному регулярному выражению, и выводит их, если вывод не отменён специальным ключом.

Синтаксис

Синтаксис может быть следующим:

grep 'word' filename
grep 'word' file1 file2 file3
grep 'string1 string2'  filename
cat otherfile | grep 'something'
command | grep 'something'
command option1 | grep 'data'
grep --color 'data' fileName

Поиск по файлу

Чтобы выполнить поиск пользователя boo в файле /etc/passwd запустите:

$ grep boo /etc/passwd

Вывод будет примерно таким:

boo:x:1000:1000:boo,,,:/home/boo:/bin/ksh

Так же вы можете выполнить регистронезависимый поиск строки boo (например, bOo, Boo, BOO и т.п.):

$ grep -i "boo" /etc/passwd

Рекурсивный поиск

Можно искать во всех файлах в каталоге:

$ grep -r "192.168.1.5" /etc/

или

$ grep -R "192.168.1.5" /etc/

Пример ла, в котором встречается искомая строка (например, /etc/ppp/options). Такое поведение можно отключить, т.е. grep не будет вставлять в результаты поиска имена файлов, добавив ключ -h:

$ grep -h -R "192.168.1.5" /etc/

или

$ grep -hR "192.168.1.5" /etc/

Пример вывода:

# ms-wins 192.168.1.50
# ms-wins 192.168.1.51
addresses1=192.168.1.5;24;192.168.1.2;

Использование grep для поиска только слов

Если вы ищете boo, то grep найдет и такое сочетание fooboo, boo123, 123boofoo и т.п. Для того чтоб grep нашел именно слово boo можно указать ключ -w:

$ grep -w "boo" file

Поиск двух разных слов

$ egrep -w 'word1|word2' /path/to/file

Подсчет количества

grep может посчитать количество вхождений слова в файл:

$ grep -c 'word' /path/to/file

Опция -n позволит вывести пронумерованные строки из файла номером этой строки:

$ grep -n 'root' /etc/passwd

Пример вывода:

1:root:x:0:0:root:/root:/bin/bash
1042:rootdoor:x:0:0:rootdoor:/home/rootdoor:/bin/csh
3319:initrootapp:x:0:0:initrootapp:/home/initroot:/bin/ksh

Инвертированный вывод

Вы можете использовать параметр -v для инвертирования вывода, т.е. вывести все строки кроме тех, в которых встречается искомое слово:

$ grep -v bar /path/to/file

Unix / Linux конвеер и grep

grep можно комбинировать с конвеером (pipe). Этот пример выведет имена жестких дисков:

# dmesg | egrep '(s|h)d[a-z]'

Показать модель CPU:

# cat /proc/cpuinfo | grep -i 'Model'

Эта же команда может быть выполнена по другому без pipe:

# grep -i 'Model' /proc/cpuinfo

Пример вывода:

model       : 30
model name  : Intel(R) Core(TM) i7 CPU       Q 820  @ 1.73GHz
model       : 30
model name  : Intel(R) Core(TM) i7 CPU       Q 820  @ 1.73GHz

Вывести только список файлов

Передав параметр -l можно вывести только имена файлов:

$ grep -l 'main' *.c

И, наконец, можно вывести результат с подсветкой:

$ grep --color vivek /etc/passwd

How To: Проксирование в приватный AWS S3 через Nginx

Проблема

Иногда нам надо давать доступ к приватному баккету в Amazon S3 с авторизацией в наших сервисах, например LDAP или банальный Basic Auth. Стандартный Nginx, к сожалению, этого не позволяет сделать. Но в интернете полно инструкций как это сделать с помощью LUA модуля Nginx. Тут я расскажу как собрать Nginx с модулем LUA и всем необходимым, чтоб можно было проксировать запросы в Amazon S3 и в конце укажу на ошибку в конфигурации из сети, которая валяется почти на каждом углу. После чего мы эту ошибку исправим.

Сборка Nginx

Для сборки нам понадобятся исходники самого Nginx, модуля LUA, Nginx Development Kit и Set Misc модуль для Nginx. Итак, устанавливаев необходимое программное обеспечение

apt install build-essential automake libgd-dev libluajit-5.1-dev libgeoip-dev

Скачиваем необходимые модули и исходники:

mkdir -p ~/tmp/nginx
wget -O ~/tmp/nginx/nginx.tar.gz http://nginx.org/download/nginx-1.11.1.tar.gz
cd ~/tmp/nginx
tar -vxzf ~/tmp/nginx/nginx.tar.gz

git clone https://github.com/simpl/ngx_devel_kit.git
git clone https://github.com/openresty/lua-nginx-module.git
git clone https://github.com/openresty/set-misc-nginx-module.git

Собираем Nginx со всеми модулями:

./configure --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_sub_module --with-http_xslt_module --with-mail --with-mail_ssl_module --add-module=${HOME}/tmp/nginx/ngx_devel_kit --add-module=${HOME}/tmp/nginx/set-misc-nginx-module --add-module=${HOME}/tmp/nginx/lua-nginx-module

Останавливаем сервис Nginx и заменяем бинарный файл:

sudo service nginx stop
sudo cp -f objs/nginx /usr/sbin/nginx

Теперь рассмотрим конфигурацию. Я приведу только location, т.к. если вы задумались о проксировании в AWS, то уже должны знаете, что такое конфигурация Nginx:

    location ~* ^/(.*) {
      set $bucket           'bucket-name';
      set $aws_access       'AWS_ACCESS_TOKEN';
      set $aws_secret       'AWS_ACCESS_SECRET';
      set $url_full         "$1";
      set_by_lua $now       "return ngx.cookie_time(ngx.time())";
      set $string_to_sign   "$request_method\n\n\n\nx-amz-date:${now}\n/$bucket/$url_full";
      set_hmac_sha1          $aws_signature $aws_secret $string_to_sign;
      set_encode_base64      $aws_signature $aws_signature;
      resolver               8.8.8.8 valid=300s;
      resolver_timeout       10s;
      proxy_http_version     1.1;

      proxy_set_header       Host $bucket.s3.amazonaws.com;
      proxy_set_header       x-amz-date $now;
      proxy_set_header       authorization "AWS $aws_access:$aws_signature";
      proxy_buffering        off;
      proxy_intercept_errors on;

      rewrite .* /$url_full break;
      proxy_pass             http://$bucket.s3.amazonaws.com;
    }

Нужно подставить ваши ключи доступа к AWS и все должно заработать как надо. Но тут есть одна проблема. Если вы храните в баккете файлы с именами без пробелов, то вы ее не заметите. Все будет работать и так. Но если вам попадется файл с пробелом в имени, то Амазон вам его не отдаст с ошибкой о некорректной сигнатуре.

Это и есть та самая проблема о которой я говорил выше. Почему так происходит? Все дело в том, что Амазон пробел заменяет на знак "+", а мы кодируем его как "%20". Т.е. сервис Амазона не видит такого файла вообще.

Поскольку проблема понятна, то и решить ее можно достаточно легко с помощью все того же LUA:

    set_by_lua $url_decoded "return ngx.re.gsub(ngx.var.url_full, '%20', '+')";

Что происходит в этой строке:

  1. Устанавливаем переменную \$url_decoded с помощью LUA
  2. Пишем в нее результат от ngx.re.gsub - это функции замены
  3. ngx.var.url_full - переменная в которой будет делаться поиск
  4. '%20' - то, что ищем
  5. '+' - то, на что меняем

И дальше в конфиге заменить везеде \$url_full на \$url_decoded. Результирующий конфиг будет такой:

  location ~* ^/(.*) {
    set $bucket           'bucket-name';
    set $aws_access       'AKIAJAL2RFUF73T66RBA';
    set $aws_secret       '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';
    set $url_full         "$1";
    set_by_lua $url_decoded "return ngx.re.gsub(ngx.var.url_full, '%20', '+')";
    set_by_lua $now       "return ngx.cookie_time(ngx.time())";
    set $string_to_sign   "$request_method\n\n\n\nx-amz-date:${now}\n/$bucket/$url_decoded";
    set_hmac_sha1          $aws_signature $aws_secret $string_to_sign;
    set_encode_base64      $aws_signature $aws_signature;
    resolver               8.8.8.8 valid=300s;
    resolver_timeout       10s;
    proxy_http_version     1.1;

    proxy_set_header       Host $bucket.s3.amazonaws.com;
    proxy_set_header       x-amz-date $now;
    proxy_set_header       authorization "AWS $aws_access:$aws_signature";
    proxy_buffering        off;
    proxy_intercept_errors on;

    rewrite .* /$url_decoded break;
    proxy_pass             http://$bucket.s3.amazonaws.com;
  }

Теперь можно запускать сервис Nginx:

sudo service nginx start

Авторизацию, я думаю, вы и сами уже умеете прикручивать к Nginx. ;)

25 примеров использования утилиты find

Краткое описание find

Утилита find позволяет искать по:

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

Если файл был найден, то мы можем сделать следующее:

  • просмотреть или отредактировать
  • сохранить
  • удалить или переименовать
  • сменить права доступа
  • любое другое действие

Немного примеров:

Простой поиск

1. Поиск всех обычных файлов

$ find Symfony -type f
Symfony/web/.htaccess
Symfony/web/app.php
Symfony/web/app_dev.php
Symfony/web/robots.txt
...

2. Поиск всех каталогов

$ find Symfony -type d
Symfony/
Symfony/web
Symfony/web/bundles
Symfony/web/bundles/webprofiler
...

3. Поиск по имени файла или каталога

$ find Symfony -name '*config*';
Symfony/app/config
Symfony/app/config/config_prod.yml
Symfony/app/config/config.yml
...

4. Поиск по имени (регистронезависимый)

$ find Symfony -iname '*config*';
...
Symfony/.../Loader/ConfigurationLoader.php
Symfony/.../ConfigurationResource.php
...
Symfony/app/config
Symfony/app/config/config_prod.yml
Symfony/app/config/config.yml
...

Поиск на основании размера

5. Найти все файлы, размер которых 300MB

$ find . -size 300M

6. Найти все файлы, размер которых больше 300MB

$ find . -size +300M

7. Найти все файлы, размер которых меньше 300MBкаталоги

$ find . -empty

Поиск по дате

GNU/Linux хранит последнюю дату следующих операций:

Операция Значение Опции find
access чтение содержимого файла -atime, -amin
modification изменение контента файла -mtime, -mmin
change of status смена имени файла или атрибутов (права доступа, владелец, ...) -ctime, -cmin

Чтоб узнать даты файла можно использовать команду stat:

$ stat index.php
...
Access: 2016-06-02 22:53:22.813885684 -0500
Modify: 2016-05-08 12:12:12.971073193 -0500
Change: 2016-05-08 12:12:12.971073193 -0500

10. Найти файлы с датой доступа менее 15 дней назад

$ find . -atime -15

11. Найти модифицированные файлы более 7 дней назад

$ find . -mtime +7

12. Найти измененные файлы в промежутке от 2 до 6 минут назад

$ find . -cmin +2 -cmin -6

Поиск основанный на имени пользователя или группы

13. Найти файлы пользователя sedlav

$ find . -user sedlav -type f

14. Найти файлы, которые относятся к группе flossblog

$ find . -group flossblog -type f

15. Найти файлы, где владелец имет uid между 500 и 1000 (исключая 500 и 1000)

$ find . -uid +500 -uid -1000 -type f

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

16. Найти все файлы, которые не принадлежат ни одному пользователю

$ find . -nouser

17. Найти все файлы, которые не принадлежат ни одной группе

$ find . -nogroup

Поиск на основании прав доступа

find позволяет искать файлы, которые может читать (-readable), писать (-writable) или запускать (-executable) текущий пользователь или файлы, которые имеют определенные права

18. Найти все файлы, которые может читать текущий пользователь

$ find . -readable

19. Найти все файлы, которые может записывать текущий пользователь

$ find . -writable

20. Найти все файлы, которые может запускать текущий пользователь

$ find . -executable

Поиск файлов с определенными правами доступа

-perm PMODE

  • PMODE может быть числовым или символьным
  • PMODE может иметь префикс / или -
  • Если PMODE не имеет префикса / или -, тогда права файла должны точно соответствовать PMODE
  • Если PMODE имеет префикс -, то права файла должны содержать PMODE
  • Если PMODE имеет префикс /, то права файла должны содержать любой из битов указанных в PMODE (символьные права не допустимы)
Права Числовое обозначение Символьное обозначение
Чтение 4 r
Запись 2 w
Запуск 1 x

Примеры:

21. Найти все файлы, владелец и группа которых имеют права на чтение и запись, а остальные могут только читать
$ find -perm 664
22. Найти все файлы, владелец и группа которых имеют права на чтение и запись, а остальные могут только читать

Примечание: - перед правами указывает на то, что будут найдены так же все файлы с правами: 777, 666, 776

$ find . -perm -664
23. Найти все файлы, которые может модифицировать (записывать) любой пользователь
$ find . -perm /222

Расширенный поиск

24. Поиск на основе регулярных выражений по каталогам на 1 уровень ниже

Найти все каталоги одним уровнем ниже каталога project (не рекурсивный поиск), которые не пусты, не оканчиваются на цифру, old backups, bkp или содержат слова backup, copy, new с последующим одинм из символов -_. .

$ PATTERN='.*/((.*([0-9]|old|ba?c?ku?ps?))|(..*)|(copy|new|backup|back|)[-_.].*)$';
$ find project -maxdepth 1 -mindepth 1 -regextype posix-egrep ! -iregex  $PATTERN  ! -empty -type d

25. Комбинируем find, xargs и grep

Это очень удобный пример для сложного поиска. Пример, найдем слово ireg во всех php файлах в project:

$ find project -name '*.php' -type f -print0 | xargs -0 grep -l ireg

Оригинал статьи

Как перейти на SHA256 в GnuPG

Алгоритм хеширования SHA1 уже считается не надежным, но все еще используется во многих системах, в том числе и GnuPG для цифровой подписи. Я не считаю, что это правильно и пора переходить на более надежные алгоритмы.

Я предпочитаю использовать SHA256. Если Вы готовы перейти на более безопасные стандарты, давайте приступим.

Для начаого давайте всем расскажем, что мы предпочитаем использовать SHA256. Для этого надо исправить предпочтения в ключе.

Получаем ID нашего ключа:

$ gpg --list-keys

Для примера мой вывод этой команды:

/home/silver/.gnupg/pubring.gpg
-------------------------------
pub   4096R/05420A87 2012-11-07
uid                  Dmitriy Lyalyuev <dmitriy@lyalyuev.info>
uid                  Dmitriy Lyalyuev <dmitriy@lyalyuev.pp.ua>
sub   4096R/6C406AF5 2012-11-07

Читать далее...

How To: Сборка Nginx со сторонней версией OpenSSL на Fedora 14

Есть у нас один старый сервер на Fedora 14 (о нем я уже писал в заметке о закрытии уязвимости в bash). В связи с последними уязвимостями в OpenSSL и жутко древнего OpenSSL в системе было решено поставить Nginx перед Apache и термнировать SSL трафик на нем.

Установили и настроили Nginx:

$ sudo yum install nginx

Но вот незадача, системный Nginx оказался древним (0.8.54) и многого не умел из коробки. Было принято решение собрать последний Nginx (1.9.1) и установить его поверх системного. Это позволит не заморачиваться со скриптами инициализации.

Делается это довольно просто. Для начала ставим необходимые пакеты:

$ sudo yum -y install gcc gcc-c++ make zlib-devel pcre-devel openssl-devel

Теперь скачиваем Nginx и собираем его:

$ cd /usr/src
$ wget http://nginx.org/download/nginx-1.9.1.tar.gz
$ tar -vxf nginx-1.9.1.tag.gz
$ cd nginx-1.9.1
$ ./configure --user=nginx --group=nginx --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --with-http_ssl_module --with-pcre
$ make

Для установки требуются root права:

$ sudo make install

Рестарт Nginx показал, что все работает как положено, но системная библиотека openssl очень старая и не поддерживает TLSv1.2. Пришлось собирать nginx со свежей версией openssl:

$ cd /usr/src
$ wget https://www.openssl.org/source/openssl-1.0.2a.tar.gz
$ tar -vxf openssl-1.0.2a.tar.gz
$ cd /usr/src/nginx-1.9.1
$ make clean
$ ./configure --user=nginx --group=nginx --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --with-http_ssl_module --with-pcre --with-openssl=/usr/src/openssl-1.0.2a/
$ make

Процесс сборки nginx с новой библиотекой openssl несколько дольше, чем без нее, но проходит все гладко. Устанавливаем:

$ sudo make install
$ sudo /etc/init.d/nginx restart

How To: Восстановление случайно поврежденной таблицы разделов GPT

Представим ситуацию, что у вас на сервере заменили вышедший из строя диск и вам необходимо восстановить работу RAID. Но у вас на "живом" диске таблица разделов не MBR, а Gе вы перепишете таблицу разделов и можете потерять данные.

Именно "можете", но еще не потеряли. Восстановить таблицу разделов еще можно.

Первое, что необходимо сделать - это сохранить текущую используемую таблицу разделов из памяти, на всякий случай:

# gdisk /dev/sda

Нажимаем 'b' и пишем имя файла "/part.bin". Теперь пробуем восстановить таблицу на второй диск, чтоб не потерять данные:

# gdisk /dev/sdb

Нажимаем 'r', затем 'l' и пишем имя нашего файла '/part.bin'. После этого смотрим, что у нас получилось нажав на 'p'.

Если данные похожи на правду, то можно проделать ту же операцию с sda. Но для начала я бы рекомендовал перестраховаться и ввести разделы в RAID, дождаться синхронизации и потом записать таблицу на диск sda.

Но если вы не боитесь потерять данные, то можно попробовать сразу восстановить таблицу разделов из резервной копии GPT:

# gdisk /dev/sda

Далее нажимаем 'r' и 'b'. Утилита восстановит таблицу разделов GPT из ее копии на диске. Проверить можно нажав 'p'.

Таким образом, GPT гораздо надежнее MBR в плане защиты от потери данных и резервирования информации о таблице разделов.

How To: Создание нового пользователя в MySQL

Для начала подключаемся к базе данных:

mysql -u root -p

Вводим пароль и получаем доступ к коммандной строке базы данных.

Создаем пользователя

CREATE USER 'newuser'@'localhost' IDENTIFIED BY 'password';

После этого у нас будет пользователь newuser без права доступа к каой либо базе данных.

Теперь необходимо дать права на доступ к базе данных. Создаем базу:

CREATE DATABASE test;

и все права доступа:

GRANT ALL PRIVILEGES ON test.* TO 'newuser'@'localhost';

Или же можно выдать права на все базы и все таблицы:

GRANT ALL PRIVILEGES ON *.* TO 'newuser'@'localhost';

Как только мы закончили, необходимо перечитать права:

FLUSH PRIVILEGES;

Теперь изменения применились.
Читать далее...

How To: ошибка Amavis Can’t locate Mail/SpamAssassin...

Сегодня после рестарта и допиливания Amavis в логах появилась такая ошибка:

07 Oct 10:13:48 mail amavis[66684]: (!)_DIE: Can’t locate Mail/SpamAssassin/CompiledRegexps/body_0.pm in @INC (@INC contains: /var/db/spamassassin/compiled/5.008/3.003000 /var/db/spamassassin/compiled/5.008/3.003000/auto lib /usr/local/lib/perl5/5.8.8/BSDPAN /usr/local/lib/perl5/site_perl/5.8.8/mach /usr/local/lib/perl5/site_perl/5.8.8 /usr/local/lib/perl5/site_perl /usr/local/lib/perl5/5.8.8/mach /usr/local/lib/perl5/5.8.8) at (eval 875) line 1.
07 Oct 10:13:48 mail amavis[66684]: (!)_DIE: Can’t locate Mail/SpamAssassin/CompiledRegexps/body_0.pm in @INC (@INC contains: /var/db/spamassassin/compiled/5.008/3.003000 /var/db/spamassassin/compiled/5.008/3.003000/auto lib /usr/local/lib/perl5/5.8.8/BSDPAN /usr/local/lib/perl5/site_perl/5.8.8/mach /usr/local/lib/perl5/site_perl/5.8.8 /usr/local/lib/perl5/site_perl /usr/local/lib/perl5/5.8.8/mach /usr/local/lib/perl5/5.8.8) at (eval 875) line 1.\nBEGIN failed—compilation aborted at (eval 875) line 1.

После чего Amavis падает. Решается просто:

sudo sa-compile
sudo sa-update -D
sudo service amavis restart

Как изменить MAC адрес bluetooth устройства

Для начала посмотрим какие устройства у нас есть в системе:

$ sudo -i
# hcitool dev
Devices:
  hci0 00:11:22:33:44:55

Теперь надо собрать утилиту для смены MAC:

# pushd /tmp
# git clone https://github.com/DmitriyLyalyuev/bdaddr.git
# cd bdaddr
# make

Проверяем, видит ли утилита устройства:

# ./bdaddr

Меняем MAC:

# ./bdaddr -i hci0 11:11:11:11:11:11
# popd

Отключаем dongle и подключаем назад. Проверяем:

# hcitool dev
Devices:
  hci0 11:11:11:11:11:11