Показаны сообщения с ярлыком администрирование. Показать все сообщения
Показаны сообщения с ярлыком администрирование. Показать все сообщения

28 июня 2016 г.

Как отсыпать совсем немножечко рута для Java и разрешить захватывать сетевые пакеты

В различных дистрибутивах Linux такие программы, как tcpdump и wireshark, использующиеся для анализа сетевого трафика, обычно требуют прав суперпользователя для получения доступа к возможностям захвата пакетов. Точно также дело обстоит и с Java-программами, которые используют системную библиотеку libpcap. Причем в этом случае вам придется запустить с неограниченными правами саму виртуальную машину Java, которая уже в свою очередь будет исполнять ваш код. Я думаю, мало кто любит лишний раз сорить суперправами направо и налево, поэтому в Linux, начиная с ядра 2.2 появилась такая штука, как Linux Capabilites, которая позволяет наделить непривилегированные процессы только необходимыми возможностями суперпользователя. В данном случае, например, нас интересует только возможность перехвата и отправки сетевых пакетов. Для установки и просмотра Linux Capabilites необходимы программы setcap и getcap, соответственно. У меня в openSUSE эти утилиты находятся в пакете libcap-progs, а в Ubuntu в пакете libcap2-bin.

Установка возможности захвата и отправки сетевых пакетов и возможности изменения конфигурации интерфейсов выглядит так:
setcap cap_net_raw,cap_net_admin=eip /usr/local/lib64/jdk1.8.0_77/bin/java
Просмотр установленных возможностей:
getcap /usr/local/lib64/jdk1.8.0_77/bin/java
/usr/local/lib64/jdk1.8.0_77/bin/java = cap_net_admin,cap_net_raw+eip
Всё просто, но если после установки этих возможностей попробовать запустить программу java из под обычного пользователя, то это не очень получится:
java -version
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
Это происходит из-за того, что при наличии у непривилегированного процесса возможностей, которыми он вроде как обладать не должен, загрузчик динамических библиотек запрещает загрузку библиотек из недоверенных каталогов. Доверенными каталогами по умолчанию являются /lib и /usr/lib (а также /lib64 и /usr/lib64).

С помощью утилиты ldd посмотрим, какие динамические библиотеки использует java: 
ldd /usr/local/lib64/jdk1.8.0_77/bin/java
        linux-vdso.so.1 (0x00007ffc91ffd000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc3dc124000)
        libjli.so => /usr/local/lib64/jdk1.8.0_77/bin/../lib/amd64/jli/libjli.so (0x00007fc3dbf0d000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fc3dbd09000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fc3db961000)
        /lib64/ld-linux-x86-64.so.2 (0x00005584e041d000)
Как видно из вывода команды ldd, при запуске java не удалось загрузить как раз ту самую библиотеку, которая находится в недоверенном каталоге ../lib/amd64/jli/.

Это можно легко пофиксить, добавив файл с расширением .conf  в каталог /etc/ld.so.conf.d, в котором перечислить все необходимые пути. В случае с java это всего лишь один каталог:
echo /usr/local/lib64/jdk1.8.0_77/lib/amd64/jli > /etc/ld.so.conf.d/java.conf
После изменения файлов в /etc/ld.so.conf.d может потребоваться перестроить кэш библиотек, для этого нужно выполнить:
ldconfig
Проверяем, что загрузчик видит нашу библиотеку:
ldconfig -v |grep jli
/usr/local/lib64/jdk1.8.0_77/lib/amd64/jli:
     libjli.so -> libjli.so
Ну и на всякий случай, команда для удаления всех дополнительных возможностей у программы:
setcap -r /usr/local/lib64/jdk1.8.0_77/bin/java
Ещё хотелось бы отметить, что не стоит без лишней необходимости добавлять нестандартные возможности вашей глобальной системной Java-машине, потому что в этом случае любая запущенная Java-программа сможет ими воспользоваться. Для разработки и запуска программ с завышенными потребностями лучше завести отдельный экземпляр Java-машины.

Где отрыто

Как приструнить Wireshark
Небаг в багтрекере Java
Куришка: man capabilities


