суббота, 14 мая 2011 г.

Переброс портов и интерфейса графических программ с помощью SSH

У вас есть учетная запись user1 на сервере example.net с IP-адресом 8.9.10.11, на котором запущен демон SSH. Вы находитесь в локальной сети, имеющей подключение к Интернету. Ваш IP-адрес в локальной сети 192.168.0.2. Все адреса взяты для примера, везде подставляйте свои значения.

Примеры задач, которые вам может понадобиться выполнить с использованием главного преимущества SSH - высокой степени защиты соединения:
  • (1) На вашем сервере установлен MySQL и соединения для пользователя root разрешены только с локальной машины (т.е. с самого сервера), вы же хотите подключиться к нему со своей домашней машины (к примеру, из MySQL Administrator или MySQL Workbench).
  • (2) В вашей локальной сети есть веб-сервис, недоступный извне, а вы хотите скачать с него файл прямо на сервер.
  • (3) Вы хотите запускать на сервере GUI-приложения (программы с графическим интерфейсом) таким образом, чтобы они отображались на вашем компьютере как обычные окна.
Сначала рассмотрим первые 2 случая, они предполагают переброс TCP-портов. Чтобы упростить понимание, немного поговорим о том, как происходят соединения TCP с точки зрения обывателя:
  1. Программа-сервер занимает определенный порт и ждет пока кто-нибудь подключится. Порт на этой машине считается занятым и другие программы уже не могут его использовать. В качестве аналогии, представьте себе розетку на стене, в которую, тем не менее, можно подключать очень много вилок.
  2. Программа-клиент соединяется с программой-сервером путем подключения к определенному адресу и порту в сети. Программа-клиент как раз втыкает свою вилку в розетку программы-сервера.
В данном случае переброс портов работает как "удлинитель", позволяя переносить розетку со стены, скажем, в другую комнату.

Теперь перейдем к практике. На практике нужно знать, что создавать "розетки" с номером порта 1024 и меньше (в том числе с помощью "удлинителя") могут только привилегированные пользователи. На "вилки" это ограничение не распространяется. И второй нюанс: "вилка удлинителя" включается в "розетку" программы-сервера только в тот момент, когда в "розетку удлинителя" включается "вилка" программы-клиента (это несколько отличается от работы обычного удлинителя). Короче говоря, вся цепочка соединений полностью создается только при появлении клиента. На самом деле, для вас это не будет иметь особой разницы в большинстве случаев, поэтому не забивайте голову.

Разберем задачу (1) в наших терминах:
  • На сервере example.net есть "розетка" на стандартном для MySQL порту 3306, причем доступна она только с самого сервера, т.е. висит на его адресе 127.0.0.1.
  • Нужно провести "удлинитель" к нам на домашний компьютер, опять же, сделав "розетку удлинителя" доступной только с локальной машины.
Для этого мы подключаемся к серверу по SSH используя следующую команду:
$ ssh user1@example.net -L localhost:3307:127.0.0.1:3306
Опция -L означает, что мы создаем локальную "розетку" с помощью "удлинителя" (L = local). Таких параметров вы можете указать несколько, таким образом проложив сразу несколько "удлинителей". Разбираем параметры:
  • localhost - IP-адрес или имя машины, где будет создана "розетка удлинителя". Здесь мы ограничиваем "розетку" подключениями только с локального компьютера. Для доступа к "розетке" со всей локальной сети можно указать здесь 192.168.0.2 (адрес для примера, см. начало статьи). Этот параметр можно не указывать (опустив и двоеточие после него, сразу начав с порта), по-умолчанию и так используется localhost. Для использования других значений придется править настройки SSH на сервере (параметр GatewayPorts, подробности в документации на sshd).
  • 3307 - номер порта, по которому будет создана "розетка удлинителя". Можно использовать здесь и стандартный порт MySQL 3306, но это вызовет проблемы, если у вас запущен и локальный MySQL.
  • 127.0.0.1 - IP-адрес или имя машины, куда будет подключаться "вилка удлинителя". Чтобы для сервера подключения казались локальными, используем 127.0.0.1, или localhost. Опять же, ничто не мешает указать произвольный адрес в сети интернет, в таком случае соединение будет установлено с указанным адресом. Может быть полезно, если нужно исключить прослушку в локальной сети, хотя есть более адекватные способы это сделать.
  • 3306 - номер порта, к которому будет подключена "вилка удлиннителя", здесь указан стандартный порт MySQL.
