Защита пакетного репозитория с помощью Reprepro в Ubuntu 14.04

Все знают, что делать, если тебе нужна программа. Чаще всего достаточно просто ввести apt-get install postfix и все, необходимый Postfix будет волшебным образом установлен.

Хотя это не совсем волшебство. Менеджер пакетов apt ищет, загружает и устанавливает пакет. Это очень удобно, но что если apt-get не может найти нужную вам программу в своем стандартном репозитории? В таком случае вы можете добавить в apt пользовательские репозитории.

Данный мануал поможет вам настроить ваш собственный безопасный репозиторий и открыть другим пользователям доступ к нему на сервере Ubuntu 14.04 LTS. Также вы узнаете, как протестировать свой репозиторий с другого сервера.

Читайте также: Управление пакетами в Ubuntu и Debian при помощи Apt-Get и Apt-Cache

Требования

Для работы вам понадобится два сервера Ubuntu 14.04 LTS, настроенные по этому мануалу.

В мануале вы научитесь:

  • Создавать и публиковать ключ для подписи репозитория.
  • Настраивать репозиторий при помощи менеджера репозиториев Reprepro.
  • Открывать доступ к репозиторию с помощью веб-сервера Nginx.
  • Добавлять репозиторий на другой сервер.

1: Подготовка и публикация ключа

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

Сейчас нужно создать зашифрованный открытый ключ и подписывающий подключ. Это делается в несколько шагов:

  • Создание главного ключа
  • Создание подключа для подписи пакетов
  • Разделение главного ключа и подключа

Создание главного ключа

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

Для начала установите rng-tools.

apt-get install rng-tools

Для генерации ключей GPG нужны случайные данные – энтропия. Обычно энтропия генерируется ядром Linux и сохраняется в пуле. Однако на облачных серверах у ядра могут возникнуть проблемы с генерацией уровня энтропии, необходимого для GPG. Чтобы помочь ядру, нужна программа rngd (она есть в пакете rng-tools). Эта программа запросит энтропию у хост-сервера. После rngd добавит данные в пул энтропии для использования другими приложениями, такими как GPG.

Если вы получили такое сообщение:

Trying to create /dev/hwrng device inode...
Starting Hardware RNG entropy gatherer daemon: (failed).
invoke-rc.d: initscript rng-tools, action "start" failed.

Запустите демон вручную:

rngd -r /dev/urandom

По умолчанию rngd ищет специальное устройство для извлечения энтропии из /dev/hwrng. Такое устройство есть не на всех виртуальных серверах. Чтобы компенсировать это, мы используем псевдослучайное устройство /dev/urandom , добавив директиву -r.

Читайте также: Использование простого демона энтропии Haveged

Теперь пул энтропии готов, и вы можете сгенерировать мастер-ключ. Для этого введите команду gpg:

gpg --gen-key
gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1

Выберите первый вариант, RSA and RSA (default). Для этого введите 1. Утилита gpg сначала сгенерирует ключ подписи, а затем подключ шифрования (оба используют алгоритм RSA). Для этого мануала ключ шифрования не нужен, но в будущем он вам не помешает, вы сможете использовать его для шифрования.

Нажмите Enter, и вам будет предложено указать размер ключа:

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096

Размер ключа напрямую зависит от необходимого вам уровня надежности. Чем больше бит, тем надежнее ключ. Проект Debian рекомендует использовать для ключа подписи 4096 битов (мы так и сделаем). В целом, размера по умолчанию 2048 будет достаточно, если вы предпочитаете такие ключи. Размер 1024 не очень надежный, его лучше не использовать.

Нажмите Enter, чтобы выбрать срок действия ключа.

Please specify how long the key should be valid.
0 = key does not expire
<n>  = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0

Мастер-ключи обычно не имеют срока годности, но вы можете установить здесь срок, в течение которого вы собираетесь использовать этот ключ. Если вы планируете использовать этот репозиторий только в течение следующих 6 месяцев, вы можете указать 6m. Значение 0 сделает ключ навсегда действительным.

Нажмите Enter, затем y. Вам будет предложено сгенерировать user ID. Эта информация будет использоваться другими и вами для идентификации этого ключа – укажите реальную информацию!

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"
Real name: Mark Lopez
Email address: mark.lopez@example.com
Comment:
You selected this USER-ID:
"Mark Lopez <mark.lopez@example.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

Если информация верна, нажмите o и Enter. Теперь нужно добавить пароль, чтобы доступ к этому ключу был только у вас. Обязательно запомните этот пароль, так как восстановить пароль ключа gpg невозможно (и это хорошо).

You need a Passphrase to protect your secret key.
Enter passphrase: (hidden)
Repeat passphrase: (hidden)