28 марта 2016 г.

Установка Java Development Kit в Linux из архива tar.gz

Данный пост, это просто обновление поста 2010 года, который до сих пор пользуется довольно большой популярностью, а так как с тех времен уже немало воды утекло, то я посчитал своим долгом актуализировать эту информацию. По пути также кое-что было переработано, надеюсь, в сторону понятности.
Если вам потребовался стандартный JDK от Oracle, вместо OpenJDK, который поставляется с современными свободными дистрибутивами Linux, то его можно скачать либо с дополнительных сторонних репозиториев для вашего дистрибутива, либо напрямую с сайта www.oracle.com. Если ставить Java из репозиториев для вашего дистрибутива, то скорее всего всё само настроется и заработает, и ни о чем беспокоится вам не придется, но если вы скачали JDK или JRE в виде архива tar.gz с сайта Oracle, придется совершить несколько дополнительных телодвижений.

На данный момент скачать JDK с сайта Oracle можно в двух видах: это RPM-пакет и вышеупомянутый архив tar.gz. Про то, на сколько удачно ставится JDK из RPM-пакета, мне сказать нечего - не пробовал. Я предпочитаю устанавливать JDK именно из архива, потому что так я получаю полное управление и понимание того, что и откуда у меня будет запускаться, а также универсальное решение, которое подойдет для всех дистрибутивов, а не только для RPM-based.

План действий
  1. Скачать нужную версию JDK (архив tar.gz)
  2. Распаковать архив
  3. Настроить переменные окружения
  4. Настроить update-alternatives
Куда распаковать?

Итак, скачали JDK. Распаковываем. Но куда? Вроде бы тупой вопрос, но я далеко не сразу пришёл к правильному  для себя  решению. Сейчас я все JDK распаковываю в каталог /usr/local/lib64 и там у меня одновременно живёт несколько версий JDK. Например, на данный момент, там у меня есть каталоги jdk1.7.0_79 и jdk1.8.0_77. В дополнение к этим каталогам, в /usr/local/lib64 у меня находится симлинк с именем jdk, который сегодня чаще всего указывает на каталог jdk1.8.0_77. К такой конфигурации я пришел, когда потребовалось периодически переключаться между различными версиями JDK, причем переключаться нужно было глобально во всей системе. Каким образом такая конфигурация помогает переключаться между версиями, станет понятно ниже.

13 февраля 2016 г.

USB redirection error в Spicy на openSUSE

Столкнулся в openSUSE с тем, что в gtk-клиенте для spice не работает проброс USB-устройств внутрь гостевой системы. После выбора устройства для проброса появляется окно с просьбой ввести пароль суперпользователя. Вводим пароль, жмём OK и получаем сообщение вроде этого:
Could not redirect Kingston DataTraveler 3.0 [0951:1666] at 2-13: Error setting USB device node ACL: 'Error setting facl: Operation not permitted'
Оказывается, что в пакете spice-gtk вместе с клиентом spicy есть еще такая программка с длинным названием spice-client-glib-usb-acl-helper. При подключении USB-устройства через spicy эта программа, по всей видимости, проверяет и назначает файлу этого устройства дополнительные права через ACL. Проблема в том, что для этого не помешало бы быть root'ом, но не смотря на запрос пароля суперпользователя, spice-client-glib-usb-acl-helper выполняется с правами обычного пользователя из-под которого запущен spicy. Короче, где-то недокостылили. Самым простым решением этой проблемы является установка бита setuid на файл spice-client-glib-usb-acl-helper:
chmod u+s /usr/bin/spice-client-glib-usb-acl-helper
После этого действия USB-устройства начинают успешно пробрасываться.

Для удобства теперь можно также отключить запрос пароля суперпользователя. Делается это через polkit. В файле /usr/share/polkit-1/actions/org.spice-space.lowlevelusbaccess.policy надо отредактировать содержимое элемента defaults следующим образом:



11 октября 2014 г.

Автоматический запуск скриптов при подключении NetworkManager