Пока будет установлено SSH-соединение, мы можем в локальных программах указывать сервер - localhost, порт - 3307 и таким образом соединяться с MySQL на сервере. "Розетка" на локальном компьютере, соединение пойдет через "удлинитель" и попадет в "розетку" на сервере.

Задача (2) является обратной:
  • На машине в локальной сети (для примера возьмем адрес 192.168.0.100) есть "розетка" с номером порта 80 (стандартный порт HTTP), доступная только для данной локальной сети.
  • Нужно провести "удлинитель" так, чтобы "розетка" оказалась на нашем сервере, а соединение происходило с "розеткой" на машине в локальной сети.
Чтобы ее решить, нужно подключиться по SSH со следующими параметрами:
$ ssh user1@example.net -R localhost:8080:192.168.0.100:80
Здесь опция -R означает, что мы создаем "розетку удлиннителя" на удаленном сервере (R = remote). Опять же, ничего не мешает указывать несколько таких опций и комбинировать их с опциями -L. Параметры:
  • localhost - IP или имя удаленной машины, на которой будет создана "розетка удлинителя". Можно не указывать (опустив двоеточие, начав сразу с порта), по-умолчанию и так localhost.
  • 8080 - номер порта для "розетки удлинителя". Повторюсь, порты до 1024 включительно могут использовать только привилегированные пользователи.
  • 192.168.0.100 - IP или имя машины на локальной стороне, в "розетку" которой мы подключим наш "удлинитель"
  • 80 - порт машины на локальной стороне, куда будет подключена "вилка удлинителя"
Пока будет установлено такое соединение, из консоли сервера мы сможем скачать какой-нибудь файл с веб-сервиса в локальной сети:
$ wget http://localhost:8080/some/path/file.zip
В самом простом случае всё заработает и так, в более сложном - вам придется на сервере дописать соответствие адреса веб-сервиса вашему локальному в файл /etc/hosts, но это оставим за пределами данной статьи.

Запоминать команды для переброса портов довольно просто:
  • Параметр (-L или -R) - это место создания "розетки удлинителя":
    L = local = "розетка" на стороне клиента
    R = remote = "розетка" на стороне сервера
  • Первая часть аргумента задает адрес и порт "розетки удлинителя", т.е. той "розетки", которую вы сами создаете с помощью SSH
  • Вторая часть аргумента - адрес и порт "розетки", куда будет подключена "вилка удлинителя", т.е. уже существующей "розетки"
Задача (3) решается уже не перебросом портов, а перебросом соединений с X-сервером. Неприятное предварительное условие - в настройках SSH-сервера должна быть включена опция X11Forwarding (должна иметь значение yes, по-умолчанию no). Далее вы просто соединяетесь с сервером следующей командой (буква X заглавная, это важно):
$ ssh user1@example.net -X
После этого, запуская графические приложения из данной консоли, вы увидите их на своем экране как обычные окна, но работать они будут на удаленном сервере.

На этом всё. Безопасных вам соединений.

понедельник, 14 февраля 2011 г.

Создаем загрузочную USB-флешку с Windows 7 из Debian/Ubuntu

У нас есть iso-образ Windows 7, USB-флешка и работающий Debian GNU/Linux (или Ubuntu). Нужно установить Windows на компьютер без DVD-привода. Как создать iso-образ с диска - оставим за пределами этой статьи. Приступим.

1. Форматируем флешку в NTFS. Для этого можно воспользоваться Gparted и не копаться в консоли. Плюс, нужно не забыть установить для раздела флаг boot (правой кнопкой на разделе, пункт "Управление флагами", включаем галочку "boot").