Теперь время для магии (вычислений). Это может занять некоторое время, поэтому наберитесь терпения.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 300 more bytes)
+++++
................+++++
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
..+++++
+++++
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 10E6133F marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
pub   4096R/10E6133F 2014-08-16
Key fingerprint = 1CD3 22ED 54B8 694A 0975  7164 6C1D 28A0 10E6 133F
uid                  Mark Lopez <mark.lopez@example.com>
sub   4096R/7B34E07C 2014-08-16

Главный ключ готов. В выводе говорится, что вы создали мастер-ключ для подписи (0E6133F в строке pub). У вашего ключа должны быть другие ID. Запишите ID ключа, он понадобится для дальнейшей работы.

Создание подключа для подписи пакетов

Теперь нужно создать второй ключ подписи, чтобы не было необходимости использовать главный ключ на этом сервере. По сути, главный ключ – это как пользователь root, который дает полномочия подключам. Если пользователь доверяет главному ключу, он может доверять и подключу.

В терминале введите:

gpg --edit-key 10E6133F

Укажите в команде ID вашего ключа. Эта команда откроет среду gpg. Здесь можно отредактировать новый ключ и добавить подраздел. Вы увидите следующий вывод:

gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub  4096R/10E6133F  created: 2014-08-16  expires: never       usage: SC
trust: ultimate      validity: ultimate
sub  4096R/7B34E07C  created: 2014-08-16  expires: never       usage: E
[ultimate] (1). Mark Lopez <mark.lopez@example.com>
gpg>

В командную строку введите:

addkey

Нажмите Enter. GPG запросит ваш пароль. Введите пароль вашего ключа.

Key is protected.
You need a passphrase to unlock the secret key for
user: "Mark Lopez <mark.lopez@example.com>"
4096-bit RSA key, ID 10E6133F, created 2014-08-16
gpg: gpg-agent is not available in this session
Enter passphrase: <hidden>

Затем вы увидите такой запрос.

Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
Your selection? 4

Выберите вид ключа. Здесь мы создадим RSA (sign only), подключ для подписи. Чтобы создать такой ключ, введите 4.

RSA и DSA одинаково безопасны.RSA быстрее на клиентах, а DSA – на серверах. RSA в данном случае лучше, потому что каждый подписанный пакет, возможно, будет проверяться сотнями клиентов.

Снова вам предлагается указать размер ключа.

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096

Мы создадим более надежный ключ размером 4096 бит.

Please specify how long the key should be valid.
0 = key does not expire
<n>  = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y

У вас уже есть мастер-ключ, а потому срок действия подключа не так важен. 1 года будет вполне достаточно.

Нажмите Enter и введите у, чтобы ответить на следующие два вопроса. Это сгенерирует новый ключ.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
............+++++
.+++++
pub  4096R/10E6133F  created: 2014-08-16  expires: never       usage: SC
trust: ultimate      validity: ultimate
sub  4096R/7B34E07C  created: 2014-08-16  expires: never       usage: E
sub  4096R/A72DB3EF  created: 2014-08-16  expires: 2015-08-16  usage: S
[ultimate] (1). Mark Lopez <mark.lopez@example.com>
gpg>

Введите save в командную строку:

save

В приведенном выше выводе SC мастер-ключа говорит, что ключ предназначен только для подписи и сертификации. E означает, что ключ может использоваться только для шифрования. Ключ подписи будет отображаться правильно только с S.

Обратите внимание на ID вашего нового ключа подписи (это условный ID A72DB3EF в выводе). ID вашего ключа будет отличаться.

Введите save, чтобы вернуться в терминал и сохранить новый ключ.

save

Разделение главного ключа и подключа

Смысл подключа в том, что благодаря ему на нашем сервере не нужен главный ключ, а это повышает безопасность. Теперь нужно разделить главный ключ и подключ. Для этого нужно экспортировать мастер-ключ и подключ, удалить ключи из хранилища GPG, а затем повторно импортировать только подключ.

Используйте команды —export-secret-key и —export для экспорта всего ключа. Не забудьте указать ID мастер-ключа.

gpg --export-secret-key 10E6133F > private.key
gpg --export 10E6133F >> private.key

По умолчанию —export-secret-key и –export выводят ключ в консоль, но мы перенаправим вывод в новый файл private.key.

Важно! Скопируйте файл private.key в надежное место. Этот файл содержит много конфиденциальных данных.

Создав резервную копию этого файла в безопасном месте, удалите файл:

#back up the private.key file before running this# rm private.key

Теперь экспортируйте открытый ключ и подключ. Укажите ID своих ключей вместо условных ID в команде.

gpg --export 10E6133F > public.key
gpg --export-secret-subkeys A72DB3EF > signing.key

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

gpg --delete-secret-key 10E6133F

Импортируйте на сервер только подключ.

gpg --import public.key signing.key