Я очень долго отказывался от использования NetworkManager (далее NM) и жил с традиционным и понятным ifup. Но теперь, пожалуй, пришло время приобщиться к цивилизации. Тем более, что NM стал уже не такой сурово глючный, как раньше, да и что там говорить, удобно на ноутбуке перещёлкиваться между проводом, WiFi и GSM-модемом.

Единственной преградой на пути к благам цивилизации для меня было то, что мне приходится использовать программу VTun для создания туннеля между домом и работой, через который я также хожу в глобальную сеть, а NM не поддерживает VTun из коробки. Конечно, всегда можно наваять пару скриптов, которые будут периодически смотреть поднятые интерфейсы, пинговать различные ip-адреса и заниматься прочими делами, чтобы понять в каком состоянии находится сеть. Но, как оказалось, можно решить эту задачу и более красивым способом с помощью NetworkManager Dispatcher Service. В systemd он обычно имеет имя NetworkManager-dispatcher.service.

NetworkManager Dispatcher Service это сервис, который при изменении состояния NM, дёргает скрипты из каталога /etc/NetworkManager/dispatcher.d и передает в них в качестве параметров командной строки имя сетевого интерфейса, у которого изменилось состояние, и новое значение этого самого состояния - up или down (vpn-up и vpn-down для VPN-соединений). 

2 октября 2013 г.

Небезопасно посылаем e-mail из bash'a используя сторонний smtp

Как известно, все настоящие админы лентяи, в хорошем смысле этого слова. По этой причине они стараются автоматизировать всё что можно и что нельзя. Одним из главных инструментов тотальной админоавтоматизации является ужасно прекрасный (или прекрасно ужасный) bash. Огромная куча поэтично сложенных bash-скриптов постоянно трудится без обеда, что бы админ мог изучить что-то новое или просто почитать Хабр :) Но бывает так, что случается беда и столкнувшийся с ней скрипт обязан призвать админа для спасения организации. Призывом админа проще, конечно же, заниматься посредством e-mail. Только не всегда есть желание ставить и настраивать какой-нибудь postfix на каждой машине, которая должна оповещать админа о проблемах. Иногда просто хочется одной командой послать письмо, использовав уже настроенный smtp организации. Сделать это можно при помощи программки msmtp. Я применяю этот подход только для использования smtp, находящегося внутри локальной сети организации, т.к. он не очень правильный с точки зрения безопасности, но в качестве примера покажу, как можно отправлять письма используя гугловский smtp.

Пример:
#!/bin/bash

printf "Subject:%b\nFrom:%b\nTo:%b\n%b\n" \
       "From good admin" "someuser@gmail.com" "ded@moroz.ru" \
       "Hello Ded Moroz! I worked hard all year, and so I want to get a red bike for the New Year!"|\
msmtp -t --host=smtp.gmail.com \
      --port=587 \
      --user=someuser \
      --passwordeval="echo some_incredible_password" \
      --from=someuser@gmail.com \
      --tls=on \
      --tls-certcheck=off \
      --auth=on 

Наверное, тут практически всё ясно и без слов, но немного поясню. Команда printf формирует само письмо, состоящее из заголовков Subject, From, To и тела письма, после чего вывод перенаправляется в команду msmtp, которая и отправляет письмо.

Параметры msmtp:
    -t - заставляет программу msmtp брать адреса назначения из заголовков To, Cc и Bcc
    --host - smtp-сервер, который надо использовать для отправки
    --port - порт smtp-сервера
    --user - пользователь
    --passwordeval - команда, которая выводит пароль на стандартный вывод
    --from - отправитель письма
    --tls - включает/выключает TLS/SSL шифрование
    --tls-certcheck - включает/выключает проверку сертификата
    --auth - включает/выключает аутентификацию

Заголовки Subject, From и To можно и не создавать, просто в таком случае письмо будет без темы и поля To, а в качестве From будет установлено значение параметра --from. Но так делать некрасиво :)

Параметр -t тоже можно не использовать, а вместо него в качестве последних параметров через пробел указать адреса, на которые нужно отправить письмо.

Если не указать параметр  --passwordeval, то при запуске команды нужно будет ввести пароль руками.