2. Создаем папку, монтируем в нее образ Windows 7 и копируем его содержимое на флешку, отмонтируем образ:
# mkdir -p /mnt/iso
# mount -o loop /path/to/image/windows7.iso /mnt/iso
# cp -r /mnt/iso/* /media/usb-flash/
# umount /mnt/iso
Пути указаны для примера и их нужно поменять на свои:
  • /mnt/iso - папка, куда мы смонтируем образ (если она уже создана, пропустите первую команду)
  • /path/to/image/windows7.iso - путь к образу
  • /media/usb-flash - папка, куда смонтирована флешка

3. Устанавливаем ms-sys. Программа нужна для записи правильного загрузочного сектора на флешку. Судя по списку изменений, нам нужна версия не ниже 2.1.4. Возможно она есть в пакетах вашего дистрибутива, но в репозиториях Debian ее не оказалось, поэтому качаем исходники, распаковываем, переходим в распакованную папку и там выполняем:
$ make
Чтобы не захламлять систему, воспользуемся программой checkinstall, она соберет программу в пакет и установит его. Для этого всё в той же папке выполняем:
# checkinstall
Вам зададут несколько вопросов с очевидными ответами и сделают всю грязную работу за нас.
Но можно воспользоваться и дедовским способом, установить программу по старинке:
# make install

4. Добавляем загрузочную запись на флешку:
# ms-sys -7 /dev/sdb
Здесь нужно заменить /dev/sdb на путь к устройству вашей флешки. Будьте очень осторожны, не перепутайте с жестким диском.

На этом всё, флешка готова к загрузке. Вставляйте ее в компьютер и выбирайте в BIOS загрузку с USB.

Источником вдохновения послужила страница на serverfault.com

воскресенье, 21 ноября 2010 г.

Настраиваем IMAP-сервер Dovecot и fetchmail на сбор почты и доставку через deliver (без полноценного MDA)

Задача: установить на машине в локальной сети IMAP-сервер, который будет забирать почту с внешнего IMAP-сервера, удаляя письма оттуда. Никакие антиспам-фильтры или антивирусы нам не нужны, за нас это сделает провайдер почтового сервиса. В качестве пользователей должен использоваться отдельный список, пользователи системы нам не подходят. Желательно всё это с минимальными телодвижениями и с минимальным количеством задействованного софта, т.к. по-моему чем больше в системе компонентов, тем больше у нее шансов сломаться.

Выбранный софт:
  • Dovecot - простой в настройке, быстрый IMAP-сервер (есть вариант и POP-сервера)
  • Fetchmail - программа для сбора почты и пересылки ее локальному агенту доставки сообщений
  • Imapsync - программа для синхронизации и переноса IMAP-ящиков с одного сервера на другой, нужна один раз. Авторы теперь хотят за нее денег, но она есть в любом нормальном Linux-дистрибутиве, так что покупать ее не придется
Обычно в статьях к этому списку добавляют MDA, который и будет доставлять почту локальным пользователям, но мы воспользуемся программой deliver, идущей в комплекте с Dovecot, тем самым исключив дополнительный компонент.

Для примеров будем использовать следующие параметры:
  • imap.external.com - внешний сервер, с которого нужно забирать почту
  • imap.localserv.net - сервер в локальной сети, на котором будут работать Dovecot и fetchmail
  • joe - имя пользователя, для которого мы будем настраивать ящик

1. Настраиваем Dovecot.
Для начала создадим нового пользователя от имени которого будут работать сессии пользователей при обращении к ящикам.
# adduser --system --group vmail
Утилита любезно создаст нам домашнюю папку, в которой мы и будем хранить почту всех пользователей (/home/vmail)