Убедитесь, что мастер-ключа на сервере нет.

gpg --list-secret-keys
sec#  4096R/10E6133F 2014-08-16
uid                  Mark Lopez <mark.lopez@example.com>
ssb   4096R/7B34E07C 2014-08-16
ssb   4096R/A72DB3EF 2014-08-16

Обратите внимание на символ # после sec. Это значит, что мастер-ключ не установлен. На сервере есть только подключ для подписи.

Удалите ключи:

rm public.key signing.key

Теперь нужно только опубликовать ваш ключ для подписи:

gpg --keyserver keyserver.ubuntu.com --send-key 10E6133F

Эта команда публикует ключ в общедоступном хранилище ключей – в данном случае это сервер ключей Ubuntu. Это позволяет другим загружать ваш ключ и легко проверять ваши пакеты.

2: Настройка репозитория с помощью Reprepro

Теперь давайте перейдем к сути этого мануала: создадим репозиторий apt-get. Apt-get репозитории – не самая простая в управлении штука. К счастью, R.Bernhard создал проект Reprepro, который позволяет создавать, управлять и синхронизировать локальный репозиторий пакетов Debian (также известный как Mirrorer). Reprepro использует лицензию GNU и полностью открытый исходный код.

Установка и настройка Reprepro

Reprepro можно установить из официального репозитория Ubuntu:

apt-get update
apt-get install reprepro

Конфигурация Reprepro зависит от репозитория, то есть настройки будут разными для нескольких репозиториев.

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

mkdir -p /var/repositories/
cd /var/repositories/

Находясь в новом каталоге, создайте каталог конфигураций:

mkdir conf
cd conf/

Теперь создайте два пустых конфига, options и distributions.

touch options distributions

Откройте файл options.

nano options

В этом файле будут опции Reprepro. Reprepro читает этот файл во время загрузки. Здесь нужно указать несколько опций.

ask-passphrase

Директива ask-passphrase запрашивает пароль GPG при подписании. Если не добавить эту опцию, Reprepro прекратит работу, если ключ зашифрован (а это так).

Нажмите Ctrl + x, затем y и Enter, чтобы сохранить изменения и вернутся в консоль.

Теперь откройте файл distributions:

nano distributions

В него нужно добавить такие директивы:

Codename: trusty
Components: main
Architectures: i386 amd64
SignWith: A72DB3EF

Директива Codename напрямую связана с кодовым именем выпущенных дистрибутивов Debian и является обязательной. Это кодовое имя для дистрибутива, который будет загружать пакеты, оно не обязательно должно соответствовать дистрибутиву этого сервера. Например, Ubuntu 14.04 LTS называется trusty, Ubuntu 12.04 LTS называется precise, а Debian 7.6 – wheezy. Этот репозиторий предназначен для Ubuntu 14.04 LTS, поэтому здесь нужно установить trusty.

Поле Components обязательно нужно заполнить. Это простое хранилище, поэтому установите здесь main. Существуют и другие пространства имен, такие как non-free и contrib (обратитесь к apt-get за правильными схемами именования).

Architectures тоже обязательное поле. Здесь перечислены двоичные архитектуры хранилища (через пробел). В этом хранилище будут размещаться пакеты для 32-битных и 64-битных серверов, поэтому здесь установлен i386 amd64. Добавьте или удалите другие архитектуры по мере необходимости.

Чтобы указать, как другие компьютеры могут проверять пакеты, используйте директиву SignWith. Это необязательная директива, но она нужна для подписания. Ключ подписи в этом примере имеет условный ID A72DB3EF, который нужно добавить в директиву. Укажите здесь ID подключа, который вы создали.

Сохраните и закройте файл, нажав Ctrl + x, затем y и Enter.

Добавление пакетов в Reprepro

Сначала давайте перейдем в расположение для временных пакетов:

mkdir -p /tmp/debs
cd /tmp/debs

Для работы вам понадобятся несколько пакетов.

wget https://github.com/Silvenga/examples/raw/master/example-helloworld_1.0.0.0_amd64.deb
wget https://github.com/Silvenga/examples/raw/master/example-helloworld_1.0.0.0_i386.deb
wget https://github.com/Silvenga/examples/raw/master/example-helloworld_1.0.0.0_amd64.deb
wget https://github.com/Silvenga/examples/raw/master/example-helloworld_1.0.0.0_i386.deb

Команда ls должна выдать такой результат:

ls
example-helloworld_1.0.0.0_amd64.deb  example-helloworld_1.0.0.0_i386.deb

Теперь у вас есть два пакета для работы: один для 32-битных машин (i386), второй – для 64-битных (amd64).

Добавьте их в репозиторий:

reprepro -b /var/repositories includedeb trusty example-helloworld_1.0.0.0_*