Исходя из вышесказанного, можно переделать процедуру отправки письма как-нибудь так:
#!/bin/bash

printf "%b\n" \
       "Hello Ded Moroz! I worked hard all year, and so I want to get a red bike for the New Year!"|\
msmtp --host=smtp.gmail.com \
      --port=587 \
      --user=someuser  \
      --from=someuser@gmail.com \
      --tls=on \
      --tls-certcheck=off \
      --auth=on \
      ded@moroz.ru \
      santa@klaus.com

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

25 марта 2011 г.

Красивое использование косвенной адресации в bash-скриптах

Косвенная адресация это когда, грубо говоря, одна переменная ссылается на какое-либо значение через другую переменную. Если говорить точнее и применительно к bash'у, то это когда одна переменная хранит имя другой переменной, которая в свою очередь содержит, например, какое-либо значение. С помощью косвенной адресации можно, используя первую переменную, сразу получить доступ к значению, которое содержит вторая переменная. Как это работает вроде бы ясно, но, возможно, не сразу понятна нужность всего этого.

Итак, допустим у нас есть переменная X, которая содержит строку "значение". Так же есть переменная Y, которая в качестве значения содержит имя переменной X. Красивость заключается в том, что с помощью прямой и косвенной адресации, используя переменную Y, можно получить соответственно имя и значение переменной X.

Простой пример:
X="значение"
Y=X
echo "$Y: ${!Y}"
В этом примере с помощью прямой адресации $Y мы получаем доступ к имени переменной X, а с помощью косвенной ${!Y} - к её значению. В старых версиях bash косвенная адресация могла использоваться только так eval Z=\$$Y, а начиная со 2 версии она стала выглядеть проще, хотя старый вариант так же может использоваться.

Теперь приведу более жизненный пример. У меня есть скрипт, который настраивает iptables. Косвенная адресация в нем используется для того, чтобы сделать проще изменение настроек скрипта и создать красивый вывод. Приведу пример поясняющий основную суть.
#!/bin/bash

# список сервисов и их портов
SSH=22
HTTP=80
HTTPS=443
SAMBA="137 138 139 445"

# локальные сервисы на которые разрешен доступ снаружи
INPUT_PORTS_ACCEPT="SSH SAMBA HTTP HTTPS"

echo "Удаленный доступ к сервисам хоста:"
# открываем доступ на разрешенные сервисы
for SERVICE_NAME in $INPUT_PORTS_ACCEPT
do
    # для каждого порта сервиса добавляем разрешающие правила в iptables
    PORTS=${!SERVICE_NAME} # устаревший вариант: eval PORTS=\$$SERVICE_NAME
    for PORT in $PORTS
    do
        iptables -t filter -A INPUT -i eth0 -p tcp --dport $PORT -j ACCEPT
        iptables -t filter -A INPUT -i eth0 -p udp --dport $PORT -j ACCEPT
    done

    # выводим имя и порты сервиса
    echo "$SERVICE_NAME: $PORTS --accept"
done
Вывод скрипта:

Удаленный доступ к сервисам хоста:
SSH: 22 --accept
SAMBA: 137 138 139 445 --accept
HTTP: 80 --accept
HTTPS: 443 --accept

Таким образом, для настройки скрипта в переменной INPUT_PORTS_ACCEPT нужно указывать не номера портов, а просто имена сервисов, и в выводе наглядно показано на какие локальные сервисы открыт доступ и какие порты им соответствуют. Красиво :)

7 декабря 2010 г.

Файлы внутри скриптов или deploy на bash'е

Одним из интересных свойств bash-скриптов является то, что в них можно запихивать файлы, которые затем сам скрипт будет из себя извлекать при запуске. Таким образом, например, устроены скрипты установки JRE и JDK для Linux. Используя это свойство, можно довольно легко создавать скрипты для автоматизированного развертывания каких-либо систем, библиотек и т.п.. Приведу примеры извлечения текстовых и бинарных данных из bash-скриптов.

30 ноября 2010 г.

Диалог с bash'ем: использование kdesu и kdialog в скриптах

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