Далее создаем нашу базу пользователей в файле /etc/dovecot/passwd Файл имеет формат
username[@localserv.net]:{SCHEMA}password
Домен указывать не обязательно. Схемы аутентификации - это формат хранения пароля. Для тестов можно использовать PLAIN - пароль нужно вписывать открытым текстом. Для полноценного использования подойдет схема SSHA. Для получения хэша пароля в этом формате есть утилита dovecotpw:
# dovecotpw -s ssha
Она попросит 2 раза ввести пароль, а в ответ выдаст хэш вместе со схемой, это и нужно вставить в файл. Приведу простой пример файла:
test:{PLAIN}pass
joe:{SSHA}DNODS3ZrOq1bu2MasNk79LxHhlU9iI03
Далее нужно сделать этот файл доступным на чтение только пользователю dovecot, от имени которого запускается демон:
# chown dovecot:dovecot /etc/dovecot/passwd
# chmod go-rwx /etc/dovecot/passwd
Теперь пишем основной конфиг /etc/dovecot/dovecot.conf

Буду приводить только изменения относительно конфига по-умолчанию в Debian.

Включаем поддержку IMAP с шифрованием. Если нужно без шифрования, то используем imap. Можно указать оба способа через пробел.
protocols = imaps
Пишем журнал в отдельные файлы. Если нужно использовать syslog, необходимо убрать пути к файлам (задать пустые параметры).
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot-info.log
Задаем формат хранения почты maildir:
mail_location = maildir:~/Maildir
Далее нам нужно узнать uid нашего пользователя vmail. Для этого запускаем команду:
# id -u vmail
Она и покажет uid указанного пользователя, в моем случае он равен 113. Теперь в конфиге задаем минимальный и максимальный uid, под которыми могут работать пользовательские сессии:
first_valid_uid = 113
last_valid_uid = 113
Далее нужно добавить секцию с настройками протокола LDA (Local Delivery Agent), т.е. это настройки программы deliver из состава Dovecot. Что указывать в качестве параметра postmaster - понятия не имею, указал первого попавшегося локального пользователя. Думаю, этот ящик в нашей конфигурации использоваться не будет, т.к. на него должны отправляться "отвергнутые" письма, которых у нас не будет за неимением анти-спам и анти-вирусных фильтров. В качестве hostname нужно указать доменное имя вашего сервера. auth_socket_path - путь к сокету аутентификации, через него deliver будет подключаться к основному процессу Dovecot для получения привилегий. Здесь же указываем отдельные файлы для журналов deliver. По аналогии с основными журналами, можно воспользоваться syslog, задав параметры пустыми значениями. Вот как будет выглядеть вся секция:
protocol lda {
  postmaster_address = user1@example.com
  hostname = imap.localserv.net
  auth_socket_path = /var/run/dovecot/auth-master
  log_path = /var/log/fetchmail/dovecot-deliver.log
  info_log_path = /var/log/fetchmail/dovecot-deliver-info.log
}
Для более детального журналирования процесса аутентификации можно на этапе отладки включить следующую опцию (после тестирования ее желательно убрать):
auth_verbose = yes
Все дальнейшие изменения будут производиться в секции auth default {...}.

Первым делом выключаем аутентификацию через PAM и базу пользователей по-умолчанию, закомментировав всё в подсекциях passdb pam {...} и userdb passwd {...}.

Далее подключаем базу паролей из нашего файла:
passdb passwd-file {
  args = /etc/dovecot/passwd
}
Для сессий работы с почтой указываем системного пользователя и папку под почту:
userdb static {
  args = uid=vmail gid=vmail home=/home/vmail/%u
}
Комментируем строчку, которая запускает один из процессов от root'а. Судя по описанию, нам это не нужно.
#user = root
И наконец, создаем сокет, чтобы deliver смог подключиться к основному процессу для получения привилегий:
socket listen {
  master {
    path = /var/run/dovecot/auth-master
    mode = 0600
    user = vmail
    group = vmail
  }
}
Сохраняем конфиг. Перезагружаем Dovecot:
# /etc/init.d/dovecot restart
2. Настраиваем Fetchmail
Нормальную документацию по написанию конфигов для этой программы я так и не нашел, всё взято из примеров на форумах, в блогах и списках рассылки. Ее можно запускать как общесистемного демона или в сессии пользователя, нас конечно же интересует первый вариант.