Флаг –b указывает базовый каталог репозитория. Команда includedeb требует два аргумента, < distribution code name > и < file path(s) >. Reprepro дважды запросит пароль подключа.

Exporting indices...
C3D099E3A72DB3EF Mark Lopez <mark.lopez@example.com> needs a passphrase
Please enter passphrase: < hidden >
C3D099E3A72DB3EF Mark Lopez <mark.lopez@example.com> needs a passphrase
Please enter passphrase: < hidden >

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

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

reprepro -b /var/repositories/ list trusty
trusty|main|i386: example-helloworld 1.0.0.0
trusty|main|amd64: example-helloworld 1.0.0.0

Чтобы удалить пакет, используйте команду remove и укажите код и имя пакета:

reprepro -b /var/repositories/ remove trusty example-helloworld

3: Настройка публичного репозитория

Итак, теперь у вас есть локальный репозиторий с парой пакетов в нем. Теперь давайте попробуем сделать его доступным для других пользователей.

Для начала нужно установить Nginx:

apt-get update
apt-get install nginx

Nginx предоставляет пример стандартной конфигурации. Скопируйте файл, если хотите иметь доступ к стандартным параметрам в будущем.

mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
touch /etc/nginx/sites-available/default

Теперь нужно настроить Nginx для обслуживания репозитория.

Откройте конфигурационный файл.

nano /etc/nginx/sites-available/default

Добавьте в него такие директивы:

server {
## Let your repository be the root directory
root        /var/repositories;
## Always good to log
access_log  /var/log/nginx/repo.access.log;
error_log   /var/log/nginx/repo.error.log;
## Prevent access to Reprepro's files
location ~ /(db|conf) {
deny        all;
return      404;
}
}

Стандартные параметры Nginx почти подходят. Нужно только настроить root-каталог и заблокировать доступ к файлам Reprepro (обратите внимание на комментарии выше).

Перезапустите Nginx:

service nginx restart

Теперь ваш публичный репозиторий Ubuntu готов.

Чтобы сообщить другим пользователям расположение репозитория, вам понадобится IP-адрес сервера. Если вы не знаете свой IP, используйте ifconfig.

ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 04:01:23:f9:0e:01
inet addr:198.199.114.168  Bcast:198.199.114.255  Mask:255.255.255.0
inet6 addr: fe80::601:23ff:fef9:e01/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:16555 errors:0 dropped:0 overruns:0 frame:0
TX packets:16815 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:7788170 (7.7 MB)  TX bytes:3058446 (3.0 MB)

В этом примере адрес сервера – 198.199.114.168.

Зная IP-адрес сервера Reprepro, вы можете добавить репозиторий на другой сервер.

4: Установка пакетов из репозитория

Перейдите на второй сервер Ubuntu 14.04 LTS, чтобы попробовать добавить ваш новый репозиторий пакетов.

На новом сервере вам нужно загрузить открытый ключ, который проверит пакеты из репозитория. Как помните, мы опубликовали ключ на keyserver.ubuntu.com.

Используйте эту команду:

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 10E6133F

команда загрузит указанный ключ и добавит его в базу данных менеджера apt. Команда adv использует GPG для загрузки ключей. Остальные два аргумента передаются прямо GPG. Поскольку ключ загружен на keyserver.ubuntu.com, используйте директиву —keyserver keyserver.ubuntu.com, чтобы извлечь ключ из этого расположения. Директива —recv-keys <key ID> указывает ключ, который нужно добавить.

Теперь добавьте адрес репозитория, который нужно найти apt-get. Вам потребуется IP-адрес вашего сервера репозитория. Это легко сделать с помощью add-apt-repository.

add-apt-repository "deb http://198.199.114.168/ trusty main"

Обратите внимание на строку, которую нужно передать add-apt-repository. Большинство репозиториев Debian можно добавить в следующем общем формате:

deb (repository location) (current distribution code name)  (the components name)

Расположение хранилища должно совпадать с расположением вашего сервера. У вас есть HTTP-сервер, поэтому можно использовать протокол http://. В данном случае расположение – это 198.199.114.168. Кодовое имя сервера – trusty. Это простой репозиторий, поэтому мы назвали компонент main.

После добавления репозитория обязательно запустите команду apt-get update. Она проверит все известные репозитории на наличие обновлений и изменений (включая тот, который вы только что создали).

apt-get update

Теперь можно установить какой-нибудь пакет из репозитория. Для этого введите:

apt-get install example-helloworld

Если команда сработала успешно, вы получите такой результат:

Hello, World!
This package was successfully installed!

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

Чтобы удалить новый пакет, введите:

apt-get remove example-helloworld

Заключение

Теперь вы умеете создавать репозитории APT с помощью Reprepro и генерировать ключи и сертификаты.

Tags: , , ,