В KDE можно легко создавать диалоговые окна в bash-скриптах, используя программу Kdialog. Причем окна могут быть самые разнообразные от обычных yes-no-cancel, до диалогов открытия/сохранения файла и отображения полосы прогресса. Использование продемонстрирую на своем реальном примере.

22 сентября 2010 г.

Отключение сохранения сессий на freenx-server

Иногда freenx-server любит "терять" сессии, а потом не может их восстановить. Для того, чтобы не загонять в тупик простых пользователей непонятными вопросами от nx-клиента, можно просто запретить сохранение сессий в настройках freenx-server.

В файле настроек сервера node.conf (у меня он лежит в каталоге /etc/nxserver) можно явно установить пустым значение переменной ENABLE_PERSISTENT_SESSION:

ENABLE_PERSISTENT_SESSION=""

Или, если необходимо отключить возможность сохранения сессий определенным пользователям, можно сделать так:

ENABLE_PERSISTENT_SESSION="all"
DISABLE_PERSISTENT_SESSION="user1,user2"

В этом случае все пользователи, кроме user1 и user2 смогут сохранять сессии.

А можно и наоборот включить сохранение сессий только определенным пользователям:

ENABLE_PERSISTENT_SESSION="user1,user2"


Не забудьте перезапустить freenx-server:

# service freenx-server restart 

или

# nxserver --restart


При отключённой возможности сохранения сессии, во время выхода из nx-клиента пользователю не будет предложено разъединиться с сохранением сеанса (disconnect), а просто будет задан вопрос для подтверждения выхода.

16 июля 2010 г.

Переименование сетевых интерфейсов в Linux (настройка UDEV)

Вб современных популярных дистрибутивах Linux имена сетевым интерфейсам присваиваются системой UDEV во время загрузки.

Для переименования интерфейса необходимо подправить файл /etc/udev/rules.d/70-persistent-net.rules

Например, файл 70-persistent-net.rules содержит такие строки:

# PCI device 0x1022:0x2000 (pcnet32)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:f3:3e:b4", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

По умолчанию привязка имени осуществляется по MAC-адресу сетевой карты.

Меняем параметр NAME="eth0" на NAME="internet":

# PCI device 0x1022:0x2000 (pcnet32)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="08:00:27:f3:3e:b4", ATTR{type}=="1", KERNEL=="eth*", NAME="internet"

Выполняем из под root'а следующие команды (или перезагружаемся):

Выключить интерфейс:
# ifconfig eth0 down 
Перечитать правила udev:
# udevadm control --reload-rules
Выгрузить драйвер сетевой карты:
# modprobe -r atl1
Загрузить драйвер сетевой карты:
# modprobe atl1
Поднять интерфейс с новым именем:
# ifconfig internet up

Узнать какой драйвер используется для вашей сетевой карты можно командой lspci -k

Всё.

(!) Переименование сетевого интерфейса может понадобиться, если у вас поменялась сетевая карта или вообще жесткий диск с работоспособной системой переставлен в другую машину, в которой, естественно, опять же другая сетевая карта. Т.к. привязка осуществляется по MAC-адресам, то UDEV добавит правило для новой сетевой карты, но если прошлая сетевая карта у вас была под именем eth0, то новой он присвоит имя eth1 и все ваши настройки работать разумеется не будут.

28 апреля 2010 г.

Конвертирование физических машин в виртуальные с помощью VMware Converter

На работе у меня был случай, когда появилась необходимость перевести человека, который весьма много времени проработал под Windows XP, на Linux. Windows XP стояла на машине на удивление очень долго без переустановок, была настроена и напичкана различными программами, и человек не хотел с ней расставаться окончательно, ему необходимо было иногда одновременно работать в двух системах. Естественно, единственный нормальный выход тут один - виртуализация. Установка винды и всех необходимых программ с нуля в виртуальную машину, а так же её настройка вылились бы в очень длительную и неприятную процедуру. Но оказалось, что есть выход гораздо проще - можно виртуализировать уже установленную систему. Для этого я воспользовался программой VMware Converter. Опишу, как это можно сделать.