Конфиг лежит в файле /etc/fetchmailrc Здесь я сразу приведу пример всего конфига. Настроен демон будет на получение новых писем каждые 2 минуты (на самом деле, это очень часто, лучше поставить 5-10 минут). Журнал будет записываться в отдельный файл (хотя, опять же, можно использовать syslog). C postmaster та же история, что и для deliver, - в случае проблем с доставкой письмо просто не удаляется с внешнего сервера и, по видимому, в ящике postmaster нет необходиимости, но всё же укажем нашего системного пользователя.

Настройки аккаунтов представляют собой этакие предложения, для удобства записал их в несколько строчек. Разберем на примере:
  • poll imap.external.com protocol imap
    здесь указываем адрес внешнего сервера и протокол по которому нужно проверять новые письма

  • user "joe" there with password "joe-password"
    указываем пользователя на внешнем сервере и его пароль там

  • options ssl
    указываем опции через пробел, ssl говорит о том, что нужно использовать шифрованный канал (в соответствии с этой опцией и указанным протоколом, fetchmail автоматически выбирает порт для соединения); для тестирования будет полезна опция keep, позволяющая оставлять письма на сервере
     
  • sslcertpath /home/vmail/.certs
    отдельная история, опишу ее после конфига

  • mda "/usr/lib/dovecot/deliver -d joe";
    здесь мы указываем программу доставки сообщений, причем для deliver нужно указать через параметр -d имя пользователя, в ящик которого придут письма с этого внешнего аккаунта
А теперь полностью пример конфига для двух пользователей:
set daemon 120       # Poll every 2 minutes
set no syslog        # Alternate log
set logfile /var/log/fetchmail/fetchmail.log
set postmaster user1   # In case of errors mails are delivered here

set no bouncemail    # avoid loss on 4xx errors
                     # on the other hand, 5xx errors get more dangerous

# Defaults
defaults:
timeout 60
batchlimit 100

# Accounts to poll
## test@external.com ##
poll imap.external.com protocol imap
user "test" there with password "secret-external-server-password"
options ssl
sslcertpath /home/vmail/.certs
mda "/usr/lib/dovecot/deliver -d test";

## joe@external.com ##
poll imap.external.com protocol imap
user "joe" there with password "joe-password"
options ssl
sslcertpath /home/vmail/.certs
mda "/usr/lib/dovecot/deliver -d joe";
А теперь одна особенность внешнего сервера, с которым мне пришлось работать. Они используют сертификаты, подписанные своим центром сертификации, поэтому пришлось скачать их корневой сертификат, положить его в папку /home/vmail/.certs и сменить ему расширение на ".pem". После этого нужно обновить индексы в папке с сертификатами, для этого запускаем:
# c_rehash /home/vmail/.certs
Сертификаты готовы к использованию.

Если мы попробуем запустить демона fetchmail от одноименного пользователя (как настроено по-умолчанию в Debian), у нас ничего не выйдет - deliver будет ругаться на отсутствие прав и невозможность сохранить письмо.

Скорее всего, в ближайшем будущем найду решение без этого шага, но пока работает только так. Нужно сменить пользователя от имени которого запускается fetchmail. Мы будем запускать ее от имени vmail, чтобы порожденный ею процесс deliver смог сохранить письма в папки виртуальных пользователей. Для этого в файле /etc/default/fetchmail вносим следующие изменения (заодно включим запуск fetchmail в качестве демона при старте системы):
START_DAEMON=yes
USER=vmail
Сохраняем файл. И пока не запускаем fetchmail, т.к. есть еще один шаг, если вы настраиваете систему для не новых ящиков и в папках на внешнем сервере уже лежат письма.

3. Миграция IMAP-ящиков с помощью imapsync
Ваши пользователи наверняка захотят, чтобы все их пометки, папки и другие данные с IMAP-ящиков внешнего сервера полностью перенеслись на локальный сервер.

Чтобы не светить пароли в списке процессов, создаем для каждого пользователя по 2 файла, содержащие пароли от внешнего и локального ящиков. Сначала подготовим папку для них:
# mkdir /home/vmail/.pass
# cd /home/vmail/.pass
Эти процедуры нужно повторить для каждого перемещаемого пользователя:
# touch joe.remote joe.local
# chown root joe.remote joe.local
# chmod 0600 joe.remote joe.local
И затем вписать в созданные файлы соответствующие пароли с помощью вашего любимого текстового редактора.

Далее начинается самое веселье. Нужно методом поиска в интернете, чтения невнятного мануала к imapsync и других магических манипуляций подобрать опции для каждого из IMAP-серверов.  Опишу опции, которые пришлось использовать мне. Большинство опций имеют на конце цифру 1 - сервер, с которого будут переноситься письма, или 2 - сервер, на который они будут переноситься. Итак, опции (те, что имеют вариант для каждого из серверов приведены с 1 на конце):
  • --host1 imap.external.com
    имя сервера

  • --port1 993
    порт для подключения

  • --user1 "joe"
    имя пользователя для аутентификации

  • --passfile1 /home/vmail/.pass/joe.remote
    путь к файлу с паролем

  • --ssl1
    использовать ли шифроввание при подключении к серверу

  • --noauthmd5
    общая опция (одна и работает сразу для обоих серверов), отключает использование аутентификации по MD5; нужна, если программа при запуске выдаст ошибку о невозможности использования такого метода аутентификации

  • --sep1 "."
    --prefix1 ""
    префикс и разделитель в именах папок, они нужны если imapsync не может определить их автоматически и явно просит указать одну из них, или возникают проблемы с недопустимыми именами при создании папок в процессе синхронизации; как их определять - расскажу ниже

  • --delete
    --expunge1
    после первой удачной синхронизации нужно добавить эти опции и запустить imapsync еще раз для удаления писем с внешнего сервера; имейте ввиду, что --expunge2 указывать не нужно
Итак, в самом простом случае для каждого аккаунта нужно запустить imapsync 2 раза. Второй раз - только убедившись, что всё перенеслось как следует, для очистки ящика на внешнем сервере. Переносим почту:
# imapsync --ssl1 --ssl2 --noauthmd5 --host1 imap.external.com --port1 993 --host2 imap.localserv.net --port2 993 --user1 "joe" --passfile1 /home/vmail/.pass/joe.remote --user2 joe --passfile2 /home/vmail/.pass/joe.local
Второй раз запускаем уже с опциями удаления:
# imapsync --ssl1 --ssl2 --noauthmd5 --host1 imap.external.com --port1 993 --host2 imap.localserv.net --port2 993 --user1 "joe" --passfile1 /home/vmail/.pass/joe.remote --user2 joe --passfile2 /home/vmail/.pass/joe.local --delete --expunge1
Теперь самое веселое, если imapsync не может определить префиксы и разделители пути на серверах, нужно соединиться с сервером (мы будем использоовать защищенное соединение), вручную залогиниться и запросить перечисление папок. Тогда мы увидим как он представляет папки и сможем это объяснить imapsync.

Соединяемся с сервером:
$ openssl s_client -connect imap.external.com:993
если видим в конце ответа
* OK IMAP4 ready
значит всё в порядке, можно разговаривать с сервером. Проходим аутентификацию:
1 login joe joe-password
видим
1 OK LOGIN Ok.
далее набираем по очереди 2 команды и анализируем их результат:
2 list "*" ""
3 list "" "*"
результат будет иметь вид, похожий на следующее:
* LIST (\HasNoChildren) "." "INBOX.Archive"
* LIST (\HasNoChildren) "." "INBOX.Sent"
* LIST (\HasNoChildren) "." "INBOX.Draft"
Это означает, что префикса у пути нет, а разделитель папок - точка. В результате параметры будут
--prefix1 "" --sep1 "."
То же самое нужно повторить и для локального сервера.

4. Контрольный запуск и исправление ошибок.
После того, как все письма перенесены на локальный сервер, можно запускать демона fetchmail и тестировать его работу:
# /etc/init.d/fetchmail start
Т.к. эта статья пишется "по горячим следам" после настройки сервера и переноса ящиков, скорее всего я забыл про какие-нибудь права на папки и файлы (например, файлы журнала). Внимательно читаем сообщения об ошибках при старте демонов или в логах, думаем головой, исправляем их и не забываем упомянуть об этом в комментариях к статье.